From 9a2c133b42a8646642c8189f7b658267c4b00c70 Mon Sep 17 00:00:00 2001 From: Joao Moura Date: Fri, 7 Aug 2026 14:11:02 -0700 Subject: [PATCH] [docs-freeze] docs: snapshot and changelog for v1.15.13 --- docs/docs.json | 1549 ++++- docs/edge/ar/changelog.mdx | 24 + docs/edge/en/changelog.mdx | 24 + docs/edge/ko/changelog.mdx | 24 + docs/edge/pt-BR/changelog.mdx | 24 + docs/v1.15.13/ar/api-reference/inputs.mdx | 8 + .../ar/api-reference/introduction.mdx | 135 + docs/v1.15.13/ar/api-reference/kickoff.mdx | 8 + docs/v1.15.13/ar/api-reference/resume.mdx | 6 + docs/v1.15.13/ar/api-reference/status.mdx | 6 + docs/v1.15.13/ar/changelog.mdx | 2385 ++++++++ .../ar/concepts/agent-capabilities.mdx | 147 + docs/v1.15.13/ar/concepts/agents.mdx | 383 ++ docs/v1.15.13/ar/concepts/checkpointing.mdx | 423 ++ docs/v1.15.13/ar/concepts/cli.mdx | 302 + docs/v1.15.13/ar/concepts/collaboration.mdx | 363 ++ docs/v1.15.13/ar/concepts/crews.mdx | 247 + docs/v1.15.13/ar/concepts/event-listener.mdx | 237 + docs/v1.15.13/ar/concepts/files.mdx | 267 + docs/v1.15.13/ar/concepts/flows.mdx | 1181 ++++ docs/v1.15.13/ar/concepts/knowledge.mdx | 1095 ++++ docs/v1.15.13/ar/concepts/llms.mdx | 1352 +++++ docs/v1.15.13/ar/concepts/memory.mdx | 878 +++ docs/v1.15.13/ar/concepts/planning.mdx | 155 + docs/v1.15.13/ar/concepts/processes.mdx | 66 + .../ar/concepts/production-architecture.mdx | 162 + docs/v1.15.13/ar/concepts/reasoning.mdx | 148 + docs/v1.15.13/ar/concepts/skills.mdx | 373 ++ docs/v1.15.13/ar/concepts/tasks.mdx | 1120 ++++ docs/v1.15.13/ar/concepts/testing.mdx | 49 + docs/v1.15.13/ar/concepts/tools.mdx | 290 + docs/v1.15.13/ar/concepts/training.mdx | 197 + docs/v1.15.13/ar/examples/cookbooks.mdx | 49 + docs/v1.15.13/ar/examples/example.mdx | 86 + .../guides/advanced/customizing-prompts.mdx | 331 ++ .../ar/guides/advanced/fingerprinting.mdx | 134 + .../agents/crafting-effective-agents.mdx | 453 ++ .../ar/guides/coding-tools/agents-md.mdx | 61 + .../ar/guides/coding-tools/build-with-ai.mdx | 214 + .../guides/concepts/evaluating-use-cases.mdx | 485 ++ docs/v1.15.13/ar/guides/crews/first-crew.mdx | 140 + .../ar/guides/flows/conversational-flows.mdx | 473 ++ docs/v1.15.13/ar/guides/flows/first-flow.mdx | 222 + .../ar/guides/flows/inputs-id-deprecation.mdx | 102 + .../ar/guides/flows/mastering-flow-state.mdx | 228 + .../migration/migrating-from-langgraph.mdx | 103 + .../ar/guides/migration/upgrading-crewai.mdx | 190 + .../ar/guides/tools/publish-custom-tools.mdx | 96 + docs/v1.15.13/ar/index.mdx | 105 + docs/v1.15.13/ar/installation.mdx | 216 + docs/v1.15.13/ar/introduction.mdx | 152 + .../ar/learn/a2a-agent-delegation.mdx | 87 + .../learn/before-and-after-kickoff-hooks.mdx | 47 + .../ar/learn/bring-your-own-agent.mdx | 41 + docs/v1.15.13/ar/learn/coding-agents.mdx | 80 + docs/v1.15.13/ar/learn/conditional-tasks.mdx | 14 + .../v1.15.13/ar/learn/create-custom-tools.mdx | 77 + docs/v1.15.13/ar/learn/custom-llm.mdx | 55 + .../ar/learn/custom-manager-agent.mdx | 81 + docs/v1.15.13/ar/learn/customizing-agents.mdx | 67 + .../ar/learn/dalle-image-generation.mdx | 52 + docs/v1.15.13/ar/learn/execution-hooks.mdx | 86 + .../ar/learn/force-tool-output-as-result.mdx | 45 + .../ar/learn/hierarchical-process.mdx | 76 + .../ar/learn/human-feedback-in-flows.mdx | 98 + docs/v1.15.13/ar/learn/human-in-the-loop.mdx | 80 + .../ar/learn/human-input-on-execution.mdx | 99 + docs/v1.15.13/ar/learn/kickoff-async.mdx | 306 + docs/v1.15.13/ar/learn/kickoff-for-each.mdx | 54 + .../ar/learn/litellm-removal-guide.mdx | 358 ++ docs/v1.15.13/ar/learn/llm-connections.mdx | 214 + docs/v1.15.13/ar/learn/llm-hooks.mdx | 427 ++ .../v1.15.13/ar/learn/llm-selection-guide.mdx | 821 +++ docs/v1.15.13/ar/learn/multimodal-agents.mdx | 141 + docs/v1.15.13/ar/learn/overview.mdx | 159 + .../replay-tasks-from-latest-crew-kickoff.mdx | 79 + docs/v1.15.13/ar/learn/sequential-process.mdx | 128 + .../ar/learn/streaming-crew-execution.mdx | 384 ++ .../ar/learn/streaming-flow-execution.mdx | 479 ++ .../ar/learn/streaming-runtime-contract.mdx | 194 + docs/v1.15.13/ar/learn/tool-hooks.mdx | 480 ++ docs/v1.15.13/ar/learn/using-annotations.mdx | 155 + docs/v1.15.13/ar/mcp/dsl-integration.mdx | 349 ++ docs/v1.15.13/ar/mcp/multiple-servers.mdx | 65 + docs/v1.15.13/ar/mcp/overview.mdx | 690 +++ docs/v1.15.13/ar/mcp/security.mdx | 149 + docs/v1.15.13/ar/mcp/sse.mdx | 151 + docs/v1.15.13/ar/mcp/stdio.mdx | 134 + docs/v1.15.13/ar/mcp/streamable-http.mdx | 136 + .../ar/observability/arize-phoenix.mdx | 150 + docs/v1.15.13/ar/observability/braintrust.mdx | 232 + docs/v1.15.13/ar/observability/datadog.mdx | 109 + docs/v1.15.13/ar/observability/galileo.mdx | 86 + docs/v1.15.13/ar/observability/langdb.mdx | 167 + docs/v1.15.13/ar/observability/langfuse.mdx | 109 + docs/v1.15.13/ar/observability/langtrace.mdx | 73 + docs/v1.15.13/ar/observability/maxim.mdx | 221 + docs/v1.15.13/ar/observability/mlflow.mdx | 206 + docs/v1.15.13/ar/observability/neatlogs.mdx | 134 + docs/v1.15.13/ar/observability/openlit.mdx | 181 + docs/v1.15.13/ar/observability/opik.mdx | 130 + docs/v1.15.13/ar/observability/overview.mdx | 120 + .../ar/observability/patronus-evaluation.mdx | 206 + docs/v1.15.13/ar/observability/portkey.mdx | 823 +++ docs/v1.15.13/ar/observability/tracing.mdx | 214 + .../v1.15.13/ar/observability/truefoundry.mdx | 146 + docs/v1.15.13/ar/observability/weave.mdx | 125 + docs/v1.15.13/ar/quickstart.mdx | 257 + docs/v1.15.13/ar/skills.mdx | 50 + docs/v1.15.13/ar/snippets/snippet-intro.mdx | 1 + docs/v1.15.13/ar/telemetry.mdx | 68 + docs/v1.15.13/ar/tools/ai-ml/aimindtool.mdx | 119 + .../ar/tools/ai-ml/codeinterpretertool.mdx | 214 + docs/v1.15.13/ar/tools/ai-ml/dalletool.mdx | 52 + docs/v1.15.13/ar/tools/ai-ml/daytona.mdx | 230 + .../v1.15.13/ar/tools/ai-ml/langchaintool.mdx | 59 + .../ar/tools/ai-ml/llamaindextool.mdx | 147 + docs/v1.15.13/ar/tools/ai-ml/overview.mdx | 65 + docs/v1.15.13/ar/tools/ai-ml/ragtool.mdx | 654 +++ docs/v1.15.13/ar/tools/ai-ml/visiontool.mdx | 50 + .../ar/tools/automation/apifyactorstool.mdx | 99 + .../ar/tools/automation/composiotool.mdx | 88 + .../ar/tools/automation/multiontool.mdx | 127 + .../v1.15.13/ar/tools/automation/overview.mdx | 60 + .../ar/tools/automation/zapieractionstool.mdx | 59 + .../cloud-storage/bedrockkbretriever.mdx | 166 + .../ar/tools/cloud-storage/overview.mdx | 51 + .../ar/tools/cloud-storage/s3readertool.mdx | 145 + .../ar/tools/cloud-storage/s3writertool.mdx | 151 + .../database-data/mongodbvectorsearchtool.mdx | 167 + .../ar/tools/database-data/mysqltool.mdx | 67 + .../ar/tools/database-data/nl2sqltool.mdx | 170 + .../ar/tools/database-data/overview.mdx | 67 + .../ar/tools/database-data/pgsearchtool.mdx | 80 + .../database-data/qdrantvectorsearchtool.mdx | 344 ++ .../database-data/singlestoresearchtool.mdx | 60 + .../database-data/snowflakesearchtool.mdx | 203 + .../weaviatevectorsearchtool.mdx | 168 + .../ar/tools/file-document/csvsearchtool.mdx | 92 + .../tools/file-document/directoryreadtool.mdx | 52 + .../file-document/directorysearchtool.mdx | 82 + .../ar/tools/file-document/docxsearchtool.mdx | 77 + .../ar/tools/file-document/filereadtool.mdx | 42 + .../ar/tools/file-document/filewritetool.mdx | 51 + .../ar/tools/file-document/jsonsearchtool.mdx | 91 + .../ar/tools/file-document/mdxsearchtool.mdx | 72 + .../ar/tools/file-document/ocrtool.mdx | 88 + .../ar/tools/file-document/overview.mdx | 97 + .../file-document/pdf-text-writing-tool.mdx | 75 + .../ar/tools/file-document/pdfsearchtool.mdx | 123 + .../ar/tools/file-document/txtsearchtool.mdx | 89 + .../ar/tools/file-document/xmlsearchtool.mdx | 74 + .../integration/bedrockinvokeagenttool.mdx | 188 + .../integration/crewaiautomationtool.mdx | 276 + .../integration/mergeagenthandlertool.mdx | 367 ++ .../ar/tools/integration/overview.mdx | 76 + docs/v1.15.13/ar/tools/overview.mdx | 140 + .../tools/search-research/arxivpapertool.mdx | 111 + .../tools/search-research/bravesearchtool.mdx | 314 + .../search-research/codedocssearchtool.mdx | 85 + .../search-research/databricks-query-tool.mdx | 81 + .../tools/search-research/exasearchtool.mdx | 137 + .../search-research/githubsearchtool.mdx | 86 + .../search-research/linkupsearchtool.mdx | 113 + .../ar/tools/search-research/overview.mdx | 94 + .../serpapi-googlesearchtool.mdx | 66 + .../serpapi-googleshoppingtool.mdx | 62 + .../tools/search-research/serperdevtool.mdx | 107 + .../search-research/tavilyextractortool.mdx | 140 + .../search-research/tavilyresearchtool.mdx | 125 + .../search-research/tavilysearchtool.mdx | 125 + .../search-research/websitesearchtool.mdx | 78 + .../youtubechannelsearchtool.mdx | 195 + .../youtubevideosearchtool.mdx | 188 + .../ar/tools/tool-integrations/overview.mdx | 31 + .../tools/web-scraping/brightdata-tools.mdx | 112 + .../web-scraping/browserbaseloadtool.mdx | 51 + .../firecrawlcrawlwebsitetool.mdx | 48 + .../firecrawlscrapewebsitetool.mdx | 44 + .../web-scraping/firecrawlsearchtool.mdx | 42 + .../web-scraping/hyperbrowserloadtool.mdx | 87 + .../ar/tools/web-scraping/overview.mdx | 112 + .../web-scraping/oxylabsscraperstool.mdx | 237 + .../scrapeelementfromwebsitetool.mdx | 140 + .../web-scraping/scrapegraphscrapetool.mdx | 197 + .../tools/web-scraping/scrapewebsitetool.mdx | 48 + .../tools/web-scraping/scrapflyscrapetool.mdx | 221 + .../web-scraping/seleniumscrapingtool.mdx | 196 + .../web-scraping/serperscrapewebsitetool.mdx | 101 + .../ar/tools/web-scraping/spidertool.mdx | 93 + .../ar/tools/web-scraping/stagehandtool.mdx | 245 + docs/v1.15.13/en/api-reference/inputs.mdx | 8 + .../en/api-reference/introduction.mdx | 135 + docs/v1.15.13/en/api-reference/kickoff.mdx | 8 + docs/v1.15.13/en/api-reference/resume.mdx | 6 + docs/v1.15.13/en/api-reference/status.mdx | 6 + docs/v1.15.13/en/changelog.mdx | 4954 ++++++++++++++++ .../en/concepts/agent-capabilities.mdx | 147 + docs/v1.15.13/en/concepts/agents.mdx | 720 +++ docs/v1.15.13/en/concepts/checkpointing.mdx | 423 ++ docs/v1.15.13/en/concepts/cli.mdx | 605 ++ docs/v1.15.13/en/concepts/collaboration.mdx | 363 ++ docs/v1.15.13/en/concepts/crews.mdx | 460 ++ docs/v1.15.13/en/concepts/event-listener.mdx | 415 ++ docs/v1.15.13/en/concepts/files.mdx | 267 + docs/v1.15.13/en/concepts/flows.mdx | 1183 ++++ docs/v1.15.13/en/concepts/knowledge.mdx | 1097 ++++ docs/v1.15.13/en/concepts/llms.mdx | 1500 +++++ docs/v1.15.13/en/concepts/memory.mdx | 885 +++ docs/v1.15.13/en/concepts/planning.mdx | 155 + docs/v1.15.13/en/concepts/processes.mdx | 66 + .../en/concepts/production-architecture.mdx | 162 + docs/v1.15.13/en/concepts/reasoning.mdx | 148 + docs/v1.15.13/en/concepts/skills.mdx | 419 ++ docs/v1.15.13/en/concepts/streaming.mdx | 137 + docs/v1.15.13/en/concepts/tasks.mdx | 1036 ++++ docs/v1.15.13/en/concepts/testing.mdx | 49 + docs/v1.15.13/en/concepts/tools.mdx | 461 ++ docs/v1.15.13/en/concepts/training.mdx | 197 + docs/v1.15.13/en/examples/cookbooks.mdx | 49 + docs/v1.15.13/en/examples/example.mdx | 86 + .../guides/advanced/customizing-prompts.mdx | 331 ++ .../en/guides/advanced/fingerprinting.mdx | 134 + .../agents/crafting-effective-agents.mdx | 453 ++ .../en/guides/coding-tools/agents-md.mdx | 65 + .../en/guides/coding-tools/build-with-ai.mdx | 214 + .../guides/concepts/evaluating-use-cases.mdx | 504 ++ docs/v1.15.13/en/guides/crews/first-crew.mdx | 162 + .../en/guides/flows/conversational-flows.mdx | 540 ++ docs/v1.15.13/en/guides/flows/first-flow.mdx | 552 ++ .../en/guides/flows/inputs-id-deprecation.mdx | 143 + .../en/guides/flows/mastering-flow-state.mdx | 841 +++ .../migration/migrating-from-langgraph.mdx | 518 ++ .../en/guides/migration/upgrading-crewai.mdx | 190 + .../en/guides/tools/publish-custom-tools.mdx | 305 + docs/v1.15.13/en/index.mdx | 159 + docs/v1.15.13/en/installation.mdx | 337 ++ docs/v1.15.13/en/introduction.mdx | 152 + .../en/learn/a2a-agent-delegation.mdx | 550 ++ docs/v1.15.13/en/learn/a2ui.mdx | 344 ++ .../learn/before-and-after-kickoff-hooks.mdx | 62 + .../en/learn/bring-your-own-agent.mdx | 444 ++ docs/v1.15.13/en/learn/coding-agents.mdx | 96 + docs/v1.15.13/en/learn/conditional-tasks.mdx | 90 + docs/v1.15.13/en/learn/consuming-streams.mdx | 177 + .../v1.15.13/en/learn/create-custom-tools.mdx | 229 + docs/v1.15.13/en/learn/custom-llm.mdx | 351 ++ .../en/learn/custom-manager-agent.mdx | 91 + docs/v1.15.13/en/learn/customizing-agents.mdx | 112 + .../en/learn/dalle-image-generation.mdx | 74 + .../en/learn/execution-boundary-hooks.mdx | 187 + docs/v1.15.13/en/learn/execution-hooks.mdx | 281 + .../en/learn/force-tool-output-as-result.mdx | 51 + .../en/learn/hierarchical-process.mdx | 113 + .../en/learn/human-feedback-in-flows.mdx | 707 +++ docs/v1.15.13/en/learn/human-in-the-loop.mdx | 159 + .../en/learn/human-input-on-execution.mdx | 99 + docs/v1.15.13/en/learn/kickoff-async.mdx | 306 + docs/v1.15.13/en/learn/kickoff-for-each.mdx | 54 + .../en/learn/litellm-removal-guide.mdx | 449 ++ docs/v1.15.13/en/learn/llm-connections.mdx | 214 + docs/v1.15.13/en/learn/llm-hooks.mdx | 282 + .../v1.15.13/en/learn/llm-selection-guide.mdx | 824 +++ docs/v1.15.13/en/learn/multimodal-agents.mdx | 141 + docs/v1.15.13/en/learn/overview.mdx | 159 + .../replay-tasks-from-latest-crew-kickoff.mdx | 79 + docs/v1.15.13/en/learn/sequential-process.mdx | 128 + docs/v1.15.13/en/learn/step-hooks.mdx | 142 + .../en/learn/streaming-crew-execution.mdx | 384 ++ .../en/learn/streaming-flow-execution.mdx | 479 ++ .../en/learn/streaming-runtime-contract.mdx | 194 + docs/v1.15.13/en/learn/tool-hooks.mdx | 340 ++ docs/v1.15.13/en/learn/using-annotations.mdx | 155 + docs/v1.15.13/en/mcp/dsl-integration.mdx | 349 ++ docs/v1.15.13/en/mcp/multiple-servers.mdx | 65 + docs/v1.15.13/en/mcp/overview.mdx | 724 +++ docs/v1.15.13/en/mcp/security.mdx | 167 + docs/v1.15.13/en/mcp/sse.mdx | 151 + docs/v1.15.13/en/mcp/stdio.mdx | 135 + docs/v1.15.13/en/mcp/streamable-http.mdx | 136 + .../en/observability/arize-phoenix.mdx | 152 + docs/v1.15.13/en/observability/braintrust.mdx | 237 + docs/v1.15.13/en/observability/datadog.mdx | 109 + docs/v1.15.13/en/observability/galileo.mdx | 115 + docs/v1.15.13/en/observability/langdb.mdx | 287 + docs/v1.15.13/en/observability/langfuse.mdx | 112 + docs/v1.15.13/en/observability/langtrace.mdx | 73 + docs/v1.15.13/en/observability/maxim.mdx | 232 + docs/v1.15.13/en/observability/mlflow.mdx | 207 + docs/v1.15.13/en/observability/neatlogs.mdx | 134 + docs/v1.15.13/en/observability/openlit.mdx | 182 + docs/v1.15.13/en/observability/opik.mdx | 130 + docs/v1.15.13/en/observability/overview.mdx | 120 + .../en/observability/patronus-evaluation.mdx | 206 + docs/v1.15.13/en/observability/portkey.mdx | 823 +++ docs/v1.15.13/en/observability/tracing.mdx | 214 + .../v1.15.13/en/observability/truefoundry.mdx | 147 + docs/v1.15.13/en/observability/weave.mdx | 125 + docs/v1.15.13/en/quickstart.mdx | 260 + docs/v1.15.13/en/skills.mdx | 50 + docs/v1.15.13/en/snippets/snippet-intro.mdx | 4 + docs/v1.15.13/en/telemetry.mdx | 68 + docs/v1.15.13/en/tools/ai-ml/aimindtool.mdx | 119 + .../en/tools/ai-ml/codeinterpretertool.mdx | 214 + docs/v1.15.13/en/tools/ai-ml/dalletool.mdx | 52 + docs/v1.15.13/en/tools/ai-ml/daytona.mdx | 230 + .../en/tools/ai-ml/e2bsandboxtools.mdx | 196 + .../v1.15.13/en/tools/ai-ml/langchaintool.mdx | 59 + .../en/tools/ai-ml/llamaindextool.mdx | 147 + docs/v1.15.13/en/tools/ai-ml/overview.mdx | 65 + docs/v1.15.13/en/tools/ai-ml/ragtool.mdx | 654 +++ docs/v1.15.13/en/tools/ai-ml/visiontool.mdx | 50 + .../en/tools/automation/apifyactorstool.mdx | 100 + .../en/tools/automation/composiotool.mdx | 88 + .../en/tools/automation/multiontool.mdx | 127 + .../v1.15.13/en/tools/automation/overview.mdx | 64 + .../v1.15.13/en/tools/automation/waittool.mdx | 124 + .../en/tools/automation/zapieractionstool.mdx | 59 + .../cloud-storage/bedrockkbretriever.mdx | 166 + .../en/tools/cloud-storage/overview.mdx | 51 + .../en/tools/cloud-storage/s3readertool.mdx | 145 + .../en/tools/cloud-storage/s3writertool.mdx | 151 + .../en/tools/database-data/db2searchtool.mdx | 211 + .../database-data/mongodbvectorsearchtool.mdx | 169 + .../en/tools/database-data/mysqltool.mdx | 70 + .../en/tools/database-data/nl2sqltool.mdx | 175 + .../en/tools/database-data/overview.mdx | 66 + .../en/tools/database-data/pgsearchtool.mdx | 83 + .../database-data/qdrantvectorsearchtool.mdx | 343 ++ .../database-data/singlestoresearchtool.mdx | 62 + .../database-data/snowflakesearchtool.mdx | 203 + .../weaviatevectorsearchtool.mdx | 169 + .../en/tools/file-document/csvsearchtool.mdx | 94 + .../tools/file-document/directoryreadtool.mdx | 54 + .../file-document/directorysearchtool.mdx | 82 + .../en/tools/file-document/docxsearchtool.mdx | 80 + .../en/tools/file-document/filereadtool.mdx | 80 + .../en/tools/file-document/filewritetool.mdx | 81 + .../en/tools/file-document/jsonsearchtool.mdx | 92 + .../en/tools/file-document/mdxsearchtool.mdx | 72 + .../en/tools/file-document/ocrtool.mdx | 90 + .../en/tools/file-document/overview.mdx | 97 + .../file-document/pdf-text-writing-tool.mdx | 77 + .../en/tools/file-document/pdfsearchtool.mdx | 124 + .../en/tools/file-document/txtsearchtool.mdx | 97 + .../en/tools/file-document/xmlsearchtool.mdx | 78 + .../integration/bedrockinvokeagenttool.mdx | 188 + .../integration/crewaiautomationtool.mdx | 276 + .../integration/mergeagenthandlertool.mdx | 367 ++ .../en/tools/integration/overview.mdx | 76 + docs/v1.15.13/en/tools/overview.mdx | 145 + .../tools/search-research/arxivpapertool.mdx | 113 + .../tools/search-research/bravesearchtool.mdx | 316 + .../search-research/codedocssearchtool.mdx | 85 + .../search-research/databricks-query-tool.mdx | 81 + .../tools/search-research/exasearchtool.mdx | 152 + .../search-research/githubsearchtool.mdx | 86 + .../search-research/linkupsearchtool.mdx | 113 + .../en/tools/search-research/overview.mdx | 120 + .../serpapi-googlesearchtool.mdx | 66 + .../serpapi-googleshoppingtool.mdx | 62 + .../tools/search-research/serperdevtool.mdx | 107 + .../search-research/tavilyextractortool.mdx | 140 + .../search-research/tavilygetresearchtool.mdx | 85 + .../search-research/tavilyresearchtool.mdx | 125 + .../search-research/tavilysearchtool.mdx | 125 + .../search-research/websitesearchtool.mdx | 78 + .../en/tools/search-research/youai-search.mdx | 176 + .../youtubechannelsearchtool.mdx | 195 + .../youtubevideosearchtool.mdx | 188 + .../en/tools/tool-integrations/overview.mdx | 31 + .../tools/web-scraping/brightdata-tools.mdx | 112 + .../web-scraping/browserbaseloadtool.mdx | 51 + .../firecrawlcrawlwebsitetool.mdx | 48 + .../firecrawlscrapewebsitetool.mdx | 44 + .../web-scraping/firecrawlsearchtool.mdx | 42 + .../web-scraping/hyperbrowserloadtool.mdx | 87 + .../en/tools/web-scraping/overview.mdx | 112 + .../web-scraping/oxylabsscraperstool.mdx | 237 + .../scrapeelementfromwebsitetool.mdx | 140 + .../web-scraping/scrapegraphscrapetool.mdx | 197 + .../tools/web-scraping/scrapewebsitetool.mdx | 48 + .../tools/web-scraping/scrapflyscrapetool.mdx | 221 + .../web-scraping/seleniumscrapingtool.mdx | 196 + .../web-scraping/serperscrapewebsitetool.mdx | 101 + .../en/tools/web-scraping/spidertool.mdx | 93 + .../en/tools/web-scraping/stagehandtool.mdx | 245 + .../en/tools/web-scraping/youai-contents.mdx | 212 + docs/v1.15.13/enterprise-api.base.yaml | 570 ++ docs/v1.15.13/enterprise-api.en.yaml | 570 ++ docs/v1.15.13/enterprise-api.ko.yaml | 358 ++ docs/v1.15.13/enterprise-api.pt-BR.yaml | 395 ++ docs/v1.15.13/ko/api-reference/inputs.mdx | 8 + .../ko/api-reference/introduction.mdx | 135 + docs/v1.15.13/ko/api-reference/kickoff.mdx | 8 + docs/v1.15.13/ko/api-reference/resume.mdx | 6 + docs/v1.15.13/ko/api-reference/status.mdx | 6 + docs/v1.15.13/ko/changelog.mdx | 5083 ++++++++++++++++ .../ko/concepts/agent-capabilities.mdx | 147 + docs/v1.15.13/ko/concepts/agents.mdx | 716 +++ docs/v1.15.13/ko/concepts/checkpointing.mdx | 423 ++ docs/v1.15.13/ko/concepts/cli.mdx | 441 ++ docs/v1.15.13/ko/concepts/collaboration.mdx | 363 ++ docs/v1.15.13/ko/concepts/crews.mdx | 462 ++ docs/v1.15.13/ko/concepts/event-listener.mdx | 415 ++ docs/v1.15.13/ko/concepts/files.mdx | 267 + docs/v1.15.13/ko/concepts/flows.mdx | 1075 ++++ docs/v1.15.13/ko/concepts/knowledge.mdx | 962 ++++ docs/v1.15.13/ko/concepts/llms.mdx | 1008 ++++ docs/v1.15.13/ko/concepts/memory.mdx | 878 +++ docs/v1.15.13/ko/concepts/planning.mdx | 153 + docs/v1.15.13/ko/concepts/processes.mdx | 66 + .../ko/concepts/production-architecture.mdx | 162 + docs/v1.15.13/ko/concepts/reasoning.mdx | 148 + docs/v1.15.13/ko/concepts/skills.mdx | 373 ++ docs/v1.15.13/ko/concepts/tasks.mdx | 938 +++ docs/v1.15.13/ko/concepts/testing.mdx | 49 + docs/v1.15.13/ko/concepts/tools.mdx | 287 + docs/v1.15.13/ko/concepts/training.mdx | 132 + docs/v1.15.13/ko/examples/cookbooks.mdx | 23 + docs/v1.15.13/ko/examples/example.mdx | 86 + .../guides/advanced/customizing-prompts.mdx | 331 ++ .../ko/guides/advanced/fingerprinting.mdx | 134 + .../agents/crafting-effective-agents.mdx | 454 ++ .../ko/guides/coding-tools/agents-md.mdx | 61 + .../ko/guides/coding-tools/build-with-ai.mdx | 214 + .../guides/concepts/evaluating-use-cases.mdx | 504 ++ docs/v1.15.13/ko/guides/crews/first-crew.mdx | 140 + .../ko/guides/flows/conversational-flows.mdx | 474 ++ docs/v1.15.13/ko/guides/flows/first-flow.mdx | 550 ++ .../ko/guides/flows/inputs-id-deprecation.mdx | 125 + .../ko/guides/flows/mastering-flow-state.mdx | 815 +++ .../migration/migrating-from-langgraph.mdx | 518 ++ .../ko/guides/migration/upgrading-crewai.mdx | 190 + .../ko/guides/tools/publish-custom-tools.mdx | 244 + docs/v1.15.13/ko/index.mdx | 102 + docs/v1.15.13/ko/installation.mdx | 209 + docs/v1.15.13/ko/introduction.mdx | 152 + .../learn/before-and-after-kickoff-hooks.mdx | 61 + .../ko/learn/bring-your-own-agent.mdx | 440 ++ docs/v1.15.13/ko/learn/coding-agents.mdx | 96 + docs/v1.15.13/ko/learn/conditional-tasks.mdx | 90 + .../v1.15.13/ko/learn/create-custom-tools.mdx | 121 + docs/v1.15.13/ko/learn/custom-llm.mdx | 351 ++ .../ko/learn/custom-manager-agent.mdx | 91 + docs/v1.15.13/ko/learn/customizing-agents.mdx | 111 + .../ko/learn/dalle-image-generation.mdx | 74 + docs/v1.15.13/ko/learn/execution-hooks.mdx | 379 ++ .../ko/learn/force-tool-output-as-result.mdx | 51 + .../ko/learn/hierarchical-process.mdx | 110 + .../ko/learn/human-feedback-in-flows.mdx | 697 +++ docs/v1.15.13/ko/learn/human-in-the-loop.mdx | 120 + .../ko/learn/human-input-on-execution.mdx | 99 + docs/v1.15.13/ko/learn/kickoff-async.mdx | 306 + docs/v1.15.13/ko/learn/kickoff-for-each.mdx | 54 + docs/v1.15.13/ko/learn/llm-connections.mdx | 214 + docs/v1.15.13/ko/learn/llm-hooks.mdx | 412 ++ .../v1.15.13/ko/learn/llm-selection-guide.mdx | 815 +++ docs/v1.15.13/ko/learn/multimodal-agents.mdx | 141 + docs/v1.15.13/ko/learn/overview.mdx | 159 + .../replay-tasks-from-latest-crew-kickoff.mdx | 79 + docs/v1.15.13/ko/learn/sequential-process.mdx | 128 + .../ko/learn/streaming-crew-execution.mdx | 384 ++ .../ko/learn/streaming-runtime-contract.mdx | 194 + docs/v1.15.13/ko/learn/tool-hooks.mdx | 498 ++ docs/v1.15.13/ko/learn/using-annotations.mdx | 155 + docs/v1.15.13/ko/mcp/dsl-integration.mdx | 234 + docs/v1.15.13/ko/mcp/multiple-servers.mdx | 65 + docs/v1.15.13/ko/mcp/overview.mdx | 341 ++ docs/v1.15.13/ko/mcp/security.mdx | 166 + docs/v1.15.13/ko/mcp/sse.mdx | 151 + docs/v1.15.13/ko/mcp/stdio.mdx | 135 + docs/v1.15.13/ko/mcp/streamable-http.mdx | 136 + .../ko/observability/arize-phoenix.mdx | 150 + docs/v1.15.13/ko/observability/braintrust.mdx | 236 + docs/v1.15.13/ko/observability/datadog.mdx | 109 + docs/v1.15.13/ko/observability/galileo.mdx | 115 + docs/v1.15.13/ko/observability/langdb.mdx | 285 + docs/v1.15.13/ko/observability/langfuse.mdx | 110 + docs/v1.15.13/ko/observability/langtrace.mdx | 73 + docs/v1.15.13/ko/observability/maxim.mdx | 227 + docs/v1.15.13/ko/observability/mlflow.mdx | 206 + docs/v1.15.13/ko/observability/neatlogs.mdx | 129 + docs/v1.15.13/ko/observability/openlit.mdx | 181 + docs/v1.15.13/ko/observability/opik.mdx | 131 + docs/v1.15.13/ko/observability/overview.mdx | 120 + .../ko/observability/patronus-evaluation.mdx | 206 + docs/v1.15.13/ko/observability/portkey.mdx | 821 +++ docs/v1.15.13/ko/observability/tracing.mdx | 214 + .../v1.15.13/ko/observability/truefoundry.mdx | 147 + docs/v1.15.13/ko/observability/weave.mdx | 125 + docs/v1.15.13/ko/quickstart.mdx | 257 + docs/v1.15.13/ko/skills.mdx | 50 + docs/v1.15.13/ko/snippets/snippet-intro.mdx | 1 + docs/v1.15.13/ko/telemetry.mdx | 67 + docs/v1.15.13/ko/tools/ai-ml/aimindtool.mdx | 119 + .../ko/tools/ai-ml/codeinterpretertool.mdx | 213 + docs/v1.15.13/ko/tools/ai-ml/dalletool.mdx | 51 + docs/v1.15.13/ko/tools/ai-ml/daytona.mdx | 230 + .../v1.15.13/ko/tools/ai-ml/langchaintool.mdx | 57 + .../ko/tools/ai-ml/llamaindextool.mdx | 147 + docs/v1.15.13/ko/tools/ai-ml/overview.mdx | 64 + docs/v1.15.13/ko/tools/ai-ml/ragtool.mdx | 173 + docs/v1.15.13/ko/tools/ai-ml/visiontool.mdx | 50 + .../ko/tools/automation/apifyactorstool.mdx | 100 + .../ko/tools/automation/composiotool.mdx | 88 + .../ko/tools/automation/multiontool.mdx | 127 + .../v1.15.13/ko/tools/automation/overview.mdx | 60 + .../ko/tools/automation/zapieractionstool.mdx | 57 + .../cloud-storage/bedrockkbretriever.mdx | 166 + .../ko/tools/cloud-storage/overview.mdx | 52 + .../ko/tools/cloud-storage/s3readertool.mdx | 145 + .../ko/tools/cloud-storage/s3writertool.mdx | 151 + .../database-data/mongodbvectorsearchtool.mdx | 167 + .../ko/tools/database-data/mysqltool.mdx | 70 + .../ko/tools/database-data/nl2sqltool.mdx | 146 + .../ko/tools/database-data/overview.mdx | 67 + .../ko/tools/database-data/pgsearchtool.mdx | 83 + .../database-data/qdrantvectorsearchtool.mdx | 344 ++ .../database-data/singlestoresearchtool.mdx | 60 + .../database-data/snowflakesearchtool.mdx | 203 + .../weaviatevectorsearchtool.mdx | 163 + .../ko/tools/file-document/csvsearchtool.mdx | 94 + .../tools/file-document/directoryreadtool.mdx | 53 + .../file-document/directorysearchtool.mdx | 82 + .../ko/tools/file-document/docxsearchtool.mdx | 80 + .../ko/tools/file-document/filereadtool.mdx | 44 + .../ko/tools/file-document/filewritetool.mdx | 55 + .../ko/tools/file-document/jsonsearchtool.mdx | 89 + .../ko/tools/file-document/mdxsearchtool.mdx | 72 + .../ko/tools/file-document/ocrtool.mdx | 88 + .../ko/tools/file-document/overview.mdx | 97 + .../file-document/pdf-text-writing-tool.mdx | 75 + .../ko/tools/file-document/pdfsearchtool.mdx | 120 + .../ko/tools/file-document/txtsearchtool.mdx | 90 + .../ko/tools/file-document/xmlsearchtool.mdx | 78 + .../integration/bedrockinvokeagenttool.mdx | 188 + .../integration/crewaiautomationtool.mdx | 276 + .../ko/tools/integration/overview.mdx | 72 + docs/v1.15.13/ko/tools/overview.mdx | 130 + .../tools/search-research/arxivpapertool.mdx | 111 + .../tools/search-research/bravesearchtool.mdx | 97 + .../search-research/codedocssearchtool.mdx | 85 + .../search-research/databricks-query-tool.mdx | 79 + .../tools/search-research/exasearchtool.mdx | 81 + .../search-research/githubsearchtool.mdx | 86 + .../search-research/linkupsearchtool.mdx | 113 + .../ko/tools/search-research/overview.mdx | 94 + .../serpapi-googlesearchtool.mdx | 64 + .../serpapi-googleshoppingtool.mdx | 60 + .../tools/search-research/serperdevtool.mdx | 106 + .../search-research/tavilyextractortool.mdx | 140 + .../search-research/tavilyresearchtool.mdx | 125 + .../search-research/tavilysearchtool.mdx | 125 + .../search-research/websitesearchtool.mdx | 78 + .../youtubechannelsearchtool.mdx | 195 + .../youtubevideosearchtool.mdx | 188 + .../ko/tools/tool-integrations/overview.mdx | 30 + .../tools/web-scraping/brightdata-tools.mdx | 110 + .../web-scraping/browserbaseloadtool.mdx | 51 + .../firecrawlcrawlwebsitetool.mdx | 48 + .../firecrawlscrapewebsitetool.mdx | 44 + .../web-scraping/firecrawlsearchtool.mdx | 42 + .../web-scraping/hyperbrowserloadtool.mdx | 87 + .../ko/tools/web-scraping/overview.mdx | 112 + .../web-scraping/oxylabsscraperstool.mdx | 236 + .../scrapeelementfromwebsitetool.mdx | 140 + .../web-scraping/scrapegraphscrapetool.mdx | 197 + .../tools/web-scraping/scrapewebsitetool.mdx | 48 + .../tools/web-scraping/scrapflyscrapetool.mdx | 221 + .../web-scraping/seleniumscrapingtool.mdx | 196 + .../web-scraping/serperscrapewebsitetool.mdx | 101 + .../ko/tools/web-scraping/spidertool.mdx | 92 + .../ko/tools/web-scraping/stagehandtool.mdx | 242 + docs/v1.15.13/pt-BR/api-reference/inputs.mdx | 8 + .../pt-BR/api-reference/introduction.mdx | 135 + docs/v1.15.13/pt-BR/api-reference/kickoff.mdx | 8 + docs/v1.15.13/pt-BR/api-reference/resume.mdx | 6 + docs/v1.15.13/pt-BR/api-reference/status.mdx | 6 + docs/v1.15.13/pt-BR/changelog.mdx | 5116 +++++++++++++++++ .../pt-BR/concepts/agent-capabilities.mdx | 147 + docs/v1.15.13/pt-BR/concepts/agents.mdx | 659 +++ .../v1.15.13/pt-BR/concepts/checkpointing.mdx | 423 ++ docs/v1.15.13/pt-BR/concepts/cli.mdx | 464 ++ .../v1.15.13/pt-BR/concepts/collaboration.mdx | 361 ++ docs/v1.15.13/pt-BR/concepts/crews.mdx | 460 ++ .../pt-BR/concepts/event-listener.mdx | 415 ++ docs/v1.15.13/pt-BR/concepts/files.mdx | 267 + docs/v1.15.13/pt-BR/concepts/flows.mdx | 1073 ++++ docs/v1.15.13/pt-BR/concepts/knowledge.mdx | 1060 ++++ docs/v1.15.13/pt-BR/concepts/llms.mdx | 932 +++ docs/v1.15.13/pt-BR/concepts/memory.mdx | 878 +++ docs/v1.15.13/pt-BR/concepts/planning.mdx | 153 + docs/v1.15.13/pt-BR/concepts/processes.mdx | 66 + .../concepts/production-architecture.mdx | 162 + docs/v1.15.13/pt-BR/concepts/reasoning.mdx | 148 + docs/v1.15.13/pt-BR/concepts/skills.mdx | 373 ++ docs/v1.15.13/pt-BR/concepts/tasks.mdx | 1105 ++++ docs/v1.15.13/pt-BR/concepts/testing.mdx | 49 + docs/v1.15.13/pt-BR/concepts/tools.mdx | 292 + docs/v1.15.13/pt-BR/concepts/training.mdx | 66 + docs/v1.15.13/pt-BR/examples/cookbooks.mdx | 23 + docs/v1.15.13/pt-BR/examples/example.mdx | 86 + .../guides/advanced/customizing-prompts.mdx | 331 ++ .../pt-BR/guides/advanced/fingerprinting.mdx | 134 + .../agents/crafting-effective-agents.mdx | 453 ++ .../pt-BR/guides/coding-tools/agents-md.mdx | 61 + .../guides/coding-tools/build-with-ai.mdx | 214 + .../guides/concepts/evaluating-use-cases.mdx | 504 ++ .../pt-BR/guides/crews/first-crew.mdx | 142 + .../guides/flows/conversational-flows.mdx | 475 ++ .../pt-BR/guides/flows/first-flow.mdx | 550 ++ .../guides/flows/inputs-id-deprecation.mdx | 142 + .../guides/flows/mastering-flow-state.mdx | 815 +++ .../migration/migrating-from-langgraph.mdx | 518 ++ .../guides/migration/upgrading-crewai.mdx | 190 + .../guides/tools/publish-custom-tools.mdx | 244 + docs/v1.15.13/pt-BR/index.mdx | 102 + docs/v1.15.13/pt-BR/installation.mdx | 216 + docs/v1.15.13/pt-BR/introduction.mdx | 152 + .../learn/before-and-after-kickoff-hooks.mdx | 61 + .../pt-BR/learn/bring-your-own-agent.mdx | 442 ++ docs/v1.15.13/pt-BR/learn/coding-agents.mdx | 96 + .../pt-BR/learn/conditional-tasks.mdx | 90 + .../pt-BR/learn/create-custom-tools.mdx | 124 + docs/v1.15.13/pt-BR/learn/custom-llm.mdx | 123 + .../pt-BR/learn/custom-manager-agent.mdx | 91 + .../pt-BR/learn/customizing-agents.mdx | 107 + .../pt-BR/learn/dalle-image-generation.mdx | 74 + docs/v1.15.13/pt-BR/learn/execution-hooks.mdx | 379 ++ .../learn/force-tool-output-as-result.mdx | 51 + .../pt-BR/learn/hierarchical-process.mdx | 112 + .../pt-BR/learn/human-feedback-in-flows.mdx | 697 +++ .../pt-BR/learn/human-in-the-loop.mdx | 120 + .../pt-BR/learn/human-input-on-execution.mdx | 99 + docs/v1.15.13/pt-BR/learn/kickoff-async.mdx | 306 + .../v1.15.13/pt-BR/learn/kickoff-for-each.mdx | 54 + docs/v1.15.13/pt-BR/learn/llm-connections.mdx | 213 + docs/v1.15.13/pt-BR/learn/llm-hooks.mdx | 388 ++ .../pt-BR/learn/llm-selection-guide.mdx | 815 +++ .../pt-BR/learn/multimodal-agents.mdx | 141 + docs/v1.15.13/pt-BR/learn/overview.mdx | 159 + .../replay-tasks-from-latest-crew-kickoff.mdx | 79 + .../pt-BR/learn/sequential-process.mdx | 128 + .../pt-BR/learn/streaming-crew-execution.mdx | 384 ++ .../learn/streaming-runtime-contract.mdx | 194 + docs/v1.15.13/pt-BR/learn/tool-hooks.mdx | 498 ++ .../pt-BR/learn/using-annotations.mdx | 155 + docs/v1.15.13/pt-BR/mcp/dsl-integration.mdx | 234 + docs/v1.15.13/pt-BR/mcp/multiple-servers.mdx | 65 + docs/v1.15.13/pt-BR/mcp/overview.mdx | 329 ++ docs/v1.15.13/pt-BR/mcp/security.mdx | 166 + docs/v1.15.13/pt-BR/mcp/sse.mdx | 151 + docs/v1.15.13/pt-BR/mcp/stdio.mdx | 134 + docs/v1.15.13/pt-BR/mcp/streamable-http.mdx | 136 + .../pt-BR/observability/arize-phoenix.mdx | 145 + .../pt-BR/observability/braintrust.mdx | 237 + docs/v1.15.13/pt-BR/observability/datadog.mdx | 108 + docs/v1.15.13/pt-BR/observability/galileo.mdx | 115 + docs/v1.15.13/pt-BR/observability/langdb.mdx | 287 + .../v1.15.13/pt-BR/observability/langfuse.mdx | 108 + .../pt-BR/observability/langtrace.mdx | 73 + docs/v1.15.13/pt-BR/observability/maxim.mdx | 149 + docs/v1.15.13/pt-BR/observability/mlflow.mdx | 186 + .../v1.15.13/pt-BR/observability/neatlogs.mdx | 134 + docs/v1.15.13/pt-BR/observability/openlit.mdx | 181 + docs/v1.15.13/pt-BR/observability/opik.mdx | 130 + .../v1.15.13/pt-BR/observability/overview.mdx | 120 + .../observability/patronus-evaluation.mdx | 206 + docs/v1.15.13/pt-BR/observability/portkey.mdx | 823 +++ docs/v1.15.13/pt-BR/observability/tracing.mdx | 214 + .../pt-BR/observability/truefoundry.mdx | 146 + docs/v1.15.13/pt-BR/observability/weave.mdx | 125 + docs/v1.15.13/pt-BR/quickstart.mdx | 257 + docs/v1.15.13/pt-BR/skills.mdx | 50 + .../v1.15.13/pt-BR/snippets/snippet-intro.mdx | 1 + docs/v1.15.13/pt-BR/telemetry.mdx | 68 + .../v1.15.13/pt-BR/tools/ai-ml/aimindtool.mdx | 119 + .../pt-BR/tools/ai-ml/codeinterpretertool.mdx | 214 + docs/v1.15.13/pt-BR/tools/ai-ml/dalletool.mdx | 52 + docs/v1.15.13/pt-BR/tools/ai-ml/daytona.mdx | 230 + .../pt-BR/tools/ai-ml/langchaintool.mdx | 58 + .../pt-BR/tools/ai-ml/llamaindextool.mdx | 147 + docs/v1.15.13/pt-BR/tools/ai-ml/overview.mdx | 66 + docs/v1.15.13/pt-BR/tools/ai-ml/ragtool.mdx | 173 + .../v1.15.13/pt-BR/tools/ai-ml/visiontool.mdx | 50 + .../tools/automation/apifyactorstool.mdx | 100 + .../pt-BR/tools/automation/composiotool.mdx | 88 + .../pt-BR/tools/automation/multiontool.mdx | 127 + .../pt-BR/tools/automation/overview.mdx | 56 + .../tools/automation/zapieractionstool.mdx | 57 + .../cloud-storage/bedrockkbretriever.mdx | 166 + .../pt-BR/tools/cloud-storage/overview.mdx | 52 + .../tools/cloud-storage/s3readertool.mdx | 145 + .../tools/cloud-storage/s3writertool.mdx | 151 + .../database-data/mongodbvectorsearchtool.mdx | 167 + .../pt-BR/tools/database-data/mysqltool.mdx | 70 + .../pt-BR/tools/database-data/nl2sqltool.mdx | 145 + .../pt-BR/tools/database-data/overview.mdx | 59 + .../tools/database-data/pgsearchtool.mdx | 83 + .../database-data/qdrantvectorsearchtool.mdx | 344 ++ .../database-data/singlestoresearchtool.mdx | 60 + .../database-data/snowflakesearchtool.mdx | 203 + .../weaviatevectorsearchtool.mdx | 163 + .../tools/file-document/csvsearchtool.mdx | 94 + .../tools/file-document/directoryreadtool.mdx | 54 + .../file-document/directorysearchtool.mdx | 82 + .../tools/file-document/docxsearchtool.mdx | 80 + .../tools/file-document/filereadtool.mdx | 44 + .../tools/file-document/filewritetool.mdx | 55 + .../tools/file-document/jsonsearchtool.mdx | 92 + .../tools/file-document/mdxsearchtool.mdx | 72 + .../pt-BR/tools/file-document/ocrtool.mdx | 88 + .../pt-BR/tools/file-document/overview.mdx | 89 + .../file-document/pdf-text-writing-tool.mdx | 75 + .../tools/file-document/pdfsearchtool.mdx | 120 + .../tools/file-document/txtsearchtool.mdx | 95 + .../tools/file-document/xmlsearchtool.mdx | 78 + .../integration/bedrockinvokeagenttool.mdx | 188 + .../integration/crewaiautomationtool.mdx | 276 + .../pt-BR/tools/integration/overview.mdx | 72 + docs/v1.15.13/pt-BR/tools/overview.mdx | 130 + .../tools/search-research/arxivpapertool.mdx | 111 + .../tools/search-research/bravesearchtool.mdx | 97 + .../search-research/codedocssearchtool.mdx | 85 + .../search-research/databricks-query-tool.mdx | 79 + .../tools/search-research/exasearchtool.mdx | 81 + .../search-research/githubsearchtool.mdx | 85 + .../search-research/linkupsearchtool.mdx | 53 + .../pt-BR/tools/search-research/overview.mdx | 72 + .../serpapi-googlesearchtool.mdx | 64 + .../serpapi-googleshoppingtool.mdx | 60 + .../tools/search-research/serperdevtool.mdx | 113 + .../search-research/tavilyextractortool.mdx | 140 + .../search-research/tavilyresearchtool.mdx | 125 + .../search-research/tavilysearchtool.mdx | 125 + .../search-research/websitesearchtool.mdx | 78 + .../youtubechannelsearchtool.mdx | 195 + .../youtubevideosearchtool.mdx | 188 + .../tools/tool-integrations/overview.mdx | 30 + .../tools/web-scraping/brightdata-tools.mdx | 110 + .../web-scraping/browserbaseloadtool.mdx | 51 + .../firecrawlcrawlwebsitetool.mdx | 48 + .../firecrawlscrapewebsitetool.mdx | 44 + .../web-scraping/firecrawlsearchtool.mdx | 42 + .../web-scraping/hyperbrowserloadtool.mdx | 87 + .../pt-BR/tools/web-scraping/overview.mdx | 108 + .../web-scraping/oxylabsscraperstool.mdx | 236 + .../scrapeelementfromwebsitetool.mdx | 140 + .../web-scraping/scrapegraphscrapetool.mdx | 197 + .../tools/web-scraping/scrapewebsitetool.mdx | 48 + .../tools/web-scraping/scrapflyscrapetool.mdx | 221 + .../web-scraping/seleniumscrapingtool.mdx | 196 + .../web-scraping/serperscrapewebsitetool.mdx | 101 + .../pt-BR/tools/web-scraping/spidertool.mdx | 92 + .../tools/web-scraping/stagehandtool.mdx | 242 + 756 files changed, 168629 insertions(+), 34 deletions(-) create mode 100644 docs/v1.15.13/ar/api-reference/inputs.mdx create mode 100644 docs/v1.15.13/ar/api-reference/introduction.mdx create mode 100644 docs/v1.15.13/ar/api-reference/kickoff.mdx create mode 100644 docs/v1.15.13/ar/api-reference/resume.mdx create mode 100644 docs/v1.15.13/ar/api-reference/status.mdx create mode 100644 docs/v1.15.13/ar/changelog.mdx create mode 100644 docs/v1.15.13/ar/concepts/agent-capabilities.mdx create mode 100644 docs/v1.15.13/ar/concepts/agents.mdx create mode 100644 docs/v1.15.13/ar/concepts/checkpointing.mdx create mode 100644 docs/v1.15.13/ar/concepts/cli.mdx create mode 100644 docs/v1.15.13/ar/concepts/collaboration.mdx create mode 100644 docs/v1.15.13/ar/concepts/crews.mdx create mode 100644 docs/v1.15.13/ar/concepts/event-listener.mdx create mode 100644 docs/v1.15.13/ar/concepts/files.mdx create mode 100644 docs/v1.15.13/ar/concepts/flows.mdx create mode 100644 docs/v1.15.13/ar/concepts/knowledge.mdx create mode 100644 docs/v1.15.13/ar/concepts/llms.mdx create mode 100644 docs/v1.15.13/ar/concepts/memory.mdx create mode 100644 docs/v1.15.13/ar/concepts/planning.mdx create mode 100644 docs/v1.15.13/ar/concepts/processes.mdx create mode 100644 docs/v1.15.13/ar/concepts/production-architecture.mdx create mode 100644 docs/v1.15.13/ar/concepts/reasoning.mdx create mode 100644 docs/v1.15.13/ar/concepts/skills.mdx create mode 100644 docs/v1.15.13/ar/concepts/tasks.mdx create mode 100644 docs/v1.15.13/ar/concepts/testing.mdx create mode 100644 docs/v1.15.13/ar/concepts/tools.mdx create mode 100644 docs/v1.15.13/ar/concepts/training.mdx create mode 100644 docs/v1.15.13/ar/examples/cookbooks.mdx create mode 100644 docs/v1.15.13/ar/examples/example.mdx create mode 100644 docs/v1.15.13/ar/guides/advanced/customizing-prompts.mdx create mode 100644 docs/v1.15.13/ar/guides/advanced/fingerprinting.mdx create mode 100644 docs/v1.15.13/ar/guides/agents/crafting-effective-agents.mdx create mode 100644 docs/v1.15.13/ar/guides/coding-tools/agents-md.mdx create mode 100644 docs/v1.15.13/ar/guides/coding-tools/build-with-ai.mdx create mode 100644 docs/v1.15.13/ar/guides/concepts/evaluating-use-cases.mdx create mode 100644 docs/v1.15.13/ar/guides/crews/first-crew.mdx create mode 100644 docs/v1.15.13/ar/guides/flows/conversational-flows.mdx create mode 100644 docs/v1.15.13/ar/guides/flows/first-flow.mdx create mode 100644 docs/v1.15.13/ar/guides/flows/inputs-id-deprecation.mdx create mode 100644 docs/v1.15.13/ar/guides/flows/mastering-flow-state.mdx create mode 100644 docs/v1.15.13/ar/guides/migration/migrating-from-langgraph.mdx create mode 100644 docs/v1.15.13/ar/guides/migration/upgrading-crewai.mdx create mode 100644 docs/v1.15.13/ar/guides/tools/publish-custom-tools.mdx create mode 100644 docs/v1.15.13/ar/index.mdx create mode 100644 docs/v1.15.13/ar/installation.mdx create mode 100644 docs/v1.15.13/ar/introduction.mdx create mode 100644 docs/v1.15.13/ar/learn/a2a-agent-delegation.mdx create mode 100644 docs/v1.15.13/ar/learn/before-and-after-kickoff-hooks.mdx create mode 100644 docs/v1.15.13/ar/learn/bring-your-own-agent.mdx create mode 100644 docs/v1.15.13/ar/learn/coding-agents.mdx create mode 100644 docs/v1.15.13/ar/learn/conditional-tasks.mdx create mode 100644 docs/v1.15.13/ar/learn/create-custom-tools.mdx create mode 100644 docs/v1.15.13/ar/learn/custom-llm.mdx create mode 100644 docs/v1.15.13/ar/learn/custom-manager-agent.mdx create mode 100644 docs/v1.15.13/ar/learn/customizing-agents.mdx create mode 100644 docs/v1.15.13/ar/learn/dalle-image-generation.mdx create mode 100644 docs/v1.15.13/ar/learn/execution-hooks.mdx create mode 100644 docs/v1.15.13/ar/learn/force-tool-output-as-result.mdx create mode 100644 docs/v1.15.13/ar/learn/hierarchical-process.mdx create mode 100644 docs/v1.15.13/ar/learn/human-feedback-in-flows.mdx create mode 100644 docs/v1.15.13/ar/learn/human-in-the-loop.mdx create mode 100644 docs/v1.15.13/ar/learn/human-input-on-execution.mdx create mode 100644 docs/v1.15.13/ar/learn/kickoff-async.mdx create mode 100644 docs/v1.15.13/ar/learn/kickoff-for-each.mdx create mode 100644 docs/v1.15.13/ar/learn/litellm-removal-guide.mdx create mode 100644 docs/v1.15.13/ar/learn/llm-connections.mdx create mode 100644 docs/v1.15.13/ar/learn/llm-hooks.mdx create mode 100644 docs/v1.15.13/ar/learn/llm-selection-guide.mdx create mode 100644 docs/v1.15.13/ar/learn/multimodal-agents.mdx create mode 100644 docs/v1.15.13/ar/learn/overview.mdx create mode 100644 docs/v1.15.13/ar/learn/replay-tasks-from-latest-crew-kickoff.mdx create mode 100644 docs/v1.15.13/ar/learn/sequential-process.mdx create mode 100644 docs/v1.15.13/ar/learn/streaming-crew-execution.mdx create mode 100644 docs/v1.15.13/ar/learn/streaming-flow-execution.mdx create mode 100644 docs/v1.15.13/ar/learn/streaming-runtime-contract.mdx create mode 100644 docs/v1.15.13/ar/learn/tool-hooks.mdx create mode 100644 docs/v1.15.13/ar/learn/using-annotations.mdx create mode 100644 docs/v1.15.13/ar/mcp/dsl-integration.mdx create mode 100644 docs/v1.15.13/ar/mcp/multiple-servers.mdx create mode 100644 docs/v1.15.13/ar/mcp/overview.mdx create mode 100644 docs/v1.15.13/ar/mcp/security.mdx create mode 100644 docs/v1.15.13/ar/mcp/sse.mdx create mode 100644 docs/v1.15.13/ar/mcp/stdio.mdx create mode 100644 docs/v1.15.13/ar/mcp/streamable-http.mdx create mode 100644 docs/v1.15.13/ar/observability/arize-phoenix.mdx create mode 100644 docs/v1.15.13/ar/observability/braintrust.mdx create mode 100644 docs/v1.15.13/ar/observability/datadog.mdx create mode 100644 docs/v1.15.13/ar/observability/galileo.mdx create mode 100644 docs/v1.15.13/ar/observability/langdb.mdx create mode 100644 docs/v1.15.13/ar/observability/langfuse.mdx create mode 100644 docs/v1.15.13/ar/observability/langtrace.mdx create mode 100644 docs/v1.15.13/ar/observability/maxim.mdx create mode 100644 docs/v1.15.13/ar/observability/mlflow.mdx create mode 100644 docs/v1.15.13/ar/observability/neatlogs.mdx create mode 100644 docs/v1.15.13/ar/observability/openlit.mdx create mode 100644 docs/v1.15.13/ar/observability/opik.mdx create mode 100644 docs/v1.15.13/ar/observability/overview.mdx create mode 100644 docs/v1.15.13/ar/observability/patronus-evaluation.mdx create mode 100644 docs/v1.15.13/ar/observability/portkey.mdx create mode 100644 docs/v1.15.13/ar/observability/tracing.mdx create mode 100644 docs/v1.15.13/ar/observability/truefoundry.mdx create mode 100644 docs/v1.15.13/ar/observability/weave.mdx create mode 100644 docs/v1.15.13/ar/quickstart.mdx create mode 100644 docs/v1.15.13/ar/skills.mdx create mode 100644 docs/v1.15.13/ar/snippets/snippet-intro.mdx create mode 100644 docs/v1.15.13/ar/telemetry.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/aimindtool.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/codeinterpretertool.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/dalletool.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/daytona.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/langchaintool.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/llamaindextool.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/ragtool.mdx create mode 100644 docs/v1.15.13/ar/tools/ai-ml/visiontool.mdx create mode 100644 docs/v1.15.13/ar/tools/automation/apifyactorstool.mdx create mode 100644 docs/v1.15.13/ar/tools/automation/composiotool.mdx create mode 100644 docs/v1.15.13/ar/tools/automation/multiontool.mdx create mode 100644 docs/v1.15.13/ar/tools/automation/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/automation/zapieractionstool.mdx create mode 100644 docs/v1.15.13/ar/tools/cloud-storage/bedrockkbretriever.mdx create mode 100644 docs/v1.15.13/ar/tools/cloud-storage/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/cloud-storage/s3readertool.mdx create mode 100644 docs/v1.15.13/ar/tools/cloud-storage/s3writertool.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/mongodbvectorsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/mysqltool.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/nl2sqltool.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/pgsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/qdrantvectorsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/singlestoresearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/snowflakesearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/database-data/weaviatevectorsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/csvsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/directoryreadtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/directorysearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/docxsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/filereadtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/filewritetool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/jsonsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/mdxsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/ocrtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/pdf-text-writing-tool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/pdfsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/txtsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/file-document/xmlsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/integration/bedrockinvokeagenttool.mdx create mode 100644 docs/v1.15.13/ar/tools/integration/crewaiautomationtool.mdx create mode 100644 docs/v1.15.13/ar/tools/integration/mergeagenthandlertool.mdx create mode 100644 docs/v1.15.13/ar/tools/integration/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/arxivpapertool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/bravesearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/codedocssearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/databricks-query-tool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/exasearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/githubsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/linkupsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/serpapi-googlesearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/serpapi-googleshoppingtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/serperdevtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/tavilyextractortool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/tavilyresearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/tavilysearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/websitesearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/youtubechannelsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/search-research/youtubevideosearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/tool-integrations/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/brightdata-tools.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/browserbaseloadtool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/firecrawlcrawlwebsitetool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/firecrawlscrapewebsitetool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/firecrawlsearchtool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/hyperbrowserloadtool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/overview.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/oxylabsscraperstool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/scrapeelementfromwebsitetool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/scrapegraphscrapetool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/scrapewebsitetool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/scrapflyscrapetool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/seleniumscrapingtool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/serperscrapewebsitetool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/spidertool.mdx create mode 100644 docs/v1.15.13/ar/tools/web-scraping/stagehandtool.mdx create mode 100644 docs/v1.15.13/en/api-reference/inputs.mdx create mode 100644 docs/v1.15.13/en/api-reference/introduction.mdx create mode 100644 docs/v1.15.13/en/api-reference/kickoff.mdx create mode 100644 docs/v1.15.13/en/api-reference/resume.mdx create mode 100644 docs/v1.15.13/en/api-reference/status.mdx create mode 100644 docs/v1.15.13/en/changelog.mdx create mode 100644 docs/v1.15.13/en/concepts/agent-capabilities.mdx create mode 100644 docs/v1.15.13/en/concepts/agents.mdx create mode 100644 docs/v1.15.13/en/concepts/checkpointing.mdx create mode 100644 docs/v1.15.13/en/concepts/cli.mdx create mode 100644 docs/v1.15.13/en/concepts/collaboration.mdx create mode 100644 docs/v1.15.13/en/concepts/crews.mdx create mode 100644 docs/v1.15.13/en/concepts/event-listener.mdx create mode 100644 docs/v1.15.13/en/concepts/files.mdx create mode 100644 docs/v1.15.13/en/concepts/flows.mdx create mode 100644 docs/v1.15.13/en/concepts/knowledge.mdx create mode 100644 docs/v1.15.13/en/concepts/llms.mdx create mode 100644 docs/v1.15.13/en/concepts/memory.mdx create mode 100644 docs/v1.15.13/en/concepts/planning.mdx create mode 100644 docs/v1.15.13/en/concepts/processes.mdx create mode 100644 docs/v1.15.13/en/concepts/production-architecture.mdx create mode 100644 docs/v1.15.13/en/concepts/reasoning.mdx create mode 100644 docs/v1.15.13/en/concepts/skills.mdx create mode 100644 docs/v1.15.13/en/concepts/streaming.mdx create mode 100644 docs/v1.15.13/en/concepts/tasks.mdx create mode 100644 docs/v1.15.13/en/concepts/testing.mdx create mode 100644 docs/v1.15.13/en/concepts/tools.mdx create mode 100644 docs/v1.15.13/en/concepts/training.mdx create mode 100644 docs/v1.15.13/en/examples/cookbooks.mdx create mode 100644 docs/v1.15.13/en/examples/example.mdx create mode 100644 docs/v1.15.13/en/guides/advanced/customizing-prompts.mdx create mode 100644 docs/v1.15.13/en/guides/advanced/fingerprinting.mdx create mode 100644 docs/v1.15.13/en/guides/agents/crafting-effective-agents.mdx create mode 100644 docs/v1.15.13/en/guides/coding-tools/agents-md.mdx create mode 100644 docs/v1.15.13/en/guides/coding-tools/build-with-ai.mdx create mode 100644 docs/v1.15.13/en/guides/concepts/evaluating-use-cases.mdx create mode 100644 docs/v1.15.13/en/guides/crews/first-crew.mdx create mode 100644 docs/v1.15.13/en/guides/flows/conversational-flows.mdx create mode 100644 docs/v1.15.13/en/guides/flows/first-flow.mdx create mode 100644 docs/v1.15.13/en/guides/flows/inputs-id-deprecation.mdx create mode 100644 docs/v1.15.13/en/guides/flows/mastering-flow-state.mdx create mode 100644 docs/v1.15.13/en/guides/migration/migrating-from-langgraph.mdx create mode 100644 docs/v1.15.13/en/guides/migration/upgrading-crewai.mdx create mode 100644 docs/v1.15.13/en/guides/tools/publish-custom-tools.mdx create mode 100644 docs/v1.15.13/en/index.mdx create mode 100644 docs/v1.15.13/en/installation.mdx create mode 100644 docs/v1.15.13/en/introduction.mdx create mode 100644 docs/v1.15.13/en/learn/a2a-agent-delegation.mdx create mode 100644 docs/v1.15.13/en/learn/a2ui.mdx create mode 100644 docs/v1.15.13/en/learn/before-and-after-kickoff-hooks.mdx create mode 100644 docs/v1.15.13/en/learn/bring-your-own-agent.mdx create mode 100644 docs/v1.15.13/en/learn/coding-agents.mdx create mode 100644 docs/v1.15.13/en/learn/conditional-tasks.mdx create mode 100644 docs/v1.15.13/en/learn/consuming-streams.mdx create mode 100644 docs/v1.15.13/en/learn/create-custom-tools.mdx create mode 100644 docs/v1.15.13/en/learn/custom-llm.mdx create mode 100644 docs/v1.15.13/en/learn/custom-manager-agent.mdx create mode 100644 docs/v1.15.13/en/learn/customizing-agents.mdx create mode 100644 docs/v1.15.13/en/learn/dalle-image-generation.mdx create mode 100644 docs/v1.15.13/en/learn/execution-boundary-hooks.mdx create mode 100644 docs/v1.15.13/en/learn/execution-hooks.mdx create mode 100644 docs/v1.15.13/en/learn/force-tool-output-as-result.mdx create mode 100644 docs/v1.15.13/en/learn/hierarchical-process.mdx create mode 100644 docs/v1.15.13/en/learn/human-feedback-in-flows.mdx create mode 100644 docs/v1.15.13/en/learn/human-in-the-loop.mdx create mode 100644 docs/v1.15.13/en/learn/human-input-on-execution.mdx create mode 100644 docs/v1.15.13/en/learn/kickoff-async.mdx create mode 100644 docs/v1.15.13/en/learn/kickoff-for-each.mdx create mode 100644 docs/v1.15.13/en/learn/litellm-removal-guide.mdx create mode 100644 docs/v1.15.13/en/learn/llm-connections.mdx create mode 100644 docs/v1.15.13/en/learn/llm-hooks.mdx create mode 100644 docs/v1.15.13/en/learn/llm-selection-guide.mdx create mode 100644 docs/v1.15.13/en/learn/multimodal-agents.mdx create mode 100644 docs/v1.15.13/en/learn/overview.mdx create mode 100644 docs/v1.15.13/en/learn/replay-tasks-from-latest-crew-kickoff.mdx create mode 100644 docs/v1.15.13/en/learn/sequential-process.mdx create mode 100644 docs/v1.15.13/en/learn/step-hooks.mdx create mode 100644 docs/v1.15.13/en/learn/streaming-crew-execution.mdx create mode 100644 docs/v1.15.13/en/learn/streaming-flow-execution.mdx create mode 100644 docs/v1.15.13/en/learn/streaming-runtime-contract.mdx create mode 100644 docs/v1.15.13/en/learn/tool-hooks.mdx create mode 100644 docs/v1.15.13/en/learn/using-annotations.mdx create mode 100644 docs/v1.15.13/en/mcp/dsl-integration.mdx create mode 100644 docs/v1.15.13/en/mcp/multiple-servers.mdx create mode 100644 docs/v1.15.13/en/mcp/overview.mdx create mode 100644 docs/v1.15.13/en/mcp/security.mdx create mode 100644 docs/v1.15.13/en/mcp/sse.mdx create mode 100644 docs/v1.15.13/en/mcp/stdio.mdx create mode 100644 docs/v1.15.13/en/mcp/streamable-http.mdx create mode 100644 docs/v1.15.13/en/observability/arize-phoenix.mdx create mode 100644 docs/v1.15.13/en/observability/braintrust.mdx create mode 100644 docs/v1.15.13/en/observability/datadog.mdx create mode 100644 docs/v1.15.13/en/observability/galileo.mdx create mode 100644 docs/v1.15.13/en/observability/langdb.mdx create mode 100644 docs/v1.15.13/en/observability/langfuse.mdx create mode 100644 docs/v1.15.13/en/observability/langtrace.mdx create mode 100644 docs/v1.15.13/en/observability/maxim.mdx create mode 100644 docs/v1.15.13/en/observability/mlflow.mdx create mode 100644 docs/v1.15.13/en/observability/neatlogs.mdx create mode 100644 docs/v1.15.13/en/observability/openlit.mdx create mode 100644 docs/v1.15.13/en/observability/opik.mdx create mode 100644 docs/v1.15.13/en/observability/overview.mdx create mode 100644 docs/v1.15.13/en/observability/patronus-evaluation.mdx create mode 100644 docs/v1.15.13/en/observability/portkey.mdx create mode 100644 docs/v1.15.13/en/observability/tracing.mdx create mode 100644 docs/v1.15.13/en/observability/truefoundry.mdx create mode 100644 docs/v1.15.13/en/observability/weave.mdx create mode 100644 docs/v1.15.13/en/quickstart.mdx create mode 100644 docs/v1.15.13/en/skills.mdx create mode 100644 docs/v1.15.13/en/snippets/snippet-intro.mdx create mode 100644 docs/v1.15.13/en/telemetry.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/aimindtool.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/codeinterpretertool.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/dalletool.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/daytona.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/e2bsandboxtools.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/langchaintool.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/llamaindextool.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/overview.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/ragtool.mdx create mode 100644 docs/v1.15.13/en/tools/ai-ml/visiontool.mdx create mode 100644 docs/v1.15.13/en/tools/automation/apifyactorstool.mdx create mode 100644 docs/v1.15.13/en/tools/automation/composiotool.mdx create mode 100644 docs/v1.15.13/en/tools/automation/multiontool.mdx create mode 100644 docs/v1.15.13/en/tools/automation/overview.mdx create mode 100644 docs/v1.15.13/en/tools/automation/waittool.mdx create mode 100644 docs/v1.15.13/en/tools/automation/zapieractionstool.mdx create mode 100644 docs/v1.15.13/en/tools/cloud-storage/bedrockkbretriever.mdx create mode 100644 docs/v1.15.13/en/tools/cloud-storage/overview.mdx create mode 100644 docs/v1.15.13/en/tools/cloud-storage/s3readertool.mdx create mode 100644 docs/v1.15.13/en/tools/cloud-storage/s3writertool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/db2searchtool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/mongodbvectorsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/mysqltool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/nl2sqltool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/overview.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/pgsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/qdrantvectorsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/singlestoresearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/snowflakesearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/database-data/weaviatevectorsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/csvsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/directoryreadtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/directorysearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/docxsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/filereadtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/filewritetool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/jsonsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/mdxsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/ocrtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/overview.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/pdf-text-writing-tool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/pdfsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/txtsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/file-document/xmlsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/integration/bedrockinvokeagenttool.mdx create mode 100644 docs/v1.15.13/en/tools/integration/crewaiautomationtool.mdx create mode 100644 docs/v1.15.13/en/tools/integration/mergeagenthandlertool.mdx create mode 100644 docs/v1.15.13/en/tools/integration/overview.mdx create mode 100644 docs/v1.15.13/en/tools/overview.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/arxivpapertool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/bravesearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/codedocssearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/databricks-query-tool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/exasearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/githubsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/linkupsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/overview.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/serpapi-googlesearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/serpapi-googleshoppingtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/serperdevtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/tavilyextractortool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/tavilygetresearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/tavilyresearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/tavilysearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/websitesearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/youai-search.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/youtubechannelsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/search-research/youtubevideosearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/tool-integrations/overview.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/brightdata-tools.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/browserbaseloadtool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/firecrawlcrawlwebsitetool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/firecrawlscrapewebsitetool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/firecrawlsearchtool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/hyperbrowserloadtool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/overview.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/oxylabsscraperstool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/scrapeelementfromwebsitetool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/scrapegraphscrapetool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/scrapewebsitetool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/scrapflyscrapetool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/seleniumscrapingtool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/serperscrapewebsitetool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/spidertool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/stagehandtool.mdx create mode 100644 docs/v1.15.13/en/tools/web-scraping/youai-contents.mdx create mode 100644 docs/v1.15.13/enterprise-api.base.yaml create mode 100644 docs/v1.15.13/enterprise-api.en.yaml create mode 100644 docs/v1.15.13/enterprise-api.ko.yaml create mode 100644 docs/v1.15.13/enterprise-api.pt-BR.yaml create mode 100644 docs/v1.15.13/ko/api-reference/inputs.mdx create mode 100644 docs/v1.15.13/ko/api-reference/introduction.mdx create mode 100644 docs/v1.15.13/ko/api-reference/kickoff.mdx create mode 100644 docs/v1.15.13/ko/api-reference/resume.mdx create mode 100644 docs/v1.15.13/ko/api-reference/status.mdx create mode 100644 docs/v1.15.13/ko/changelog.mdx create mode 100644 docs/v1.15.13/ko/concepts/agent-capabilities.mdx create mode 100644 docs/v1.15.13/ko/concepts/agents.mdx create mode 100644 docs/v1.15.13/ko/concepts/checkpointing.mdx create mode 100644 docs/v1.15.13/ko/concepts/cli.mdx create mode 100644 docs/v1.15.13/ko/concepts/collaboration.mdx create mode 100644 docs/v1.15.13/ko/concepts/crews.mdx create mode 100644 docs/v1.15.13/ko/concepts/event-listener.mdx create mode 100644 docs/v1.15.13/ko/concepts/files.mdx create mode 100644 docs/v1.15.13/ko/concepts/flows.mdx create mode 100644 docs/v1.15.13/ko/concepts/knowledge.mdx create mode 100644 docs/v1.15.13/ko/concepts/llms.mdx create mode 100644 docs/v1.15.13/ko/concepts/memory.mdx create mode 100644 docs/v1.15.13/ko/concepts/planning.mdx create mode 100644 docs/v1.15.13/ko/concepts/processes.mdx create mode 100644 docs/v1.15.13/ko/concepts/production-architecture.mdx create mode 100644 docs/v1.15.13/ko/concepts/reasoning.mdx create mode 100644 docs/v1.15.13/ko/concepts/skills.mdx create mode 100644 docs/v1.15.13/ko/concepts/tasks.mdx create mode 100644 docs/v1.15.13/ko/concepts/testing.mdx create mode 100644 docs/v1.15.13/ko/concepts/tools.mdx create mode 100644 docs/v1.15.13/ko/concepts/training.mdx create mode 100644 docs/v1.15.13/ko/examples/cookbooks.mdx create mode 100644 docs/v1.15.13/ko/examples/example.mdx create mode 100644 docs/v1.15.13/ko/guides/advanced/customizing-prompts.mdx create mode 100644 docs/v1.15.13/ko/guides/advanced/fingerprinting.mdx create mode 100644 docs/v1.15.13/ko/guides/agents/crafting-effective-agents.mdx create mode 100644 docs/v1.15.13/ko/guides/coding-tools/agents-md.mdx create mode 100644 docs/v1.15.13/ko/guides/coding-tools/build-with-ai.mdx create mode 100644 docs/v1.15.13/ko/guides/concepts/evaluating-use-cases.mdx create mode 100644 docs/v1.15.13/ko/guides/crews/first-crew.mdx create mode 100644 docs/v1.15.13/ko/guides/flows/conversational-flows.mdx create mode 100644 docs/v1.15.13/ko/guides/flows/first-flow.mdx create mode 100644 docs/v1.15.13/ko/guides/flows/inputs-id-deprecation.mdx create mode 100644 docs/v1.15.13/ko/guides/flows/mastering-flow-state.mdx create mode 100644 docs/v1.15.13/ko/guides/migration/migrating-from-langgraph.mdx create mode 100644 docs/v1.15.13/ko/guides/migration/upgrading-crewai.mdx create mode 100644 docs/v1.15.13/ko/guides/tools/publish-custom-tools.mdx create mode 100644 docs/v1.15.13/ko/index.mdx create mode 100644 docs/v1.15.13/ko/installation.mdx create mode 100644 docs/v1.15.13/ko/introduction.mdx create mode 100644 docs/v1.15.13/ko/learn/before-and-after-kickoff-hooks.mdx create mode 100644 docs/v1.15.13/ko/learn/bring-your-own-agent.mdx create mode 100644 docs/v1.15.13/ko/learn/coding-agents.mdx create mode 100644 docs/v1.15.13/ko/learn/conditional-tasks.mdx create mode 100644 docs/v1.15.13/ko/learn/create-custom-tools.mdx create mode 100644 docs/v1.15.13/ko/learn/custom-llm.mdx create mode 100644 docs/v1.15.13/ko/learn/custom-manager-agent.mdx create mode 100644 docs/v1.15.13/ko/learn/customizing-agents.mdx create mode 100644 docs/v1.15.13/ko/learn/dalle-image-generation.mdx create mode 100644 docs/v1.15.13/ko/learn/execution-hooks.mdx create mode 100644 docs/v1.15.13/ko/learn/force-tool-output-as-result.mdx create mode 100644 docs/v1.15.13/ko/learn/hierarchical-process.mdx create mode 100644 docs/v1.15.13/ko/learn/human-feedback-in-flows.mdx create mode 100644 docs/v1.15.13/ko/learn/human-in-the-loop.mdx create mode 100644 docs/v1.15.13/ko/learn/human-input-on-execution.mdx create mode 100644 docs/v1.15.13/ko/learn/kickoff-async.mdx create mode 100644 docs/v1.15.13/ko/learn/kickoff-for-each.mdx create mode 100644 docs/v1.15.13/ko/learn/llm-connections.mdx create mode 100644 docs/v1.15.13/ko/learn/llm-hooks.mdx create mode 100644 docs/v1.15.13/ko/learn/llm-selection-guide.mdx create mode 100644 docs/v1.15.13/ko/learn/multimodal-agents.mdx create mode 100644 docs/v1.15.13/ko/learn/overview.mdx create mode 100644 docs/v1.15.13/ko/learn/replay-tasks-from-latest-crew-kickoff.mdx create mode 100644 docs/v1.15.13/ko/learn/sequential-process.mdx create mode 100644 docs/v1.15.13/ko/learn/streaming-crew-execution.mdx create mode 100644 docs/v1.15.13/ko/learn/streaming-runtime-contract.mdx create mode 100644 docs/v1.15.13/ko/learn/tool-hooks.mdx create mode 100644 docs/v1.15.13/ko/learn/using-annotations.mdx create mode 100644 docs/v1.15.13/ko/mcp/dsl-integration.mdx create mode 100644 docs/v1.15.13/ko/mcp/multiple-servers.mdx create mode 100644 docs/v1.15.13/ko/mcp/overview.mdx create mode 100644 docs/v1.15.13/ko/mcp/security.mdx create mode 100644 docs/v1.15.13/ko/mcp/sse.mdx create mode 100644 docs/v1.15.13/ko/mcp/stdio.mdx create mode 100644 docs/v1.15.13/ko/mcp/streamable-http.mdx create mode 100644 docs/v1.15.13/ko/observability/arize-phoenix.mdx create mode 100644 docs/v1.15.13/ko/observability/braintrust.mdx create mode 100644 docs/v1.15.13/ko/observability/datadog.mdx create mode 100644 docs/v1.15.13/ko/observability/galileo.mdx create mode 100644 docs/v1.15.13/ko/observability/langdb.mdx create mode 100644 docs/v1.15.13/ko/observability/langfuse.mdx create mode 100644 docs/v1.15.13/ko/observability/langtrace.mdx create mode 100644 docs/v1.15.13/ko/observability/maxim.mdx create mode 100644 docs/v1.15.13/ko/observability/mlflow.mdx create mode 100644 docs/v1.15.13/ko/observability/neatlogs.mdx create mode 100644 docs/v1.15.13/ko/observability/openlit.mdx create mode 100644 docs/v1.15.13/ko/observability/opik.mdx create mode 100644 docs/v1.15.13/ko/observability/overview.mdx create mode 100644 docs/v1.15.13/ko/observability/patronus-evaluation.mdx create mode 100644 docs/v1.15.13/ko/observability/portkey.mdx create mode 100644 docs/v1.15.13/ko/observability/tracing.mdx create mode 100644 docs/v1.15.13/ko/observability/truefoundry.mdx create mode 100644 docs/v1.15.13/ko/observability/weave.mdx create mode 100644 docs/v1.15.13/ko/quickstart.mdx create mode 100644 docs/v1.15.13/ko/skills.mdx create mode 100644 docs/v1.15.13/ko/snippets/snippet-intro.mdx create mode 100644 docs/v1.15.13/ko/telemetry.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/aimindtool.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/codeinterpretertool.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/dalletool.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/daytona.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/langchaintool.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/llamaindextool.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/ragtool.mdx create mode 100644 docs/v1.15.13/ko/tools/ai-ml/visiontool.mdx create mode 100644 docs/v1.15.13/ko/tools/automation/apifyactorstool.mdx create mode 100644 docs/v1.15.13/ko/tools/automation/composiotool.mdx create mode 100644 docs/v1.15.13/ko/tools/automation/multiontool.mdx create mode 100644 docs/v1.15.13/ko/tools/automation/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/automation/zapieractionstool.mdx create mode 100644 docs/v1.15.13/ko/tools/cloud-storage/bedrockkbretriever.mdx create mode 100644 docs/v1.15.13/ko/tools/cloud-storage/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/cloud-storage/s3readertool.mdx create mode 100644 docs/v1.15.13/ko/tools/cloud-storage/s3writertool.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/mongodbvectorsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/mysqltool.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/nl2sqltool.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/pgsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/qdrantvectorsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/singlestoresearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/snowflakesearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/database-data/weaviatevectorsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/csvsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/directoryreadtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/directorysearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/docxsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/filereadtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/filewritetool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/jsonsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/mdxsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/ocrtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/pdf-text-writing-tool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/pdfsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/txtsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/file-document/xmlsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/integration/bedrockinvokeagenttool.mdx create mode 100644 docs/v1.15.13/ko/tools/integration/crewaiautomationtool.mdx create mode 100644 docs/v1.15.13/ko/tools/integration/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/arxivpapertool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/bravesearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/codedocssearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/databricks-query-tool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/exasearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/githubsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/linkupsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/serpapi-googlesearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/serpapi-googleshoppingtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/serperdevtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/tavilyextractortool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/tavilyresearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/tavilysearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/websitesearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/youtubechannelsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/search-research/youtubevideosearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/tool-integrations/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/brightdata-tools.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/browserbaseloadtool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/firecrawlcrawlwebsitetool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/firecrawlscrapewebsitetool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/firecrawlsearchtool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/hyperbrowserloadtool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/overview.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/oxylabsscraperstool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/scrapeelementfromwebsitetool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/scrapegraphscrapetool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/scrapewebsitetool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/scrapflyscrapetool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/seleniumscrapingtool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/serperscrapewebsitetool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/spidertool.mdx create mode 100644 docs/v1.15.13/ko/tools/web-scraping/stagehandtool.mdx create mode 100644 docs/v1.15.13/pt-BR/api-reference/inputs.mdx create mode 100644 docs/v1.15.13/pt-BR/api-reference/introduction.mdx create mode 100644 docs/v1.15.13/pt-BR/api-reference/kickoff.mdx create mode 100644 docs/v1.15.13/pt-BR/api-reference/resume.mdx create mode 100644 docs/v1.15.13/pt-BR/api-reference/status.mdx create mode 100644 docs/v1.15.13/pt-BR/changelog.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/agent-capabilities.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/agents.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/checkpointing.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/cli.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/collaboration.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/crews.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/event-listener.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/files.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/flows.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/knowledge.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/llms.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/memory.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/planning.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/processes.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/production-architecture.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/reasoning.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/skills.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/tasks.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/testing.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/tools.mdx create mode 100644 docs/v1.15.13/pt-BR/concepts/training.mdx create mode 100644 docs/v1.15.13/pt-BR/examples/cookbooks.mdx create mode 100644 docs/v1.15.13/pt-BR/examples/example.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/advanced/customizing-prompts.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/advanced/fingerprinting.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/agents/crafting-effective-agents.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/coding-tools/agents-md.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/coding-tools/build-with-ai.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/concepts/evaluating-use-cases.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/crews/first-crew.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/flows/conversational-flows.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/flows/first-flow.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/flows/inputs-id-deprecation.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/flows/mastering-flow-state.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/migration/migrating-from-langgraph.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/migration/upgrading-crewai.mdx create mode 100644 docs/v1.15.13/pt-BR/guides/tools/publish-custom-tools.mdx create mode 100644 docs/v1.15.13/pt-BR/index.mdx create mode 100644 docs/v1.15.13/pt-BR/installation.mdx create mode 100644 docs/v1.15.13/pt-BR/introduction.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/before-and-after-kickoff-hooks.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/bring-your-own-agent.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/coding-agents.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/conditional-tasks.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/create-custom-tools.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/custom-llm.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/custom-manager-agent.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/customizing-agents.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/dalle-image-generation.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/execution-hooks.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/force-tool-output-as-result.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/hierarchical-process.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/human-feedback-in-flows.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/human-in-the-loop.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/human-input-on-execution.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/kickoff-async.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/kickoff-for-each.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/llm-connections.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/llm-hooks.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/llm-selection-guide.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/multimodal-agents.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/replay-tasks-from-latest-crew-kickoff.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/sequential-process.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/streaming-crew-execution.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/streaming-runtime-contract.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/tool-hooks.mdx create mode 100644 docs/v1.15.13/pt-BR/learn/using-annotations.mdx create mode 100644 docs/v1.15.13/pt-BR/mcp/dsl-integration.mdx create mode 100644 docs/v1.15.13/pt-BR/mcp/multiple-servers.mdx create mode 100644 docs/v1.15.13/pt-BR/mcp/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/mcp/security.mdx create mode 100644 docs/v1.15.13/pt-BR/mcp/sse.mdx create mode 100644 docs/v1.15.13/pt-BR/mcp/stdio.mdx create mode 100644 docs/v1.15.13/pt-BR/mcp/streamable-http.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/arize-phoenix.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/braintrust.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/datadog.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/galileo.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/langdb.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/langfuse.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/langtrace.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/maxim.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/mlflow.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/neatlogs.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/openlit.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/opik.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/patronus-evaluation.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/portkey.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/tracing.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/truefoundry.mdx create mode 100644 docs/v1.15.13/pt-BR/observability/weave.mdx create mode 100644 docs/v1.15.13/pt-BR/quickstart.mdx create mode 100644 docs/v1.15.13/pt-BR/skills.mdx create mode 100644 docs/v1.15.13/pt-BR/snippets/snippet-intro.mdx create mode 100644 docs/v1.15.13/pt-BR/telemetry.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/aimindtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/codeinterpretertool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/dalletool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/daytona.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/langchaintool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/llamaindextool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/ragtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/ai-ml/visiontool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/automation/apifyactorstool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/automation/composiotool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/automation/multiontool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/automation/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/automation/zapieractionstool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/cloud-storage/bedrockkbretriever.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/cloud-storage/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/cloud-storage/s3readertool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/cloud-storage/s3writertool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/mongodbvectorsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/mysqltool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/nl2sqltool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/pgsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/qdrantvectorsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/singlestoresearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/snowflakesearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/database-data/weaviatevectorsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/csvsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/directoryreadtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/directorysearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/docxsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/filereadtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/filewritetool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/jsonsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/mdxsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/ocrtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/pdf-text-writing-tool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/pdfsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/txtsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/file-document/xmlsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/integration/bedrockinvokeagenttool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/integration/crewaiautomationtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/integration/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/arxivpapertool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/bravesearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/codedocssearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/databricks-query-tool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/exasearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/githubsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/linkupsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/serpapi-googlesearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/serpapi-googleshoppingtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/serperdevtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/tavilyextractortool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/tavilyresearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/tavilysearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/websitesearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/youtubechannelsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/search-research/youtubevideosearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/tool-integrations/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/brightdata-tools.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/browserbaseloadtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/firecrawlcrawlwebsitetool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/firecrawlscrapewebsitetool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/firecrawlsearchtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/hyperbrowserloadtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/overview.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/oxylabsscraperstool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/scrapeelementfromwebsitetool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/scrapegraphscrapetool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/scrapewebsitetool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/scrapflyscrapetool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/seleniumscrapingtool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/serperscrapewebsitetool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/spidertool.mdx create mode 100644 docs/v1.15.13/pt-BR/tools/web-scraping/stagehandtool.mdx diff --git a/docs/docs.json b/docs/docs.json index ea5ee40663..76130e0c5d 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -445,6 +445,397 @@ ], "tag": "Edge" }, + { + "version": "v1.15.13", + "tabs": [ + { + "tab": "Home", + "icon": "house", + "groups": [ + { + "group": "Welcome", + "pages": [ + "index" + ] + } + ] + }, + { + "tab": "Documentation", + "icon": "book-open", + "groups": [ + { + "group": "Get Started", + "pages": [ + "v1.15.13/en/introduction", + "v1.15.13/en/guides/coding-tools/build-with-ai", + "v1.15.13/en/skills", + "v1.15.13/en/installation", + "v1.15.13/en/quickstart" + ] + }, + { + "group": "Guides", + "pages": [ + { + "group": "Strategy", + "icon": "compass", + "pages": [ + "v1.15.13/en/guides/concepts/evaluating-use-cases" + ] + }, + { + "group": "Agents", + "icon": "user", + "pages": [ + "v1.15.13/en/guides/agents/crafting-effective-agents" + ] + }, + { + "group": "Crews", + "icon": "users", + "pages": [ + "v1.15.13/en/guides/crews/first-crew" + ] + }, + { + "group": "Flows", + "icon": "code-branch", + "pages": [ + "v1.15.13/en/guides/flows/first-flow", + "v1.15.13/en/guides/flows/mastering-flow-state", + "v1.15.13/en/guides/flows/conversational-flows", + "v1.15.13/en/guides/flows/inputs-id-deprecation" + ] + }, + { + "group": "Tools", + "icon": "wrench", + "pages": [ + "v1.15.13/en/guides/tools/publish-custom-tools" + ] + }, + { + "group": "Coding Tools", + "icon": "terminal", + "pages": [ + "v1.15.13/en/guides/coding-tools/agents-md", + "v1.15.13/en/guides/coding-tools/build-with-ai" + ] + }, + { + "group": "Advanced", + "icon": "gear", + "pages": [ + "v1.15.13/en/guides/advanced/customizing-prompts", + "v1.15.13/en/guides/advanced/fingerprinting" + ] + }, + { + "group": "Migration", + "icon": "shuffle", + "pages": [ + "v1.15.13/en/guides/migration/migrating-from-langgraph", + "v1.15.13/en/guides/migration/upgrading-crewai" + ] + } + ] + }, + { + "group": "Core Concepts", + "pages": [ + "v1.15.13/en/concepts/agents", + "v1.15.13/en/concepts/agent-capabilities", + "v1.15.13/en/concepts/tasks", + "v1.15.13/en/concepts/crews", + "v1.15.13/en/concepts/flows", + "v1.15.13/en/concepts/streaming", + "v1.15.13/en/concepts/production-architecture", + "v1.15.13/en/concepts/knowledge", + "v1.15.13/en/concepts/skills", + "v1.15.13/en/concepts/llms", + "v1.15.13/en/concepts/files", + "v1.15.13/en/concepts/processes", + "v1.15.13/en/concepts/collaboration", + "v1.15.13/en/concepts/training", + "v1.15.13/en/concepts/memory", + "v1.15.13/en/concepts/reasoning", + "v1.15.13/en/concepts/planning", + "v1.15.13/en/concepts/testing", + "v1.15.13/en/concepts/cli", + "v1.15.13/en/concepts/tools", + "v1.15.13/en/concepts/event-listener", + "v1.15.13/en/concepts/checkpointing" + ] + }, + { + "group": "MCP Integration", + "pages": [ + "v1.15.13/en/mcp/overview", + "v1.15.13/en/mcp/dsl-integration", + "v1.15.13/en/mcp/stdio", + "v1.15.13/en/mcp/sse", + "v1.15.13/en/mcp/streamable-http", + "v1.15.13/en/mcp/multiple-servers", + "v1.15.13/en/mcp/security" + ] + }, + { + "group": "Tools", + "pages": [ + "v1.15.13/en/tools/overview", + { + "group": "File & Document", + "icon": "folder-open", + "pages": [ + "v1.15.13/en/tools/file-document/overview", + "v1.15.13/en/tools/file-document/filereadtool", + "v1.15.13/en/tools/file-document/filewritetool", + "v1.15.13/en/tools/file-document/pdfsearchtool", + "v1.15.13/en/tools/file-document/docxsearchtool", + "v1.15.13/en/tools/file-document/mdxsearchtool", + "v1.15.13/en/tools/file-document/xmlsearchtool", + "v1.15.13/en/tools/file-document/txtsearchtool", + "v1.15.13/en/tools/file-document/jsonsearchtool", + "v1.15.13/en/tools/file-document/csvsearchtool", + "v1.15.13/en/tools/file-document/directorysearchtool", + "v1.15.13/en/tools/file-document/directoryreadtool", + "v1.15.13/en/tools/file-document/ocrtool", + "v1.15.13/en/tools/file-document/pdf-text-writing-tool" + ] + }, + { + "group": "Web Scraping & Browsing", + "icon": "globe", + "pages": [ + "v1.15.13/en/tools/web-scraping/overview", + "v1.15.13/en/tools/web-scraping/scrapewebsitetool", + "v1.15.13/en/tools/web-scraping/scrapeelementfromwebsitetool", + "v1.15.13/en/tools/web-scraping/scrapflyscrapetool", + "v1.15.13/en/tools/web-scraping/seleniumscrapingtool", + "v1.15.13/en/tools/web-scraping/scrapegraphscrapetool", + "v1.15.13/en/tools/web-scraping/spidertool", + "v1.15.13/en/tools/web-scraping/browserbaseloadtool", + "v1.15.13/en/tools/web-scraping/hyperbrowserloadtool", + "v1.15.13/en/tools/web-scraping/stagehandtool", + "v1.15.13/en/tools/web-scraping/firecrawlcrawlwebsitetool", + "v1.15.13/en/tools/web-scraping/firecrawlscrapewebsitetool", + "v1.15.13/en/tools/web-scraping/oxylabsscraperstool", + "v1.15.13/en/tools/web-scraping/brightdata-tools", + "v1.15.13/en/tools/web-scraping/youai-contents" + ] + }, + { + "group": "Search & Research", + "icon": "magnifying-glass", + "pages": [ + "v1.15.13/en/tools/search-research/overview", + "v1.15.13/en/tools/search-research/serperdevtool", + "v1.15.13/en/tools/search-research/bravesearchtool", + "v1.15.13/en/tools/search-research/exasearchtool", + "v1.15.13/en/tools/search-research/linkupsearchtool", + "v1.15.13/en/tools/search-research/githubsearchtool", + "v1.15.13/en/tools/search-research/websitesearchtool", + "v1.15.13/en/tools/search-research/codedocssearchtool", + "v1.15.13/en/tools/search-research/youtubechannelsearchtool", + "v1.15.13/en/tools/search-research/youtubevideosearchtool", + "v1.15.13/en/tools/search-research/tavilysearchtool", + "v1.15.13/en/tools/search-research/tavilyextractortool", + "v1.15.13/en/tools/search-research/tavilyresearchtool", + "v1.15.13/en/tools/search-research/arxivpapertool", + "v1.15.13/en/tools/search-research/serpapi-googlesearchtool", + "v1.15.13/en/tools/search-research/serpapi-googleshoppingtool", + "v1.15.13/en/tools/search-research/databricks-query-tool", + "v1.15.13/en/tools/search-research/youai-search" + ] + }, + { + "group": "Database & Data", + "icon": "database", + "pages": [ + "v1.15.13/en/tools/database-data/overview", + "v1.15.13/en/tools/database-data/mysqltool", + "v1.15.13/en/tools/database-data/pgsearchtool", + "v1.15.13/en/tools/database-data/snowflakesearchtool", + "v1.15.13/en/tools/database-data/nl2sqltool", + "v1.15.13/en/tools/database-data/qdrantvectorsearchtool", + "v1.15.13/en/tools/database-data/weaviatevectorsearchtool", + "v1.15.13/en/tools/database-data/mongodbvectorsearchtool", + "v1.15.13/en/tools/database-data/singlestoresearchtool", + "v1.15.13/en/tools/database-data/db2searchtool" + ] + }, + { + "group": "AI & Machine Learning", + "icon": "brain", + "pages": [ + "v1.15.13/en/tools/ai-ml/overview", + "v1.15.13/en/tools/ai-ml/dalletool", + "v1.15.13/en/tools/ai-ml/visiontool", + "v1.15.13/en/tools/ai-ml/aimindtool", + "v1.15.13/en/tools/ai-ml/llamaindextool", + "v1.15.13/en/tools/ai-ml/langchaintool", + "v1.15.13/en/tools/ai-ml/ragtool", + "v1.15.13/en/tools/ai-ml/codeinterpretertool", + "v1.15.13/en/tools/ai-ml/daytona", + "v1.15.13/en/tools/ai-ml/e2bsandboxtools" + ] + }, + { + "group": "Cloud & Storage", + "icon": "cloud", + "pages": [ + "v1.15.13/en/tools/cloud-storage/overview", + "v1.15.13/en/tools/cloud-storage/s3readertool", + "v1.15.13/en/tools/cloud-storage/s3writertool", + "v1.15.13/en/tools/cloud-storage/bedrockkbretriever" + ] + }, + { + "group": "Integrations", + "icon": "plug", + "pages": [ + "v1.15.13/en/tools/integration/overview", + "v1.15.13/en/tools/integration/bedrockinvokeagenttool", + "v1.15.13/en/tools/integration/crewaiautomationtool", + "v1.15.13/en/tools/integration/mergeagenthandlertool" + ] + }, + { + "group": "Automation", + "icon": "bolt", + "pages": [ + "v1.15.13/en/tools/automation/overview", + "v1.15.13/en/tools/automation/apifyactorstool", + "v1.15.13/en/tools/automation/composiotool", + "v1.15.13/en/tools/automation/multiontool", + "v1.15.13/en/tools/automation/waittool", + "v1.15.13/en/tools/automation/zapieractionstool" + ] + } + ] + }, + { + "group": "Observability", + "pages": [ + "v1.15.13/en/observability/tracing", + "v1.15.13/en/observability/overview", + "v1.15.13/en/observability/arize-phoenix", + "v1.15.13/en/observability/braintrust", + "v1.15.13/en/observability/datadog", + "v1.15.13/en/observability/galileo", + "v1.15.13/en/observability/langdb", + "v1.15.13/en/observability/langfuse", + "v1.15.13/en/observability/langtrace", + "v1.15.13/en/observability/maxim", + "v1.15.13/en/observability/mlflow", + "v1.15.13/en/observability/neatlogs", + "v1.15.13/en/observability/openlit", + "v1.15.13/en/observability/opik", + "v1.15.13/en/observability/patronus-evaluation", + "v1.15.13/en/observability/portkey", + "v1.15.13/en/observability/weave", + "v1.15.13/en/observability/truefoundry" + ] + }, + { + "group": "Learn", + "pages": [ + "v1.15.13/en/learn/overview", + "v1.15.13/en/learn/llm-selection-guide", + "v1.15.13/en/learn/conditional-tasks", + "v1.15.13/en/learn/coding-agents", + "v1.15.13/en/learn/create-custom-tools", + "v1.15.13/en/learn/custom-llm", + "v1.15.13/en/learn/custom-manager-agent", + "v1.15.13/en/learn/customizing-agents", + "v1.15.13/en/learn/dalle-image-generation", + "v1.15.13/en/learn/force-tool-output-as-result", + "v1.15.13/en/learn/hierarchical-process", + "v1.15.13/en/learn/human-input-on-execution", + "v1.15.13/en/learn/human-in-the-loop", + "v1.15.13/en/learn/human-feedback-in-flows", + "v1.15.13/en/learn/kickoff-async", + "v1.15.13/en/learn/kickoff-for-each", + "v1.15.13/en/learn/streaming-runtime-contract", + "v1.15.13/en/learn/consuming-streams", + "v1.15.13/en/learn/llm-connections", + "v1.15.13/en/learn/litellm-removal-guide", + "v1.15.13/en/learn/multimodal-agents", + "v1.15.13/en/learn/replay-tasks-from-latest-crew-kickoff", + "v1.15.13/en/learn/sequential-process", + "v1.15.13/en/learn/using-annotations", + { + "group": "Execution Hooks", + "pages": [ + "v1.15.13/en/learn/execution-hooks", + "v1.15.13/en/learn/llm-hooks", + "v1.15.13/en/learn/tool-hooks", + "v1.15.13/en/learn/execution-boundary-hooks", + "v1.15.13/en/learn/step-hooks", + "v1.15.13/en/learn/before-and-after-kickoff-hooks" + ] + } + ] + }, + { + "group": "Telemetry", + "pages": [ + "v1.15.13/en/telemetry" + ] + } + ] + }, + { + "tab": "AMP", + "icon": "briefcase", + "href": "https://docs-platform.crewai.com/platform/en/introduction" + }, + { + "tab": "API Reference", + "icon": "magnifying-glass", + "groups": [ + { + "group": "Getting Started", + "pages": [ + "v1.15.13/en/api-reference/introduction", + "v1.15.13/en/api-reference/inputs", + "v1.15.13/en/api-reference/kickoff", + "v1.15.13/en/api-reference/resume", + "v1.15.13/en/api-reference/status" + ] + } + ] + }, + { + "tab": "Examples", + "icon": "code", + "groups": [ + { + "group": "Examples", + "pages": [ + "v1.15.13/en/examples/example", + "v1.15.13/en/examples/cookbooks" + ] + } + ] + }, + { + "tab": "Changelog", + "icon": "clock", + "groups": [ + { + "group": "Release Notes", + "pages": [ + "v1.15.13/en/changelog" + ] + } + ] + } + ], + "tag": "Latest", + "default": true + }, { "version": "v1.15.12", "tabs": [ @@ -832,9 +1223,7 @@ } ] } - ], - "tag": "Latest", - "default": true + ] }, { "version": "v1.15.11", @@ -11676,6 +12065,364 @@ ], "tag": "Edge" }, + { + "version": "v1.15.13", + "tabs": [ + { + "tab": "Início", + "icon": "house", + "groups": [ + { + "group": "Bem-vindo", + "pages": [ + "v1.15.13/pt-BR/index" + ] + } + ] + }, + { + "tab": "Documentação", + "icon": "book-open", + "groups": [ + { + "group": "Começando", + "pages": [ + "v1.15.13/pt-BR/introduction", + "v1.15.13/pt-BR/guides/coding-tools/build-with-ai", + "v1.15.13/pt-BR/skills", + "v1.15.13/pt-BR/installation", + "v1.15.13/pt-BR/quickstart" + ] + }, + { + "group": "Guias", + "pages": [ + { + "group": "Estratégia", + "icon": "compass", + "pages": [ + "v1.15.13/pt-BR/guides/concepts/evaluating-use-cases" + ] + }, + { + "group": "Agentes", + "icon": "user", + "pages": [ + "v1.15.13/pt-BR/guides/agents/crafting-effective-agents" + ] + }, + { + "group": "Crews", + "icon": "users", + "pages": [ + "v1.15.13/pt-BR/guides/crews/first-crew" + ] + }, + { + "group": "Flows", + "icon": "code-branch", + "pages": [ + "v1.15.13/pt-BR/guides/flows/first-flow", + "v1.15.13/pt-BR/guides/flows/mastering-flow-state", + "v1.15.13/pt-BR/guides/flows/conversational-flows", + "v1.15.13/pt-BR/guides/flows/inputs-id-deprecation" + ] + }, + { + "group": "Ferramentas", + "icon": "wrench", + "pages": [ + "v1.15.13/pt-BR/guides/tools/publish-custom-tools" + ] + }, + { + "group": "Ferramentas de Codificação", + "icon": "terminal", + "pages": [ + "v1.15.13/pt-BR/guides/coding-tools/agents-md" + ] + }, + { + "group": "Avançado", + "icon": "gear", + "pages": [ + "v1.15.13/pt-BR/guides/advanced/customizing-prompts", + "v1.15.13/pt-BR/guides/advanced/fingerprinting" + ] + }, + { + "group": "Migração", + "icon": "shuffle", + "pages": [ + "v1.15.13/pt-BR/guides/migration/migrating-from-langgraph" + ] + } + ] + }, + { + "group": "Conceitos-Chave", + "pages": [ + "v1.15.13/pt-BR/concepts/agents", + "v1.15.13/pt-BR/concepts/agent-capabilities", + "v1.15.13/pt-BR/concepts/tasks", + "v1.15.13/pt-BR/concepts/crews", + "v1.15.13/pt-BR/concepts/flows", + "v1.15.13/pt-BR/concepts/production-architecture", + "v1.15.13/pt-BR/concepts/knowledge", + "v1.15.13/pt-BR/concepts/skills", + "v1.15.13/pt-BR/concepts/llms", + "v1.15.13/pt-BR/concepts/files", + "v1.15.13/pt-BR/concepts/processes", + "v1.15.13/pt-BR/concepts/collaboration", + "v1.15.13/pt-BR/concepts/training", + "v1.15.13/pt-BR/concepts/memory", + "v1.15.13/pt-BR/concepts/reasoning", + "v1.15.13/pt-BR/concepts/planning", + "v1.15.13/pt-BR/concepts/testing", + "v1.15.13/pt-BR/concepts/cli", + "v1.15.13/pt-BR/concepts/tools", + "v1.15.13/pt-BR/concepts/event-listener", + "v1.15.13/pt-BR/concepts/checkpointing" + ] + }, + { + "group": "Integração MCP", + "pages": [ + "v1.15.13/pt-BR/mcp/overview", + "v1.15.13/pt-BR/mcp/dsl-integration", + "v1.15.13/pt-BR/mcp/stdio", + "v1.15.13/pt-BR/mcp/sse", + "v1.15.13/pt-BR/mcp/streamable-http", + "v1.15.13/pt-BR/mcp/multiple-servers", + "v1.15.13/pt-BR/mcp/security" + ] + }, + { + "group": "Ferramentas", + "pages": [ + "v1.15.13/pt-BR/tools/overview", + { + "group": "Arquivo & Documento", + "icon": "folder-open", + "pages": [ + "v1.15.13/pt-BR/tools/file-document/overview", + "v1.15.13/pt-BR/tools/file-document/filereadtool", + "v1.15.13/pt-BR/tools/file-document/filewritetool", + "v1.15.13/pt-BR/tools/file-document/pdfsearchtool", + "v1.15.13/pt-BR/tools/file-document/docxsearchtool", + "v1.15.13/pt-BR/tools/file-document/mdxsearchtool", + "v1.15.13/pt-BR/tools/file-document/xmlsearchtool", + "v1.15.13/pt-BR/tools/file-document/txtsearchtool", + "v1.15.13/pt-BR/tools/file-document/jsonsearchtool", + "v1.15.13/pt-BR/tools/file-document/csvsearchtool", + "v1.15.13/pt-BR/tools/file-document/directorysearchtool", + "v1.15.13/pt-BR/tools/file-document/directoryreadtool" + ] + }, + { + "group": "Web Scraping & Navegação", + "icon": "globe", + "pages": [ + "v1.15.13/pt-BR/tools/web-scraping/overview", + "v1.15.13/pt-BR/tools/web-scraping/scrapewebsitetool", + "v1.15.13/pt-BR/tools/web-scraping/scrapeelementfromwebsitetool", + "v1.15.13/pt-BR/tools/web-scraping/scrapflyscrapetool", + "v1.15.13/pt-BR/tools/web-scraping/seleniumscrapingtool", + "v1.15.13/pt-BR/tools/web-scraping/scrapegraphscrapetool", + "v1.15.13/pt-BR/tools/web-scraping/spidertool", + "v1.15.13/pt-BR/tools/web-scraping/browserbaseloadtool", + "v1.15.13/pt-BR/tools/web-scraping/hyperbrowserloadtool", + "v1.15.13/pt-BR/tools/web-scraping/stagehandtool", + "v1.15.13/pt-BR/tools/web-scraping/firecrawlcrawlwebsitetool", + "v1.15.13/pt-BR/tools/web-scraping/firecrawlscrapewebsitetool", + "v1.15.13/pt-BR/tools/web-scraping/oxylabsscraperstool" + ] + }, + { + "group": "Pesquisa", + "icon": "magnifying-glass", + "pages": [ + "v1.15.13/pt-BR/tools/search-research/overview", + "v1.15.13/pt-BR/tools/search-research/serperdevtool", + "v1.15.13/pt-BR/tools/search-research/bravesearchtool", + "v1.15.13/pt-BR/tools/search-research/exasearchtool", + "v1.15.13/pt-BR/tools/search-research/linkupsearchtool", + "v1.15.13/pt-BR/tools/search-research/githubsearchtool", + "v1.15.13/pt-BR/tools/search-research/websitesearchtool", + "v1.15.13/pt-BR/tools/search-research/codedocssearchtool", + "v1.15.13/pt-BR/tools/search-research/youtubechannelsearchtool", + "v1.15.13/pt-BR/tools/search-research/youtubevideosearchtool" + ] + }, + { + "group": "Dados", + "icon": "database", + "pages": [ + "v1.15.13/pt-BR/tools/database-data/overview", + "v1.15.13/pt-BR/tools/database-data/mysqltool", + "v1.15.13/pt-BR/tools/database-data/pgsearchtool", + "v1.15.13/pt-BR/tools/database-data/snowflakesearchtool", + "v1.15.13/pt-BR/tools/database-data/nl2sqltool", + "v1.15.13/pt-BR/tools/database-data/qdrantvectorsearchtool", + "v1.15.13/pt-BR/tools/database-data/weaviatevectorsearchtool" + ] + }, + { + "group": "IA & Machine Learning", + "icon": "brain", + "pages": [ + "v1.15.13/pt-BR/tools/ai-ml/overview", + "v1.15.13/pt-BR/tools/ai-ml/dalletool", + "v1.15.13/pt-BR/tools/ai-ml/visiontool", + "v1.15.13/pt-BR/tools/ai-ml/aimindtool", + "v1.15.13/pt-BR/tools/ai-ml/llamaindextool", + "v1.15.13/pt-BR/tools/ai-ml/langchaintool", + "v1.15.13/pt-BR/tools/ai-ml/ragtool", + "v1.15.13/pt-BR/tools/ai-ml/codeinterpretertool", + "v1.15.13/pt-BR/tools/ai-ml/daytona" + ] + }, + { + "group": "Cloud & Armazenamento", + "icon": "cloud", + "pages": [ + "v1.15.13/pt-BR/tools/cloud-storage/overview", + "v1.15.13/pt-BR/tools/cloud-storage/s3readertool", + "v1.15.13/pt-BR/tools/cloud-storage/s3writertool", + "v1.15.13/pt-BR/tools/cloud-storage/bedrockkbretriever" + ] + }, + { + "group": "Integrations", + "icon": "plug", + "pages": [ + "v1.15.13/pt-BR/tools/integration/overview", + "v1.15.13/pt-BR/tools/integration/bedrockinvokeagenttool", + "v1.15.13/pt-BR/tools/integration/crewaiautomationtool" + ] + }, + { + "group": "Automação", + "icon": "bolt", + "pages": [ + "v1.15.13/pt-BR/tools/automation/overview", + "v1.15.13/pt-BR/tools/automation/apifyactorstool", + "v1.15.13/pt-BR/tools/automation/composiotool", + "v1.15.13/pt-BR/tools/automation/multiontool" + ] + } + ] + }, + { + "group": "Observabilidade", + "pages": [ + "v1.15.13/pt-BR/observability/tracing", + "v1.15.13/pt-BR/observability/overview", + "v1.15.13/pt-BR/observability/arize-phoenix", + "v1.15.13/pt-BR/observability/braintrust", + "v1.15.13/pt-BR/observability/datadog", + "v1.15.13/pt-BR/observability/galileo", + "v1.15.13/pt-BR/observability/langdb", + "v1.15.13/pt-BR/observability/langfuse", + "v1.15.13/pt-BR/observability/langtrace", + "v1.15.13/pt-BR/observability/maxim", + "v1.15.13/pt-BR/observability/mlflow", + "v1.15.13/pt-BR/observability/openlit", + "v1.15.13/pt-BR/observability/opik", + "v1.15.13/pt-BR/observability/patronus-evaluation", + "v1.15.13/pt-BR/observability/portkey", + "v1.15.13/pt-BR/observability/weave", + "v1.15.13/pt-BR/observability/truefoundry" + ] + }, + { + "group": "Aprenda", + "pages": [ + "v1.15.13/pt-BR/learn/overview", + "v1.15.13/pt-BR/learn/llm-selection-guide", + "v1.15.13/pt-BR/learn/conditional-tasks", + "v1.15.13/pt-BR/learn/coding-agents", + "v1.15.13/pt-BR/learn/create-custom-tools", + "v1.15.13/pt-BR/learn/custom-llm", + "v1.15.13/pt-BR/learn/custom-manager-agent", + "v1.15.13/pt-BR/learn/customizing-agents", + "v1.15.13/pt-BR/learn/dalle-image-generation", + "v1.15.13/pt-BR/learn/force-tool-output-as-result", + "v1.15.13/pt-BR/learn/hierarchical-process", + "v1.15.13/pt-BR/learn/human-input-on-execution", + "v1.15.13/pt-BR/learn/human-in-the-loop", + "v1.15.13/pt-BR/learn/human-feedback-in-flows", + "v1.15.13/pt-BR/learn/kickoff-async", + "v1.15.13/pt-BR/learn/kickoff-for-each", + "v1.15.13/pt-BR/learn/streaming-runtime-contract", + "v1.15.13/pt-BR/learn/llm-connections", + "v1.15.13/pt-BR/learn/multimodal-agents", + "v1.15.13/pt-BR/learn/replay-tasks-from-latest-crew-kickoff", + "v1.15.13/pt-BR/learn/sequential-process", + "v1.15.13/pt-BR/learn/using-annotations", + "v1.15.13/pt-BR/learn/execution-hooks", + "v1.15.13/pt-BR/learn/llm-hooks", + "v1.15.13/pt-BR/learn/tool-hooks" + ] + }, + { + "group": "Telemetria", + "pages": [ + "v1.15.13/pt-BR/telemetry" + ] + } + ] + }, + { + "tab": "AMP", + "icon": "briefcase", + "href": "https://docs-platform.crewai.com/platform/pt-BR/introduction" + }, + { + "tab": "Referência da API", + "icon": "magnifying-glass", + "groups": [ + { + "group": "Começando", + "pages": [ + "v1.15.13/pt-BR/api-reference/introduction", + "v1.15.13/pt-BR/api-reference/inputs", + "v1.15.13/pt-BR/api-reference/kickoff", + "v1.15.13/pt-BR/api-reference/resume", + "v1.15.13/pt-BR/api-reference/status" + ] + } + ] + }, + { + "tab": "Exemplos", + "icon": "code", + "groups": [ + { + "group": "Exemplos", + "pages": [ + "v1.15.13/pt-BR/examples/example", + "v1.15.13/pt-BR/examples/cookbooks" + ] + } + ] + }, + { + "tab": "Notas de Versão", + "icon": "clock", + "groups": [ + { + "group": "Notas de Versão", + "pages": [ + "v1.15.13/pt-BR/changelog" + ] + } + ] + } + ], + "tag": "Latest", + "default": true + }, { "version": "v1.15.12", "tabs": [ @@ -12030,9 +12777,7 @@ } ] } - ], - "tag": "Latest", - "default": true + ] }, { "version": "v1.15.11", @@ -22254,6 +22999,376 @@ ], "tag": "Edge" }, + { + "version": "v1.15.13", + "tabs": [ + { + "tab": "홈", + "icon": "house", + "groups": [ + { + "group": "환영합니다", + "pages": [ + "v1.15.13/ko/index" + ] + } + ] + }, + { + "tab": "기술 문서", + "icon": "book-open", + "groups": [ + { + "group": "시작 안내", + "pages": [ + "v1.15.13/ko/introduction", + "v1.15.13/ko/guides/coding-tools/build-with-ai", + "v1.15.13/ko/skills", + "v1.15.13/ko/installation", + "v1.15.13/ko/quickstart" + ] + }, + { + "group": "가이드", + "pages": [ + { + "group": "전략", + "icon": "compass", + "pages": [ + "v1.15.13/ko/guides/concepts/evaluating-use-cases" + ] + }, + { + "group": "에이전트 (Agents)", + "icon": "user", + "pages": [ + "v1.15.13/ko/guides/agents/crafting-effective-agents" + ] + }, + { + "group": "크루 (Crews)", + "icon": "users", + "pages": [ + "v1.15.13/ko/guides/crews/first-crew" + ] + }, + { + "group": "플로우 (Flows)", + "icon": "code-branch", + "pages": [ + "v1.15.13/ko/guides/flows/first-flow", + "v1.15.13/ko/guides/flows/mastering-flow-state", + "v1.15.13/ko/guides/flows/conversational-flows", + "v1.15.13/ko/guides/flows/inputs-id-deprecation" + ] + }, + { + "group": "도구", + "icon": "wrench", + "pages": [ + "v1.15.13/ko/guides/tools/publish-custom-tools" + ] + }, + { + "group": "코딩 도구", + "icon": "terminal", + "pages": [ + "v1.15.13/ko/guides/coding-tools/agents-md" + ] + }, + { + "group": "고급", + "icon": "gear", + "pages": [ + "v1.15.13/ko/guides/advanced/customizing-prompts", + "v1.15.13/ko/guides/advanced/fingerprinting" + ] + }, + { + "group": "마이그레이션", + "icon": "shuffle", + "pages": [ + "v1.15.13/ko/guides/migration/migrating-from-langgraph" + ] + } + ] + }, + { + "group": "핵심 개념", + "pages": [ + "v1.15.13/ko/concepts/agents", + "v1.15.13/ko/concepts/tasks", + "v1.15.13/ko/concepts/agent-capabilities", + "v1.15.13/ko/concepts/crews", + "v1.15.13/ko/concepts/flows", + "v1.15.13/ko/concepts/production-architecture", + "v1.15.13/ko/concepts/knowledge", + "v1.15.13/ko/concepts/skills", + "v1.15.13/ko/concepts/llms", + "v1.15.13/ko/concepts/files", + "v1.15.13/ko/concepts/processes", + "v1.15.13/ko/concepts/collaboration", + "v1.15.13/ko/concepts/training", + "v1.15.13/ko/concepts/memory", + "v1.15.13/ko/concepts/reasoning", + "v1.15.13/ko/concepts/planning", + "v1.15.13/ko/concepts/testing", + "v1.15.13/ko/concepts/cli", + "v1.15.13/ko/concepts/tools", + "v1.15.13/ko/concepts/event-listener", + "v1.15.13/ko/concepts/checkpointing" + ] + }, + { + "group": "MCP 통합", + "pages": [ + "v1.15.13/ko/mcp/overview", + "v1.15.13/ko/mcp/dsl-integration", + "v1.15.13/ko/mcp/stdio", + "v1.15.13/ko/mcp/sse", + "v1.15.13/ko/mcp/streamable-http", + "v1.15.13/ko/mcp/multiple-servers", + "v1.15.13/ko/mcp/security" + ] + }, + { + "group": "도구 (Tools)", + "pages": [ + "v1.15.13/ko/tools/overview", + { + "group": "파일 & 문서", + "icon": "folder-open", + "pages": [ + "v1.15.13/ko/tools/file-document/overview", + "v1.15.13/ko/tools/file-document/filereadtool", + "v1.15.13/ko/tools/file-document/filewritetool", + "v1.15.13/ko/tools/file-document/pdfsearchtool", + "v1.15.13/ko/tools/file-document/docxsearchtool", + "v1.15.13/ko/tools/file-document/mdxsearchtool", + "v1.15.13/ko/tools/file-document/xmlsearchtool", + "v1.15.13/ko/tools/file-document/txtsearchtool", + "v1.15.13/ko/tools/file-document/jsonsearchtool", + "v1.15.13/ko/tools/file-document/csvsearchtool", + "v1.15.13/ko/tools/file-document/directorysearchtool", + "v1.15.13/ko/tools/file-document/directoryreadtool", + "v1.15.13/ko/tools/file-document/ocrtool", + "v1.15.13/ko/tools/file-document/pdf-text-writing-tool" + ] + }, + { + "group": "웹 스크래핑 & 브라우징", + "icon": "globe", + "pages": [ + "v1.15.13/ko/tools/web-scraping/overview", + "v1.15.13/ko/tools/web-scraping/scrapewebsitetool", + "v1.15.13/ko/tools/web-scraping/scrapeelementfromwebsitetool", + "v1.15.13/ko/tools/web-scraping/scrapflyscrapetool", + "v1.15.13/ko/tools/web-scraping/seleniumscrapingtool", + "v1.15.13/ko/tools/web-scraping/scrapegraphscrapetool", + "v1.15.13/ko/tools/web-scraping/spidertool", + "v1.15.13/ko/tools/web-scraping/browserbaseloadtool", + "v1.15.13/ko/tools/web-scraping/hyperbrowserloadtool", + "v1.15.13/ko/tools/web-scraping/stagehandtool", + "v1.15.13/ko/tools/web-scraping/firecrawlcrawlwebsitetool", + "v1.15.13/ko/tools/web-scraping/firecrawlscrapewebsitetool", + "v1.15.13/ko/tools/web-scraping/oxylabsscraperstool", + "v1.15.13/ko/tools/web-scraping/brightdata-tools" + ] + }, + { + "group": "검색 및 연구", + "icon": "magnifying-glass", + "pages": [ + "v1.15.13/ko/tools/search-research/overview", + "v1.15.13/ko/tools/search-research/serperdevtool", + "v1.15.13/ko/tools/search-research/bravesearchtool", + "v1.15.13/ko/tools/search-research/exasearchtool", + "v1.15.13/ko/tools/search-research/linkupsearchtool", + "v1.15.13/ko/tools/search-research/githubsearchtool", + "v1.15.13/ko/tools/search-research/websitesearchtool", + "v1.15.13/ko/tools/search-research/codedocssearchtool", + "v1.15.13/ko/tools/search-research/youtubechannelsearchtool", + "v1.15.13/ko/tools/search-research/youtubevideosearchtool", + "v1.15.13/ko/tools/search-research/tavilysearchtool", + "v1.15.13/ko/tools/search-research/tavilyextractortool", + "v1.15.13/ko/tools/search-research/tavilyresearchtool", + "v1.15.13/ko/tools/search-research/arxivpapertool", + "v1.15.13/ko/tools/search-research/serpapi-googlesearchtool", + "v1.15.13/ko/tools/search-research/serpapi-googleshoppingtool", + "v1.15.13/ko/tools/search-research/databricks-query-tool" + ] + }, + { + "group": "데이터베이스 & 데이터", + "icon": "database", + "pages": [ + "v1.15.13/ko/tools/database-data/overview", + "v1.15.13/ko/tools/database-data/mysqltool", + "v1.15.13/ko/tools/database-data/pgsearchtool", + "v1.15.13/ko/tools/database-data/snowflakesearchtool", + "v1.15.13/ko/tools/database-data/nl2sqltool", + "v1.15.13/ko/tools/database-data/qdrantvectorsearchtool", + "v1.15.13/ko/tools/database-data/weaviatevectorsearchtool", + "v1.15.13/ko/tools/database-data/mongodbvectorsearchtool", + "v1.15.13/ko/tools/database-data/singlestoresearchtool" + ] + }, + { + "group": "인공지능 & 머신러닝", + "icon": "brain", + "pages": [ + "v1.15.13/ko/tools/ai-ml/overview", + "v1.15.13/ko/tools/ai-ml/dalletool", + "v1.15.13/ko/tools/ai-ml/visiontool", + "v1.15.13/ko/tools/ai-ml/aimindtool", + "v1.15.13/ko/tools/ai-ml/llamaindextool", + "v1.15.13/ko/tools/ai-ml/langchaintool", + "v1.15.13/ko/tools/ai-ml/ragtool", + "v1.15.13/ko/tools/ai-ml/codeinterpretertool" + ] + }, + { + "group": "클라우드 & 스토리지", + "icon": "cloud", + "pages": [ + "v1.15.13/ko/tools/cloud-storage/overview", + "v1.15.13/ko/tools/cloud-storage/s3readertool", + "v1.15.13/ko/tools/cloud-storage/s3writertool", + "v1.15.13/ko/tools/cloud-storage/bedrockkbretriever" + ] + }, + { + "group": "Integrations", + "icon": "plug", + "pages": [ + "v1.15.13/ko/tools/integration/overview", + "v1.15.13/ko/tools/integration/bedrockinvokeagenttool", + "v1.15.13/ko/tools/integration/crewaiautomationtool" + ] + }, + { + "group": "자동화", + "icon": "bolt", + "pages": [ + "v1.15.13/ko/tools/automation/overview", + "v1.15.13/ko/tools/automation/apifyactorstool", + "v1.15.13/ko/tools/automation/composiotool", + "v1.15.13/ko/tools/automation/multiontool", + "v1.15.13/ko/tools/automation/zapieractionstool" + ] + } + ] + }, + { + "group": "Observability", + "pages": [ + "v1.15.13/ko/observability/tracing", + "v1.15.13/ko/observability/overview", + "v1.15.13/ko/observability/arize-phoenix", + "v1.15.13/ko/observability/braintrust", + "v1.15.13/ko/observability/datadog", + "v1.15.13/ko/observability/galileo", + "v1.15.13/ko/observability/langdb", + "v1.15.13/ko/observability/langfuse", + "v1.15.13/ko/observability/langtrace", + "v1.15.13/ko/observability/maxim", + "v1.15.13/ko/observability/mlflow", + "v1.15.13/ko/observability/neatlogs", + "v1.15.13/ko/observability/openlit", + "v1.15.13/ko/observability/opik", + "v1.15.13/ko/observability/patronus-evaluation", + "v1.15.13/ko/observability/portkey", + "v1.15.13/ko/observability/weave" + ] + }, + { + "group": "학습", + "pages": [ + "v1.15.13/ko/learn/overview", + "v1.15.13/ko/learn/llm-selection-guide", + "v1.15.13/ko/learn/conditional-tasks", + "v1.15.13/ko/learn/coding-agents", + "v1.15.13/ko/learn/create-custom-tools", + "v1.15.13/ko/learn/custom-llm", + "v1.15.13/ko/learn/custom-manager-agent", + "v1.15.13/ko/learn/customizing-agents", + "v1.15.13/ko/learn/dalle-image-generation", + "v1.15.13/ko/learn/force-tool-output-as-result", + "v1.15.13/ko/learn/hierarchical-process", + "v1.15.13/ko/learn/human-input-on-execution", + "v1.15.13/ko/learn/human-in-the-loop", + "v1.15.13/ko/learn/human-feedback-in-flows", + "v1.15.13/ko/learn/kickoff-async", + "v1.15.13/ko/learn/kickoff-for-each", + "v1.15.13/ko/learn/streaming-runtime-contract", + "v1.15.13/ko/learn/llm-connections", + "v1.15.13/ko/learn/multimodal-agents", + "v1.15.13/ko/learn/replay-tasks-from-latest-crew-kickoff", + "v1.15.13/ko/learn/sequential-process", + "v1.15.13/ko/learn/using-annotations", + "v1.15.13/ko/learn/execution-hooks", + "v1.15.13/ko/learn/llm-hooks", + "v1.15.13/ko/learn/tool-hooks" + ] + }, + { + "group": "Telemetry", + "pages": [ + "v1.15.13/ko/telemetry" + ] + } + ] + }, + { + "tab": "엔터프라이즈", + "icon": "briefcase", + "href": "https://docs-platform.crewai.com/platform/ko/introduction" + }, + { + "tab": "API 레퍼런스", + "icon": "magnifying-glass", + "groups": [ + { + "group": "시작 안내", + "pages": [ + "v1.15.13/ko/api-reference/introduction", + "v1.15.13/ko/api-reference/inputs", + "v1.15.13/ko/api-reference/kickoff", + "v1.15.13/ko/api-reference/resume", + "v1.15.13/ko/api-reference/status" + ] + } + ] + }, + { + "tab": "예시", + "icon": "code", + "groups": [ + { + "group": "예시", + "pages": [ + "v1.15.13/ko/examples/example", + "v1.15.13/ko/examples/cookbooks" + ] + } + ] + }, + { + "tab": "변경 로그", + "icon": "clock", + "groups": [ + { + "group": "릴리스 노트", + "pages": [ + "v1.15.13/ko/changelog" + ] + } + ] + } + ], + "tag": "Latest", + "default": true + }, { "version": "v1.15.12", "tabs": [ @@ -22620,9 +23735,7 @@ } ] } - ], - "tag": "Latest", - "default": true + ] }, { "version": "v1.15.11", @@ -33180,6 +34293,376 @@ ], "tag": "Edge" }, + { + "version": "v1.15.13", + "tabs": [ + { + "tab": "الرئيسية", + "icon": "house", + "groups": [ + { + "group": "مرحباً", + "pages": [ + "v1.15.13/ar/index" + ] + } + ] + }, + { + "tab": "التقنية التوثيق", + "icon": "book-open", + "groups": [ + { + "group": "البدء", + "pages": [ + "v1.15.13/ar/introduction", + "v1.15.13/ar/guides/coding-tools/build-with-ai", + "v1.15.13/ar/skills", + "v1.15.13/ar/installation", + "v1.15.13/ar/quickstart" + ] + }, + { + "group": "الأدلّة", + "pages": [ + { + "group": "الاستراتيجية", + "icon": "compass", + "pages": [ + "v1.15.13/ar/guides/concepts/evaluating-use-cases" + ] + }, + { + "group": "الوكلاء", + "icon": "user", + "pages": [ + "v1.15.13/ar/guides/agents/crafting-effective-agents" + ] + }, + { + "group": "الطواقم", + "icon": "users", + "pages": [ + "v1.15.13/ar/guides/crews/first-crew" + ] + }, + { + "group": "التدفقات", + "icon": "code-branch", + "pages": [ + "v1.15.13/ar/guides/flows/first-flow", + "v1.15.13/ar/guides/flows/mastering-flow-state", + "v1.15.13/ar/guides/flows/conversational-flows", + "v1.15.13/ar/guides/flows/inputs-id-deprecation" + ] + }, + { + "group": "الأدوات", + "icon": "wrench", + "pages": [ + "v1.15.13/ar/guides/tools/publish-custom-tools" + ] + }, + { + "group": "أدوات البرمجة", + "icon": "terminal", + "pages": [ + "v1.15.13/ar/guides/coding-tools/agents-md" + ] + }, + { + "group": "متقدّم", + "icon": "gear", + "pages": [ + "v1.15.13/ar/guides/advanced/customizing-prompts", + "v1.15.13/ar/guides/advanced/fingerprinting" + ] + }, + { + "group": "الترحيل", + "icon": "shuffle", + "pages": [ + "v1.15.13/ar/guides/migration/migrating-from-langgraph" + ] + } + ] + }, + { + "group": "المفاهيم الأساسية", + "pages": [ + "v1.15.13/ar/concepts/agents", + "v1.15.13/ar/concepts/agent-capabilities", + "v1.15.13/ar/concepts/tasks", + "v1.15.13/ar/concepts/crews", + "v1.15.13/ar/concepts/flows", + "v1.15.13/ar/concepts/production-architecture", + "v1.15.13/ar/concepts/knowledge", + "v1.15.13/ar/concepts/skills", + "v1.15.13/ar/concepts/llms", + "v1.15.13/ar/concepts/files", + "v1.15.13/ar/concepts/processes", + "v1.15.13/ar/concepts/collaboration", + "v1.15.13/ar/concepts/training", + "v1.15.13/ar/concepts/memory", + "v1.15.13/ar/concepts/reasoning", + "v1.15.13/ar/concepts/planning", + "v1.15.13/ar/concepts/testing", + "v1.15.13/ar/concepts/cli", + "v1.15.13/ar/concepts/tools", + "v1.15.13/ar/concepts/event-listener", + "v1.15.13/ar/concepts/checkpointing" + ] + }, + { + "group": "تكامل MCP", + "pages": [ + "v1.15.13/ar/mcp/overview", + "v1.15.13/ar/mcp/dsl-integration", + "v1.15.13/ar/mcp/stdio", + "v1.15.13/ar/mcp/sse", + "v1.15.13/ar/mcp/streamable-http", + "v1.15.13/ar/mcp/multiple-servers", + "v1.15.13/ar/mcp/security" + ] + }, + { + "group": "الأدوات", + "pages": [ + "v1.15.13/ar/tools/overview", + { + "group": "الملفات والمستندات", + "icon": "folder-open", + "pages": [ + "v1.15.13/ar/tools/file-document/overview", + "v1.15.13/ar/tools/file-document/filereadtool", + "v1.15.13/ar/tools/file-document/filewritetool", + "v1.15.13/ar/tools/file-document/pdfsearchtool", + "v1.15.13/ar/tools/file-document/docxsearchtool", + "v1.15.13/ar/tools/file-document/mdxsearchtool", + "v1.15.13/ar/tools/file-document/xmlsearchtool", + "v1.15.13/ar/tools/file-document/txtsearchtool", + "v1.15.13/ar/tools/file-document/jsonsearchtool", + "v1.15.13/ar/tools/file-document/csvsearchtool", + "v1.15.13/ar/tools/file-document/directorysearchtool", + "v1.15.13/ar/tools/file-document/directoryreadtool", + "v1.15.13/ar/tools/file-document/ocrtool", + "v1.15.13/ar/tools/file-document/pdf-text-writing-tool" + ] + }, + { + "group": "استخراج بيانات الويب", + "icon": "globe", + "pages": [ + "v1.15.13/ar/tools/web-scraping/overview", + "v1.15.13/ar/tools/web-scraping/scrapewebsitetool", + "v1.15.13/ar/tools/web-scraping/scrapeelementfromwebsitetool", + "v1.15.13/ar/tools/web-scraping/scrapflyscrapetool", + "v1.15.13/ar/tools/web-scraping/seleniumscrapingtool", + "v1.15.13/ar/tools/web-scraping/scrapegraphscrapetool", + "v1.15.13/ar/tools/web-scraping/spidertool", + "v1.15.13/ar/tools/web-scraping/browserbaseloadtool", + "v1.15.13/ar/tools/web-scraping/hyperbrowserloadtool", + "v1.15.13/ar/tools/web-scraping/stagehandtool", + "v1.15.13/ar/tools/web-scraping/firecrawlcrawlwebsitetool", + "v1.15.13/ar/tools/web-scraping/firecrawlscrapewebsitetool", + "v1.15.13/ar/tools/web-scraping/oxylabsscraperstool", + "v1.15.13/ar/tools/web-scraping/brightdata-tools" + ] + }, + { + "group": "البحث والاستكشاف", + "icon": "magnifying-glass", + "pages": [ + "v1.15.13/ar/tools/search-research/overview", + "v1.15.13/ar/tools/search-research/serperdevtool", + "v1.15.13/ar/tools/search-research/bravesearchtool", + "v1.15.13/ar/tools/search-research/exasearchtool", + "v1.15.13/ar/tools/search-research/linkupsearchtool", + "v1.15.13/ar/tools/search-research/githubsearchtool", + "v1.15.13/ar/tools/search-research/websitesearchtool", + "v1.15.13/ar/tools/search-research/codedocssearchtool", + "v1.15.13/ar/tools/search-research/youtubechannelsearchtool", + "v1.15.13/ar/tools/search-research/youtubevideosearchtool", + "v1.15.13/ar/tools/search-research/tavilysearchtool", + "v1.15.13/ar/tools/search-research/tavilyextractortool", + "v1.15.13/ar/tools/search-research/tavilyresearchtool", + "v1.15.13/ar/tools/search-research/arxivpapertool", + "v1.15.13/ar/tools/search-research/serpapi-googlesearchtool", + "v1.15.13/ar/tools/search-research/serpapi-googleshoppingtool", + "v1.15.13/ar/tools/search-research/databricks-query-tool" + ] + }, + { + "group": "قواعد البيانات", + "icon": "database", + "pages": [ + "v1.15.13/ar/tools/database-data/overview", + "v1.15.13/ar/tools/database-data/mysqltool", + "v1.15.13/ar/tools/database-data/pgsearchtool", + "v1.15.13/ar/tools/database-data/snowflakesearchtool", + "v1.15.13/ar/tools/database-data/nl2sqltool", + "v1.15.13/ar/tools/database-data/qdrantvectorsearchtool", + "v1.15.13/ar/tools/database-data/weaviatevectorsearchtool", + "v1.15.13/ar/tools/database-data/mongodbvectorsearchtool", + "v1.15.13/ar/tools/database-data/singlestoresearchtool" + ] + }, + { + "group": "الذكاء الاصطناعي والتعلّم الآلي", + "icon": "brain", + "pages": [ + "v1.15.13/ar/tools/ai-ml/overview", + "v1.15.13/ar/tools/ai-ml/dalletool", + "v1.15.13/ar/tools/ai-ml/visiontool", + "v1.15.13/ar/tools/ai-ml/aimindtool", + "v1.15.13/ar/tools/ai-ml/llamaindextool", + "v1.15.13/ar/tools/ai-ml/langchaintool", + "v1.15.13/ar/tools/ai-ml/ragtool", + "v1.15.13/ar/tools/ai-ml/codeinterpretertool" + ] + }, + { + "group": "التخزين السحابي", + "icon": "cloud", + "pages": [ + "v1.15.13/ar/tools/cloud-storage/overview", + "v1.15.13/ar/tools/cloud-storage/s3readertool", + "v1.15.13/ar/tools/cloud-storage/s3writertool", + "v1.15.13/ar/tools/cloud-storage/bedrockkbretriever" + ] + }, + { + "group": "Integrations", + "icon": "plug", + "pages": [ + "v1.15.13/ar/tools/integration/overview", + "v1.15.13/ar/tools/integration/bedrockinvokeagenttool", + "v1.15.13/ar/tools/integration/crewaiautomationtool" + ] + }, + { + "group": "الأتمتة", + "icon": "bolt", + "pages": [ + "v1.15.13/ar/tools/automation/overview", + "v1.15.13/ar/tools/automation/apifyactorstool", + "v1.15.13/ar/tools/automation/composiotool", + "v1.15.13/ar/tools/automation/multiontool", + "v1.15.13/ar/tools/automation/zapieractionstool" + ] + } + ] + }, + { + "group": "Observability", + "pages": [ + "v1.15.13/ar/observability/tracing", + "v1.15.13/ar/observability/overview", + "v1.15.13/ar/observability/arize-phoenix", + "v1.15.13/ar/observability/braintrust", + "v1.15.13/ar/observability/datadog", + "v1.15.13/ar/observability/galileo", + "v1.15.13/ar/observability/langdb", + "v1.15.13/ar/observability/langfuse", + "v1.15.13/ar/observability/langtrace", + "v1.15.13/ar/observability/maxim", + "v1.15.13/ar/observability/mlflow", + "v1.15.13/ar/observability/neatlogs", + "v1.15.13/ar/observability/openlit", + "v1.15.13/ar/observability/opik", + "v1.15.13/ar/observability/patronus-evaluation", + "v1.15.13/ar/observability/portkey", + "v1.15.13/ar/observability/weave" + ] + }, + { + "group": "التعلّم", + "pages": [ + "v1.15.13/ar/learn/overview", + "v1.15.13/ar/learn/llm-selection-guide", + "v1.15.13/ar/learn/conditional-tasks", + "v1.15.13/ar/learn/coding-agents", + "v1.15.13/ar/learn/create-custom-tools", + "v1.15.13/ar/learn/custom-llm", + "v1.15.13/ar/learn/custom-manager-agent", + "v1.15.13/ar/learn/customizing-agents", + "v1.15.13/ar/learn/dalle-image-generation", + "v1.15.13/ar/learn/force-tool-output-as-result", + "v1.15.13/ar/learn/hierarchical-process", + "v1.15.13/ar/learn/human-input-on-execution", + "v1.15.13/ar/learn/human-in-the-loop", + "v1.15.13/ar/learn/human-feedback-in-flows", + "v1.15.13/ar/learn/kickoff-async", + "v1.15.13/ar/learn/kickoff-for-each", + "v1.15.13/ar/learn/streaming-runtime-contract", + "v1.15.13/ar/learn/llm-connections", + "v1.15.13/ar/learn/multimodal-agents", + "v1.15.13/ar/learn/replay-tasks-from-latest-crew-kickoff", + "v1.15.13/ar/learn/sequential-process", + "v1.15.13/ar/learn/using-annotations", + "v1.15.13/ar/learn/execution-hooks", + "v1.15.13/ar/learn/llm-hooks", + "v1.15.13/ar/learn/tool-hooks" + ] + }, + { + "group": "Telemetry", + "pages": [ + "v1.15.13/ar/telemetry" + ] + } + ] + }, + { + "tab": "المؤسسات", + "icon": "briefcase", + "href": "https://docs-platform.crewai.com/platform/ar/introduction" + }, + { + "tab": "API المرجع", + "icon": "magnifying-glass", + "groups": [ + { + "group": "البدء", + "pages": [ + "v1.15.13/ar/api-reference/introduction", + "v1.15.13/ar/api-reference/inputs", + "v1.15.13/ar/api-reference/kickoff", + "v1.15.13/ar/api-reference/resume", + "v1.15.13/ar/api-reference/status" + ] + } + ] + }, + { + "tab": "أمثلة", + "icon": "code", + "groups": [ + { + "group": "أمثلة", + "pages": [ + "v1.15.13/ar/examples/example", + "v1.15.13/ar/examples/cookbooks" + ] + } + ] + }, + { + "tab": "التغييرات السجلات", + "icon": "clock", + "groups": [ + { + "group": "سجل التغييرات", + "pages": [ + "v1.15.13/ar/changelog" + ] + } + ] + } + ], + "tag": "Latest", + "default": true + }, { "version": "v1.15.12", "tabs": [ @@ -33546,9 +35029,7 @@ } ] } - ], - "tag": "Latest", - "default": true + ] }, { "version": "v1.15.11", @@ -42425,55 +43906,55 @@ }, { "source": "/api-reference", - "destination": "/v1.15.12/en/api-reference/introduction" + "destination": "/v1.15.13/en/api-reference/introduction" }, { "source": "/introduction", - "destination": "/v1.15.12/en/introduction" + "destination": "/v1.15.13/en/introduction" }, { "source": "/skills", - "destination": "/v1.15.12/en/skills" + "destination": "/v1.15.13/en/skills" }, { "source": "/installation", - "destination": "/v1.15.12/en/installation" + "destination": "/v1.15.13/en/installation" }, { "source": "/quickstart", - "destination": "/v1.15.12/en/quickstart" + "destination": "/v1.15.13/en/quickstart" }, { "source": "/changelog", - "destination": "/v1.15.12/en/changelog" + "destination": "/v1.15.13/en/changelog" }, { "source": "/telemetry", - "destination": "/v1.15.12/en/telemetry" + "destination": "/v1.15.13/en/telemetry" }, { "source": "/concepts/:path*", - "destination": "/v1.15.12/en/concepts/:path*" + "destination": "/v1.15.13/en/concepts/:path*" }, { "source": "/guides/:path*", - "destination": "/v1.15.12/en/guides/:path*" + "destination": "/v1.15.13/en/guides/:path*" }, { "source": "/tools/:path*", - "destination": "/v1.15.12/en/tools/:path*" + "destination": "/v1.15.13/en/tools/:path*" }, { "source": "/learn/:path*", - "destination": "/v1.15.12/en/learn/:path*" + "destination": "/v1.15.13/en/learn/:path*" }, { "source": "/mcp/:path*", - "destination": "/v1.15.12/en/mcp/:path*" + "destination": "/v1.15.13/en/mcp/:path*" }, { "source": "/observability/:path*", - "destination": "/v1.15.12/en/observability/:path*" + "destination": "/v1.15.13/en/observability/:path*" }, { "source": "/enterprise/:path*", @@ -42525,42 +44006,42 @@ }, { "source": "/api-reference/:path*", - "destination": "/v1.15.12/en/api-reference/:path*" + "destination": "/v1.15.13/en/api-reference/:path*" }, { "source": "/en/api-reference", - "destination": "/v1.15.12/en/api-reference/introduction" + "destination": "/v1.15.13/en/api-reference/introduction" }, { "source": "/pt-BR/api-reference", - "destination": "/v1.15.12/pt-BR/api-reference/introduction" + "destination": "/v1.15.13/pt-BR/api-reference/introduction" }, { "source": "/ko/api-reference", - "destination": "/v1.15.12/ko/api-reference/introduction" + "destination": "/v1.15.13/ko/api-reference/introduction" }, { "source": "/examples/:path*", - "destination": "/v1.15.12/en/examples/:path*" + "destination": "/v1.15.13/en/examples/:path*" }, { "source": "/en/:slug*", - "destination": "/v1.15.12/en/:slug*", + "destination": "/v1.15.13/en/:slug*", "permanent": false }, { "source": "/pt-BR/:slug*", - "destination": "/v1.15.12/pt-BR/:slug*", + "destination": "/v1.15.13/pt-BR/:slug*", "permanent": false }, { "source": "/ko/:slug*", - "destination": "/v1.15.12/ko/:slug*", + "destination": "/v1.15.13/ko/:slug*", "permanent": false }, { "source": "/ar/:slug*", - "destination": "/v1.15.12/ar/:slug*", + "destination": "/v1.15.13/ar/:slug*", "permanent": false } ], diff --git a/docs/edge/ar/changelog.mdx b/docs/edge/ar/changelog.mdx index e8cfe2e7b6..5de9f62796 100644 --- a/docs/edge/ar/changelog.mdx +++ b/docs/edge/ar/changelog.mdx @@ -4,6 +4,30 @@ description: "تحديثات المنتج والتحسينات وإصلاحات icon: "clock" mode: "wide" --- + + ## v1.15.13 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.13) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح الحفاظ على مزود النماذج الموجهة بواسطة LiteLLM. + - تعزيز نماذج حدث LLM الهشة. + - إصلاح التقارير الناقصة لاستخدام رموز التخزين المؤقت من Anthropic. + - ترقية h2 إلى الإصدار 4.4.1 لمعالجة ثغرة الأمان GHSA-6hr6-w5qg-qmwg. + + ### الوثائق + - إضافة سير العمل DOCS_TRANSLATIONS لمزامنة المواقع. + - إصلاح الروابط المعطلة في README، وفهرس المحتويات، وإرشادات المساهمة. + - لقطة وتغيير سجل الإصدار 1.15.12. + + ## المساهمون + + @Vidit-Ostwal, @joaomdmoura, @lucasgomide, @theCyberTech + + + ## v1.15.12 diff --git a/docs/edge/en/changelog.mdx b/docs/edge/en/changelog.mdx index bd70ca1709..7978807dc8 100644 --- a/docs/edge/en/changelog.mdx +++ b/docs/edge/en/changelog.mdx @@ -4,6 +4,30 @@ description: "Product updates, improvements, and bug fixes for CrewAI" icon: "clock" mode: "wide" --- + + ## v1.15.13 + + [View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.13) + + ## What's Changed + + ### Bug Fixes + - Fix preservation of provider on LiteLLM-routed models. + - Harden brittle LLM event-bus mocks. + - Fix underreporting of Anthropic cache token usage. + - Bump h2 to version 4.4.1 to address security vulnerability GHSA-6hr6-w5qg-qmwg. + + ### Documentation + - Add DOCS_TRANSLATIONS workflow for locale synchronization. + - Fix broken README links, table of contents, and contribution guidance. + - Snapshot and changelog for version 1.15.12. + + ## Contributors + + @Vidit-Ostwal, @joaomdmoura, @lucasgomide, @theCyberTech + + + ## v1.15.12 diff --git a/docs/edge/ko/changelog.mdx b/docs/edge/ko/changelog.mdx index 27fb4d19ad..9c38357e44 100644 --- a/docs/edge/ko/changelog.mdx +++ b/docs/edge/ko/changelog.mdx @@ -4,6 +4,30 @@ description: "CrewAI의 제품 업데이트, 개선 사항 및 버그 수정" icon: "clock" mode: "wide" --- + + ## v1.15.13 + + [GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.15.13) + + ## 변경 사항 + + ### 버그 수정 + - LiteLLM 라우팅 모델에서 제공자의 보존 문제 수정. + - 취약한 LLM 이벤트 버스 모의 객체 강화. + - Anthropic 캐시 토큰 사용량의 과소 보고 문제 수정. + - 보안 취약점 GHSA-6hr6-w5qg-qmwg를 해결하기 위해 h2를 버전 4.4.1로 업데이트. + + ### 문서 + - 로케일 동기화를 위한 DOCS_TRANSLATIONS 워크플로 추가. + - 깨진 README 링크, 목차 및 기여 가이드 수정. + - 버전 1.15.12에 대한 스냅샷 및 변경 로그. + + ## 기여자 + + @Vidit-Ostwal, @joaomdmoura, @lucasgomide, @theCyberTech + + + ## v1.15.12 diff --git a/docs/edge/pt-BR/changelog.mdx b/docs/edge/pt-BR/changelog.mdx index c753e9d3bc..a589fad5b3 100644 --- a/docs/edge/pt-BR/changelog.mdx +++ b/docs/edge/pt-BR/changelog.mdx @@ -4,6 +4,30 @@ description: "Atualizações de produto, melhorias e correções do CrewAI" icon: "clock" mode: "wide" --- + + ## v1.15.13 + + [Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.13) + + ## O que Mudou + + ### Correções de Bugs + - Corrigir a preservação do provedor em modelos roteados por LiteLLM. + - Fortalecer os mocks do barramento de eventos LLM que são frágeis. + - Corrigir a subnotificação do uso de tokens de cache da Anthropic. + - Atualizar o h2 para a versão 4.4.1 para resolver a vulnerabilidade de segurança GHSA-6hr6-w5qg-qmwg. + + ### Documentação + - Adicionar o fluxo de trabalho DOCS_TRANSLATIONS para sincronização de locais. + - Corrigir links quebrados no README, tabela de conteúdos e orientações de contribuição. + - Snapshot e changelog para a versão 1.15.12. + + ## Contributors + + @Vidit-Ostwal, @joaomdmoura, @lucasgomide, @theCyberTech + + + ## v1.15.12 diff --git a/docs/v1.15.13/ar/api-reference/inputs.mdx b/docs/v1.15.13/ar/api-reference/inputs.mdx new file mode 100644 index 0000000000..4cbd43f094 --- /dev/null +++ b/docs/v1.15.13/ar/api-reference/inputs.mdx @@ -0,0 +1,8 @@ +--- +title: "GET /inputs" +description: "الحصول على المدخلات المطلوبة لطاقمك" +openapi: "/v1.15.13/enterprise-api.en.yaml GET /inputs" +mode: "wide" +--- + + diff --git a/docs/v1.15.13/ar/api-reference/introduction.mdx b/docs/v1.15.13/ar/api-reference/introduction.mdx new file mode 100644 index 0000000000..60f7bb118b --- /dev/null +++ b/docs/v1.15.13/ar/api-reference/introduction.mdx @@ -0,0 +1,135 @@ +--- +title: "مقدمة" +description: "المرجع الكامل لواجهة برمجة تطبيقات CrewAI AMP REST" +icon: "code" +mode: "wide" +--- + +# واجهة برمجة تطبيقات CrewAI AMP + +مرحبًا بك في مرجع واجهة برمجة تطبيقات CrewAI AMP. تتيح لك هذه الواجهة التفاعل برمجيًا مع الأطقم المنشورة، مما يمكّنك من دمجها مع تطبيقاتك وسير عملك وخدماتك. + +## البدء السريع + + + + انتقل إلى صفحة تفاصيل طاقمك في لوحة تحكم CrewAI AMP وانسخ رمز Bearer من علامة تبويب الحالة. + + + + استخدم نقطة النهاية `GET /inputs` لمعرفة المعاملات التي يتوقعها طاقمك. + + + + استدعِ `POST /kickoff` مع مدخلاتك لبدء تنفيذ الطاقم واستلام + `kickoff_id`. + + + + استخدم `GET /status/{kickoff_id}` للتحقق من حالة التنفيذ واسترجاع النتائج. + + + +## المصادقة + +تتطلب جميع طلبات API المصادقة باستخدام رمز Bearer. أدرج رمزك في ترويسة `Authorization`: + +```bash +curl -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + https://your-crew-url.crewai.com/inputs +``` + +### أنواع الرموز + +| نوع الرمز | النطاق | حالة الاستخدام | +| :-------------------- | :------------------------ | :----------------------------------------------------------- | +| **Bearer Token** | وصول على مستوى المؤسسة | عمليات الطاقم الكاملة، مثالي للتكامل بين الخوادم | +| **User Bearer Token** | وصول محدد بالمستخدم | صلاحيات محدودة، مناسب للعمليات الخاصة بالمستخدم | + + + يمكنك العثور على كلا نوعي الرموز في علامة تبويب الحالة من صفحة تفاصيل طاقمك في + لوحة تحكم CrewAI AMP. + + +## عنوان URL الأساسي + +لكل طاقم منشور نقطة نهاية API فريدة خاصة به: + +``` +https://your-crew-name.crewai.com +``` + +استبدل `your-crew-name` بعنوان URL الفعلي لطاقمك من لوحة التحكم. + +## سير العمل النموذجي + +1. **الاكتشاف**: استدعِ `GET /inputs` لفهم ما يحتاجه طاقمك +2. **التنفيذ**: أرسل المدخلات عبر `POST /kickoff` لبدء المعالجة +3. **المراقبة**: استعلم عن `GET /status/{kickoff_id}` حتى الاكتمال +4. **النتائج**: استخرج المخرجات النهائية من الاستجابة المكتملة + +## معالجة الأخطاء + +تستخدم الواجهة أكواد حالة HTTP القياسية: + +| الكود | المعنى | +| ----- | :----------------------------------------- | +| `200` | نجاح | +| `400` | طلب غير صالح - تنسيق مدخلات غير صحيح | +| `401` | غير مصرّح - رمز bearer غير صالح | +| `404` | غير موجود - المورد غير موجود | +| `422` | خطأ في التحقق - مدخلات مطلوبة مفقودة | +| `500` | خطأ في الخادم - تواصل مع الدعم | + +## الاختبار التفاعلي + + + **لماذا لا يوجد زر "إرسال"؟** نظرًا لأن كل مستخدم CrewAI AMP لديه عنوان URL + فريد للطاقم، نستخدم **وضع المرجع** بدلاً من بيئة تفاعلية لتجنب + الالتباس. يوضح لك هذا بالضبط كيف يجب أن تبدو الطلبات بدون + أزرار إرسال غير فعالة. + + +تعرض لك كل صفحة نقطة نهاية: + +- **تنسيق الطلب الدقيق** مع جميع المعاملات +- **أمثلة الاستجابة** لحالات النجاح والخطأ +- **عينات الكود** بلغات متعددة (cURL، Python، JavaScript، إلخ) +- **أمثلة المصادقة** بتنسيق رمز Bearer الصحيح + +### **لاختبار واجهتك الفعلية:** + + + + انسخ أمثلة cURL واستبدل العنوان URL + الرمز بقيمك الحقيقية + + + استورد الأمثلة في أداة اختبار API المفضلة لديك + + + +**مثال على سير العمل:** + +1. **انسخ مثال cURL هذا** من أي صفحة نقطة نهاية +2. **استبدل `your-actual-crew-name.crewai.com`** بعنوان URL الحقيقي لطاقمك +3. **استبدل رمز Bearer** برمزك الحقيقي من لوحة التحكم +4. **نفّذ الطلب** في طرفيتك أو عميل API + +## هل تحتاج مساعدة؟ + + + + احصل على مساعدة في تكامل API واستكشاف الأخطاء وإصلاحها + + + إدارة أطقمك وعرض سجلات التنفيذ + + diff --git a/docs/v1.15.13/ar/api-reference/kickoff.mdx b/docs/v1.15.13/ar/api-reference/kickoff.mdx new file mode 100644 index 0000000000..d82c88a62c --- /dev/null +++ b/docs/v1.15.13/ar/api-reference/kickoff.mdx @@ -0,0 +1,8 @@ +--- +title: "POST /kickoff" +description: "بدء تنفيذ الطاقم" +openapi: "/v1.15.13/enterprise-api.en.yaml POST /kickoff" +mode: "wide" +--- + + diff --git a/docs/v1.15.13/ar/api-reference/resume.mdx b/docs/v1.15.13/ar/api-reference/resume.mdx new file mode 100644 index 0000000000..8962c91f7b --- /dev/null +++ b/docs/v1.15.13/ar/api-reference/resume.mdx @@ -0,0 +1,6 @@ +--- +title: "POST /resume" +description: "استئناف تنفيذ الطاقم مع التغذية الراجعة البشرية" +openapi: "/v1.15.13/enterprise-api.en.yaml POST /resume" +mode: "wide" +--- diff --git a/docs/v1.15.13/ar/api-reference/status.mdx b/docs/v1.15.13/ar/api-reference/status.mdx new file mode 100644 index 0000000000..eb134dbdf2 --- /dev/null +++ b/docs/v1.15.13/ar/api-reference/status.mdx @@ -0,0 +1,6 @@ +--- +title: "GET /status/{kickoff_id}" +description: "الحصول على حالة التنفيذ" +openapi: "/v1.15.13/enterprise-api.en.yaml GET /status/{kickoff_id}" +mode: "wide" +--- diff --git a/docs/v1.15.13/ar/changelog.mdx b/docs/v1.15.13/ar/changelog.mdx new file mode 100644 index 0000000000..5de9f62796 --- /dev/null +++ b/docs/v1.15.13/ar/changelog.mdx @@ -0,0 +1,2385 @@ +--- +title: "سجل التغييرات" +description: "تحديثات المنتج والتحسينات وإصلاحات الأخطاء لـ CrewAI" +icon: "clock" +mode: "wide" +--- + + ## v1.15.13 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.13) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح الحفاظ على مزود النماذج الموجهة بواسطة LiteLLM. + - تعزيز نماذج حدث LLM الهشة. + - إصلاح التقارير الناقصة لاستخدام رموز التخزين المؤقت من Anthropic. + - ترقية h2 إلى الإصدار 4.4.1 لمعالجة ثغرة الأمان GHSA-6hr6-w5qg-qmwg. + + ### الوثائق + - إضافة سير العمل DOCS_TRANSLATIONS لمزامنة المواقع. + - إصلاح الروابط المعطلة في README، وفهرس المحتويات، وإرشادات المساهمة. + - لقطة وتغيير سجل الإصدار 1.15.12. + + ## المساهمون + + @Vidit-Ostwal, @joaomdmoura, @lucasgomide, @theCyberTech + + + + + ## v1.15.12 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.12) + + ## ما الذي تغير + + ### الميزات + - زيادة إصدار Flow canary عند الإصدار + - إضافة URLReadTool لقراءة عناوين URL العشوائية + - إضافة بيانات التعريف الخاصة بالتطبيق إلى أدوات إجراءات المنصة + - توحيد الهيكل تحت `crewai create ` + + ### إصلاحات الأخطاء + - توضيح أخطاء تصادم أسماء المسارات/المعالجين في المحادثات + + ### الوثائق + - تحديث ملف AGENTS.md للهيكل الموحد لأداة سطر الأوامر لإنشاء + + ### تغييرات كبيرة + - لا شيء + + ## المساهمون + + @Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech + + + + + ## v1.15.11 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.11) + + ## ما الذي تغير + + ### الميزات + - تتبع عمليات إرسال خطاف الاعتراض في التلميتري + - إضافة project_id لربط استخدام OSS بحساب المؤسسة + - عرض AMP في AGENTS.md واكتشاف وكلاء الترميز في التلميتري + - إضافة أداة بحث IBM Db2 + + ### إصلاحات الأخطاء + - مسح تنبيهات تطهير جزء URL غير المكتمل في CodeQL + - تحديث aiohttp وcryptography لمسح ستة تحذيرات GHSA + - الإبلاغ عن خطأ CEL الحقيقي للفشل داخل الأدبيات الخرائطية + - تخطي CI الكود بشكل صحيح لطلبات السحب الخاصة بالوثائق فقط + + ### الوثائق + - لقطة وتغيير السجل للإصدار v1.15.10 + + ## المساهمون + + @PawanThakurIBM, @Vidit-Ostwal, @gabemilani, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech + + + + + ## v1.15.10 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.10) + + ## ما الذي تغير + + ### الميزات + - جمع أحداث استخدام المهارات + + ### الوثائق + - إزالة وثائق AMP التي تم نقلها + - تحديث إرشادات الإبلاغ عن الأمان + - لقطة وتغيير السجل للإصدار v1.15.9 + + ## المساهمون + + @gvieira, @joaomdmoura, @theCyberTech + + + + + ## v1.15.9 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.9) + + ## ما الذي تغير + + ### الميزات + - عرض فشل الأدوات بدلاً من الإبلاغ عنها كنجاح + - إصدار FlowFailedEvent عندما يفشل تنفيذ التدفق + - تنفيذ الكشف التدريجي للمهارات + + ### الوثائق + - تحديث اللقطة وسجل التغييرات للإصدار v1.15.8 + + ## المساهمون + + @github-actions[bot], @joaomdmoura, @lorenzejay, @lucasgomide + + + + + ## v1.15.8 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.8) + + ## ما الذي تغير + + ### الميزات + - إضافة WaitTool لإيقاف التنفيذ في المهام الطويلة. + + ### إصلاحات الأخطاء + - إصلاح كتابات FileWriterTool ومعالجة الحواف الخشنة في أداة الملف. + - وضع E2B_API_KEY كمتغير بيئي مطلوب لأدوات E2B. + + ### الوثائق + - تحديث إرشادات توفر النموذج. + + ## المساهمون + + @github-actions[bot], @joaomdmoura, @lucasgomide, @oalami, @thiagomoretto + + + + + ## v1.15.7 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.7) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - حل مهارات السجل من خلال عميل CrewAI+ الخاص بالوقت الفعلي + - استعادة من أدوات GPT-5.6 + reasoning_effort 400 + - جعل استدعاء الأدوات يعمل على مسار واجهة برمجة التطبيقات Responses + - توجيه النماذج التي تعيد الاستجابات فقط بدلاً من الفشل مع 404 + - رفع bedrock-agentcore لتصحيح CVE-2026-16796 + + ### الرصد + - إصدار أحداث استخدام المهارات في الوقت الفعلي للرصد + + ### الوثائق + - إضافة لقطة وتغيير السجل للإصدار v1.15.7a1 + + ## المساهمون + + @alex-clawd, @joaomdmoura, @lorenzejay + + + + + ## v1.15.7a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.7a1) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح حل مهارات السجل من خلال عميل CrewAI+ الخاص بالوقت الفعلي. + - استعادة الأداء من أخطاء أدوات GPT-5.6 وجهد الاستدلال 400. + - جعل استدعاء الأدوات يعمل على مسار واجهة برمجة التطبيقات للاستجابات. + - توجيه نماذج الاستجابات فقط لمنع أخطاء 404. + - رفع اعتماد bedrock-agentcore لإصلاح CVE-2026-16796. + + ### الرصد + - إصدار أحداث استخدام المهارات في الوقت الفعلي لتحسين الرصد. + + ### الوثائق + - تحديثات لقطة وتغيير للإصدار 1.15.6. + + ## المساهمون + + @alex-clawd, @joaomdmoura, @lorenzejay + + + + + ## v1.15.6 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.6) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح الكشف عن أدوات معاينة Anthropic. + - الحفاظ على أسماء خصائص مخطط الأدوات الصارمة. + - تنفيذ حدث execution_end عند فشل تنفيذ الطاقم والتدفق. + - التعامل مع get_agent غير المتزامن في load_agent_from_repository. + - إصلاح مشكلات حل الاعتماد. + + ### الوثائق + - لقطة وتاريخ التغييرات للإصدار v1.15.5. + + ## المساهمون + + @alex-clawd, @iris-clawd, @lorenzejay, @lucasgomide, @theCyberTech, @vinibrsl + + + + + ## v1.15.5 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.5) + + ## ما الذي تغير + + ### الميزات + - مصادقة تنزيلات سجل المهارات + + ### الوثائق + - تحديث اللقطة وسجل التغييرات للإصدار v1.15.4 + + ## المساهمون + + @vinibrsl + + + + + ## v1.15.4 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.4) + + ## ما الذي تغير + + ### الميزات + - ترقية مستودع المهارات من حالة تجريبية + + ### الوثائق + - إضافة تدفقات في وثائق الاستوديو + + ## المساهمون + + @jessemiller, @joaomdmoura, @vinibrsl + + + + + ## v1.15.3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.3) + + ## ما الذي تغير + + ### الميزات + - إضافة معلمة معرف المنظمة إلى عميل PlusAPI + - إضافة نقاط اعتراض الخطوات وإعادة صياغة توثيق نقاط تنفيذ @on + - توصيل نقاط اعتراض حدود التنفيذ + - إضافة موزع اعتراض عام + - تشغيل التدفقات التصريحية على واجهة المستخدم النصية (خيار الطرية بدون واجهة) + + ### إصلاحات الأخطاء + - مزامنة حدث بدء التنفيذ المكتمل مع نتيجة خطاف OUTPUT + - إصلاح سمات وكيل المستودع الفارغة + - التأكد من أن خطافات after_llm_call لا تكسر تنفيذ الأدوات الأصلية + - تجنب الإضافة المزدوجة لرد الدور عندما يقوم المعالج بقص التاريخ + - جعل تخزين نتائج الأدوات اختيارياً بدلاً من أن يكون مفعلًا بشكل افتراضي + - التوقف عن إعادة كتابة وصف الأداة المؤلف عند الإنشاء + - كشف استخدام الرموز تحت كلا الاسمين في نتائج الوكيل والطاقم + - الإبلاغ عن مقاييس الاستخدام لكل استدعاء في نتائج بدء التنفيذ + - التوقف عن إعادة تشغيل نية الدور السابق عندما تعيد route_turn() قيمة غير صحيحة + + ### الوثائق + - تحديث تجميع خطافات التنفيذ وتوثيق جميع سياقات الخطاف + + ## المساهمون + + @joaomdmoura, @lorenzejay, @lucasgomide, @vinibrsl + + + + + ## v1.15.3a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.3a2) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح تزامن حدث انتهاء الانطلاق مع نتيجة خطاف OUTPUT + + ### الوثائق + - تحديث لقطة الشاشة وسجل التغييرات للإصدار v1.15.3a1 + + ### تحديثات التبعية + - رفع setuptools إلى 0.83.0 لمعالجة PYSEC-2026-3447 + + ## المساهمون + + @lucasgomide, @vinibrsl + + + + + ## v1.15.3a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.3a1) + + ## ما الذي تغير + + ### الميزات + - إضافة معلمة معرف المنظمة إلى عميل PlusAPI. + - إضافة نقاط اعتراض الخطوات وإعادة صياغة وثائق نقاط تنفيذ `@on`. + - توصيل نقاط اعتراض حدود التنفيذ. + - إضافة موصل عام للاعتراضات. + - تشغيل التدفقات التصريحية على واجهة المستخدم النصية (نسخة احتياطية من الطرفية بدون واجهة). + - تحسين عناوين URL المخصصة لـ OpenAI. + + ### إصلاحات الأخطاء + - إصلاح سمات وكيل المستودع الفارغة. + - إصلاح نقاط `after_llm_call` لمنع كسر تنفيذ الأدوات الأصلية. + - إيقاف الإضافة المزدوجة لرد الدور عندما يقوم المعالج بقص التاريخ. + - جعل تخزين نتائج الأدوات اختيارياً بدلاً من أن يكون مفعلًا بشكل افتراضي. + - إيقاف إعادة كتابة وصف الأداة المؤلف عند الإنشاء. + - كشف استخدام الرموز تحت كلا الاسمين في نتائج الوكيل والطاقم. + - الإبلاغ عن مقاييس الاستخدام لكل استدعاء في نتائج البداية. + - إيقاف إعادة تشغيل نية الدور السابق عندما تعيد `route_turn()` قيمة غير صحيحة. + - تصريف الكتابات في الذاكرة قبل أحداث البداية وإكمال التدفق. + + ### الوثائق + - تجميع نقاط تنفيذ الوثائق وتوثيق جميع سياقات الاعتراض. + - تحديث الوثائق لنقاط تنفيذ الاعتراض. + + ## المساهمون + + @joaomdmoura, @lorenzejay, @lucasgomide, @vinibrsl + + + + + ## v1.15.2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.2) + + ## ما الذي تغير + + ### الميزات + - سحب أحدث نماذج LLM ديناميكيًا في معالج الطاقم. + - دعم تعريفات المهارات المضمنة. + - إضافة مهارة تأليف تعريف التدفق المُولد. + - دعم مدخلات إجراءات التدفق المهيكلة. + - إضافة مساعد نصي لمطالبات CEL للتدفق. + - إضافة مساعد نصي لمثال مهارة التدفق. + - تنفيذ إعداد الرسائل ومعالجة التعليقات في AgentExecutor. + - إضافة وكلاء المستودع إلى تعريفات التدفق. + - تعريف بروتوكول إطار البث للتدفقات. + - نوع الأداة والتطبيق في CrewDefinition. + - إعادة توجيه أوامر القالب إلى crewAIInc-fde org. + + ### إصلاحات الأخطاء + - تخزين نموذج كتالوج المفتاح بواسطة مفتاح API الدقيق، تقصير TTL، وتخطي Ollama. + - توحيد دقة مدخلات التدفق لـ `crewai run` والمطالبة من مخطط الحالة. + - حل مشكلات pip-audit لـ onnx 1.22.0 و nltk PYSEC-2026-597. + - التأكد من أننا نكتب الإصدار للتدفقات. + - تضمين aiobotocore في الإضافات الأساسية. + - رفض طرق التدفق ذات الاستماع الذاتي. + - قطع تنقل إصدار الوثائق من Edge حتى لا يتم إسقاط الصفحات الجديدة. + + ### الوثائق + - تحديث اللغة من القواعد إلى السياسات لتتناسب مع تغييرات لوحة المعلومات الجديدة. + - توثيق خيارات وكيل التدفق. + - إضافة وثائق البث إلى التنقل. + - توثيق نوع قاعدة حد التكلفة في وحدة التحكم الخاصة بالوكيل. + - حذف مراجع CREWAI_LOG_FORMAT من دليل Datadog. + + ## المساهمون + + @akaKuruma, @danielfsbarreto, @github-code-quality[bot], @joaomdmoura, @lorenzejay, @lucasgomide, @manisrinivasan2k1, @renatonitta, @vinibrsl + + + + + ## v1.15.2a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.2a2) + + ## ما الذي تغير + + ### الميزات + - إضافة aiobotocore إلى الإضافات الأساسية + - توثيق خيارات وكيل التدفق + - إضافة مساعد نصي إلى مثال مهارة التدفق + - إضافة مساعد نصي لمطالب CEL الخاصة بالتدفق + - إضافة وثائق البث إلى التنقل + + ### إصلاحات الأخطاء + - رفض طرق التدفق ذات الاستماع الذاتي + + ### الوثائق + - تحديث اللقطة وسجل التغييرات للإصدار v1.15.2a1 + - ضغط ملف AGENTS.md + + ## المساهمون + + @akaKuruma, @github-code-quality[bot], @lorenzejay, @vinibrsl + + + + + ## v1.15.2a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.2a1) + + ## ما الذي تغير + + ### الميزات + - إعادة توجيه أوامر القالب إلى منظمة crewAIInc-fde + - دعم تعريفات المهارات المضمنة + - تعريف بروتوكول إطار التدفق للتدفقات + - إضافة أداة النوع والتطبيق في CrewDefinition + - إضافة مهارة تأليف تعريف التدفق المُنشأ + + ### إصلاحات الأخطاء + - قطع تنقل إصدار الوثائق من Edge لمنع فقدان الصفحات الجديدة + + ### الوثائق + - توثيق نوع قاعدة حد التكلفة في وحدة التحكم الخاصة بالوكيل + - إزالة مراجع CREWAI_LOG_FORMAT من دليل Datadog + + ## المساهمون + + @danielfsbarreto, @joaomdmoura, @lorenzejay, @lucasgomide, @vinibrsl + + + + + ## v1.15.1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.1) + + ## ما الذي تغير + + ### الميزات + - تهيئة مستودعات Git للمشاريع المولدة (#6364) + - طلب تعريفات مشروع CrewAI بشكل صريح (#6358) + - فتح صفحة النشر بعد نشر CLI (#6343) + + ### إصلاحات الأخطاء + - إصلاح حل رابط معرف صفحة النشر (#6365) + - إصلاح عرض قالب الطاقم JSON (#6359) + - إصلاح تثبيت إصدار الطاقم JSON (#6342) + - إصلاح تجاوز إعادة التوجيه SSRF في عمليات السحب (#6331) + + ### الوثائق + - تحسين وضع المصدر المفتوح في README (#6363) + - تحسين دعوة العمل لإعداد وكيل البرمجة (#6344) + - إضافة لقطة وتغيير السجل للإصدار 1.15.1a1 (#6362) + + ## المساهمون + + @joaomdmoura, @lorenzejay, @oalami, @theCyberTech, @vinibrsl + + + + + ## v1.15.1a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.1a1) + + ## ما الذي تغير + + ### الميزات + - تتبع بيانات الزر TUI + - يتطلب تعريفات مشروع CrewAI بشكل صريح + - فتح صفحة النشر بعد نشر CLI + + ### إصلاحات الأخطاء + - إصلاح عرض قالب الطاقم بصيغة JSON + - إصلاح تثبيت إصدار الطاقم بصيغة JSON + - إصلاح تجاوز إعادة التوجيه SSRF في عمليات جلب البيانات + + ### الوثائق + - تحسين دعوة إعداد وكيل البرمجة + - لقطة وتغيير السجل للإصدار v1.15.0 + + ## المساهمون + + @joaomdmoura, @lorenzejay, @theCyberTech, @vinibrsl + + + + + ## v1.15.0 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.0) + + ## ما الذي تغير + + ### الميزات + - تتبع استخدام تدفق المحادثات في التليمتري + - دعم تدفقات المحادثات في واجهة سطر الأوامر TUI + - إضافة تحميل تدفق موحد بالإعلان + - إضافة دعم تدفق CLI بالإعلان + - إضافة تعبير "if" اختياري إلى خطوات each.do + - إضافة إجراء عميل فردي إلى تعريفات التدفق + - إضافة إجراءات الطاقم إلى تعريف التدفق + - إضافة تحميل تعريف الطاقم داخل السطر + - إضافة إجراء مركب `each` إلى تعريف التدفق + - تنفيذ دعم وضع DMN في إنشاء الطاقم وتنفيذه + + ### إصلاحات الأخطاء + - إصلاح تطبيق أذونات المالك فقط على ملفات الاعتماد + - إصلاح مدخلات بدء حالة تدفق مخطط JSON + - إصلاح تجاوز مسار الرابط الرمزي في استخراج أرشيف المهارة + - تجميع استخدام الرموز عبر جميع مكالمات LLM + - إزالة أداة Exa المكررة + - حل مشاكل الطاقم JSON + - إصلاح معالجة الطاقم JSON وتعزيز وظيفة إعادة تعيين الذاكرة + + ### الوثائق + - تحديث وثائق التثبيت والبدء السريع لمشاريع الطاقم التي تعتمد على JSON + - إضافة دليل تكامل Datadog مع لوحة عمليات قابلة للاستيراد + - إضافة صفحة استوديو "بطاقة واحدة لكل خطوة" + - إضافة لقطات وتغييرات للإصدارات السابقة التي تؤدي إلى v1.15.0 + + ### الأداء + - تحسين تجربة بدء تشغيل crewai run + - الحفاظ على تقدم طريقة التدفق مرئيًا للطاقم المتداخل + + ### إعادة الهيكلة + - إزالة `StateProxy` من الوصول إلى حالة التدفق + - دمج `crewai run` و `crewai flow kickoff` + - تمييز أنواع حالة تعريف التدفق + - توصيل التكوين والاستمرارية من تعريف التدفق إلى وقت التشغيل + + ## المساهمون + + @gabemilani, @github-code-quality[bot], @greysonlalonde, @iris-clawd, @jessemiller, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech, @vinibrsl + + + + + ## v1.14.8a5 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.8a5) + + ## ما الذي تغير + + ### الميزات + - جعل المراجع التصريحية تعمل عبر التدفقات والفرق (#6326) + + ### إصلاحات الأخطاء + - إصلاح مدخلات بدء حالة تدفق مخطط JSON (#6325) + + ### الوثائق + - وضع بطاقة واحدة لكل خطوة تحت استوديو الفريق وإزالة لافتة التوزيع (AGE-107) (#6317) + - تحديث اللقطة وسجل التغييرات للإصدار v1.14.8a4 (#6319) + + ### إعادة الهيكلة + - إزالة `StateProxy` من الوصول إلى حالة التدفق (#6327) + + ## المساهمون + + @jessemiller, @vinibrsl + + + + + ## v1.14.8a4 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.8a4) + + ## ما الذي تغير + + ### الميزات + - دعم تدفقات المحادثة في واجهة سطر الأوامر TUI. + + ### إصلاحات الأخطاء + - إصلاح مسار التوجيه الرمزي في استخراج أرشيف المهارات. + - التحقق من صحة مسارات تعريف التدفق الإعلاني. + + ### الوثائق + - تحديث اللقطة وسجل التغييرات للإصدار v1.14.8a3. + + ## المساهمون + + @lorenzejay, @theCyberTech, @vinibrsl + + + + + ## v1.14.8a3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.8a3) + + ## ما الذي تغير + + ### الميزات + - إضافة تحميل تدفق موحد إعلاني + - تحسين تجربة بدء تشغيل crewai run + - دمج `crewai run` و `crewai flow kickoff` + - الحفاظ على تقدم طريقة التدفق مرئيًا للفرق المتداخلة + - إضافة دعم واجهة سطر الأوامر الإعلانية للتدفق + - السماح باستخدام `@router()` كطريقة بدء لتدفق + - إضافة مخططات مخرجات مكتوبة لأدوات CrewAI + + ### إصلاحات الأخطاء + - تثبيت opentelemetry على ~=1.42.0 + + ### الوثائق + - إضافة صفحة استوديو "بطاقة واحدة لكل خطوة" + + ## المساهمون + + @jessemiller, @joaomdmoura, @lucasgomide, @vinibrsl + + + + + ## v1.14.8a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.8a2) + + ## ما الذي تغير + + ### الميزات + - إضافة إجراء عميل واحد إلى تعريفات التدفق + - التحقق من تعبيرات CEL للتدفق عند تحميل التعريف + + ### الوثائق + - إضافة دليل تكامل Datadog مع لوحة عمليات قابلة للاستيراد + - تحديث اللقطة وسجل التغييرات للإصدار v1.14.8a1 + + ## المساهمون + + @joaomdmoura, @lucasgomide, @vinibrsl + + + + + ## v1.14.8a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.8a1) + + ## ما الذي تغير + + ### الميزات + - إضافة تعبير if اختياري إلى خطوات each.do + + ### إصلاحات الأخطاء + - إصلاح مشكلات JSON crew + + ### الوثائق + - تحديث snapshot و changelog للإصدار v1.14.8a + + ## المساهمون + + @joaomdmoura, @vinibrsl + + + + + ## v1.14.8a + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.8a) + + ## ما الذي تغير + + ### الميزات + - إضافة إجراء كتلة نصية/كود إلى FlowDefinition + - إضافة إجراءات الطاقم إلى FlowDefinition + - إضافة إجراء مركب `each` إلى FlowDefinition + - تنفيذ دعم وضع DMN في إنشاء الطاقم وتنفيذه + - تحسين وظيفة إعادة تعيين الذاكرة ومعالجة الطاقم بتنسيق JSON + - إضافة تعبيرات إلى إجراءات FlowDefinition + - تنفيذ أدوات تشغيل تعريف التدفق بدون كود Python + - دفع التغذية الراجعة البشرية من تعريف التدفق + - توصيل التكوين والاستمرارية من FlowDefinition إلى وقت التشغيل + - إضافة `crewai run --definition` للتدفقات التصريحية + - دعم تراجع نشر ZIP وتشغيل مشاريع الطاقم بتنسيق JSON + - تقديم الطواقم بتنسيق JSON أولاً + + ### إصلاحات الأخطاء + - إصلاح أداة Exa المكررة + - إصلاح استخدام الرموز المجمعة عبر جميع استدعاءات LLM + - حل المشكلات المتعلقة بتحميل الطاقم ومنطق التحقق + + ### الوثائق + - توثيق حقول FlowDefinition في مخطط JSON + - تحديث وثائق التثبيت والبدء السريع لمشاريع الطاقم بتنسيق JSON أولاً + - تحديث سجل التغييرات والإصدار لـ v1.14.7 + + ## المساهمون + + @gabemilani, @greysonlalonde, @iris-clawd, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech, @vinibrsl + + + + + ## v1.14.7 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.7) + + ## ما الذي تغير + + ### الميزات + - إضافة واجهات خلفية افتراضية قابلة للتوصيل للذاكرة، والمعرفة، وrag، وflow. + - عرض السبب الحقيقي للإنهاء، ومعلمات العينة، وresponse.id في أحداث LLM. + - تصنيف مشغلات DSL كزخارف واعية للمسار. + - إضافة واجهة برمجة تطبيقات الدردشة لتدفقات المحادثة. + - جعل واجهة القفل قابلة للتجاوز. + - بناء FlowDefinition من بيانات التعريف الخاصة بـ Flow DSL. + - إضافة مزود LLM من Snowflake Cortex الأصلي. + - إضافة دعم لملفات الوكلاء المدربين من crew. + + ### إصلاحات الأخطاء + - إصلاح نقطة التحقق لإعادة بناء BaseLLM مخصص كـ LLM ملموس عند الاستعادة. + - تقييد الاستعادة على علامة لمنع اللقطات الحية من إعادة التشغيل كاستئناف. + - تحديد حالة وقت التشغيل لكل تشغيل للحد من النمو وعزل التشغيل المتزامن. + - إصلاح إعدادات التتبع على crewai-login. + - احترام suppress_flow_events لأحداث تنفيذ الطريقة. + - استعادة [project.scripts] في حزمة crewai لتثبيت أداة uv. + - حل مشكلات CVE الخاصة بـ pip-audit لـ aiohttp وdocling وdocling-core. + - إصلاح إدخال الملفات الذي لا يعمل بشكل موثوق. + - إصلاح تاريخ نتائج أدوات Snowflake Claude غير المكتملة. + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.7. + - تحديث وثائق جامع OpenTelemetry. + - تحديث دليل NVIDIA Nemotron LLM. + - إضافة دليل تكامل Databricks. + - إضافة دليل تكامل Snowflake. + + ### الأداء + - تحسين سرعة استيراد crewai من خلال تحميل مستندات docling بشكل كسول. + + ### إعادة الهيكلة + - تبسيط تقييم شروط التدفق ليكون بلا حالة لكل حدث. + - فصل منطق المحادثة عن وقت التشغيل وإضافة تعريف المحادثة. + - تقسيم `flow.py` إلى DSL، وتعريف، ووقت تشغيل. + + ## المساهمون + + @Luzk, @alex-clawd, @devin-ai-integration[bot], @greysonlalonde, @gvieira, @jessemiller, @lorenzejay, @lucasgomide, @mattatcha, @vinibrsl + + + + + ## v1.14.7rc2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.7rc2) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - استعادة البوابة على علامة لمنع اللقطات الحية من إعادة التشغيل كاستئناف + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.7rc1 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.14.7rc1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.7rc1) + + ## ما الذي تغير + + ### الميزات + - إضافة `reset_runtime_state` لإطلاق حالة الحافلة المتراكمة + - التعامل مع دعم كل من الموجهات المخصصة + - فصل منطق المحادثة عن وقت التشغيل وإضافة `conversational_definition` + + ### إصلاحات الأخطاء + - إصلاح نطاق حالة وقت التشغيل لكل تشغيل للحد من النمو وعزل التشغيلات المتزامنة + - إصلاح إعدادات القياس عن بُعد على `crewai-login` + - إصلاح احترام `suppress_flow_events` لفعاليات تنفيذ الأساليب + + ### الوثائق + - تحديث صور OpenTelemetry + - تحديث الوثائق لتعكس الحالة الجديدة لجمع بيانات OpenTelemetry + - تحديث سجل التغييرات والإصدار لـ v1.14.7a4 + + ### إعادة الهيكلة + - تبسيط تقييم شرط التدفق ليكون بلا حالة لكل حدث + - تحسين دورة توجيه المحادثة مع تقليل مسار واحد + + ## المساهمون + + @greysonlalonde, @lorenzejay, @lucasgomide, @vinibrsl + + + + + ## v1.14.7a4 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.7a4) + + ## ما الذي تغير + + ### الميزات + - نقل وقت التشغيل @listen/@router لقراءة من FlowDefinition + - إضافة واجهات خلفية افتراضية قابلة للتوصيل للذاكرة، والمعرفة، وrag، وflow + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.7a3 + + ## المساهمون + + @greysonlalonde, @mattatcha, @vinibrsl + + + + + ## v1.14.7a3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.7a3) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح تعرض `ask_for_human_input` في `AgentExecutor` التجريبي + - حل مشكلات CVEs الخاصة بـ pip-audit لـ `aiohttp`، `docling`، `docling-core`، و `pip` + + ### إعادة هيكلة + - نقل `@start` لقراءة من `FlowDefinition` + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.7a2 + + ## المساهمون + + @greysonlalonde، @lorenzejay، @vinibrsl + + + + + ## v1.14.7a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.7a2) + + ## ما الذي تغير + + ### الميزات + - إضافة دعم تتبع تدفقات المحادثة. + - تحديث وثائق تدفق المحادثة لاستخدام `handle_turn`. + - عرض السبب الحقيقي لإنهاء المحادثة، ومعلمات العينة، و`response.id` في أحداث LLM. + - تصنيف مشغلات DSL كزخارف واعية بالمسار. + - تنفيذ واجهة برمجة التطبيقات للدردشة لتدفقات المحادثة. + - جعل قفل الخلفية قابلاً للتجاوز في متجر القفل. + - تقسيم أحادي تدفق DSL إلى وحدات زخرفية مركزة. + - تسطيح استخدام ذاكرة التخزين المؤقت LiteLLM/أعداد الأسباب الفرعية في `_usage_to_dict`. + - بناء `FlowDefinition` من بيانات التعريف الخاصة بتدفق DSL. + + ### الوثائق + - إضافة دليل NVIDIA Nemotron LLM. + - توثيق عمليات نشر المونوريبو. + - تحديث سجل التغييرات والإصدار لـ v1.14.7a1. + + ## المساهمون + + @alex-clawd, @gvieira, @lorenzejay, @lucasgomide, @mattatcha, @vinibrsl + + + + + ## v1.14.7a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.7a1) + + ## ما الذي تغير + + ### الميزات + - إضافة دعم ملفات الوكلاء المدربين + - إضافة مزود LLM الأصلي لـ Snowflake Cortex + - إضافة دليل تكامل Databricks + - إضافة دليل تكامل Snowflake + + ### إصلاحات الأخطاء + - إصلاح CLI عن طريق استعادة `[project.scripts]` في حزمة crewai لتثبيت أداة UV + - حل مشكلات موثوقية إدخال الملفات + - إصلاح تاريخ نتائج الأدوات غير المكتملة في Snowflake Claude + - التعامل مع استدعاءات الأدوات الممثلة كسلاسل لـ Snowflake Claude + - إعادة تفعيل مستمعي `or_` متعدد المصادر عبر دورات مدفوعة بالموجه + + ### الأداء + - تحسين سرعة استيراد crewai عن طريق تحميل استيرادات docling بشكل كسول + + ### إعادة هيكلة + - تقسيم `flow.py` إلى DSL، تعريف، وتشغيل + + ## المساهمون + + @Luzk, @alex-clawd, @devin-ai-integration[bot], @greysonlalonde, @jessemiller, @lorenzejay, @vinibrsl + + + + + ## v1.14.6 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.6) + + ## ما الذي تغير + + ### الميزات + - تحسين StdioTransport لمنع تسرب متغيرات البيئة + - تعزيز تكوين التخطيط ومعالجة الملاحظات + - إعلان env_vars على DatabricksQueryTool + - إضافة وثائق خطة التحكم في الوكيل + + ### إصلاحات الأخطاء + - إصلاح تسرب المخرجات المنظمة في حلقات استدعاء الأدوات + - حذف ردود الاستدعاء غير القابلة للعودة وحالة المحول في نقطة التحقق + - تسلسل الحقول من النوع [BaseModel] كـ JSON schema في نقطة التحقق + - تجنب مهمة orphan task_started عند استعادة نطاق الاستئناف + - السماح لـ AgentExecutor بالاستعادة من نقطة التحقق + - تصحيح خطأ الكتابة من mongodb إلى pymongo في package_dependencies + + ### الوثائق + - إضافة كتلة تنقل وثائق ACP (بيتا) إلى صفحات خطة التحكم في الوكيل + - إزالة المراجع إلى العمليات التوافقية من صفحة العمليات + - إعادة هيكلة صفحة نقاط التحقق + - توثيق خطوة تثبيت حزمة الإدارة لمرة واحدة + - نقل Secrets Manager / Workload Identity من replicated-config + - إزالة تعبيرات `{" "}` JSX التي تكسر عرض `` + + ### إعادة الهيكلة + - نقل مستودع المهارات إلى experimental + CREWAI_EXPERIMENTAL gate + + ## المساهمون + + @akaKuruma, @alex-clawd, @github-actions[bot], @greysonlalonde, @heitorado, @iris-clawd, @lorenzejay, @lucasgomide, @mattatcha, @thiagomoretto, @vinibrsl + + + + + ## v1.14.6a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.6a2) + + ## ما الذي تغير + + ### الميزات + - تحسين `StdioTransport` لمنع تسرب متغيرات البيئة + - تحسين تكوين التخطيط ومعالجة المراقبة + - إعلان `env_vars` على `DatabricksQueryTool` + - إضافة وثائق خطة التحكم بالوكيل + + ### إصلاحات الأخطاء + - إصلاح تسرب المخرجات المنظمة في حلقات استدعاء الأدوات + - حذف الاستدعاءات غير القابلة للعودة وحالة المحول في نقاط التحقق + - تسلسل حقول `type[BaseModel]` كـ JSON schema في نقاط التحقق + - تجنب `task_started` اليتيمة عند استعادة نطاق الاستئناف + - السماح لـ `AgentExecutor` بالاستعادة من نقطة تحقق + - تصحيح خطأ مطبعي في MongoDB إلى `pymongo` في تبعيات الحزمة + + ### الوثائق + - إعادة هيكلة صفحة نقاط التحقق + - توثيق خطوة تثبيت حزمة الإدارة لمرة واحدة + - نقل Secrets Manager / Workload Identity من replicated-config + - إزالة إدخال Skills Repository من سجل التغييرات + + ## المساهمون + + @github-actions[bot], @greysonlalonde, @heitorado, @iris-clawd, @lorenzejay, @lucasgomide, @mattatcha, @thiagomoretto, @vinibrsl + + + + + ## v1.14.6a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.6a1) + + ## ما الذي تغير + + ### الميزات + - توليد ملاحظات إصدار مصنفة للمؤسسات + + ### إصلاحات الأخطاء + - تعزيز تسلسل حالة وقت التشغيل عبر حقول الكيان + - تحديث idna إلى 3.15 لمعالجة مشكلة الأمان GHSA-65pc-fj4g-8rjx + - إزالة تعبيرات JSX `{" "}` التي تعطل عرض `` + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.5 + + ## المساهمون + + @akaKuruma, @alex-clawd, @greysonlalonde + + + + + ## v1.14.5 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5) + + ## ما الذي تغير + + ### الميزات + - إلغاء استخدام `CrewAgentExecutor`، وتعيين وكلاء الطاقم الافتراضيين إلى `AgentExecutor` + - تحسين أدوات صندوق الرمل Daytona + - إضافة معلمة بدء `restore_from_state_id` + - إضافة تسليط الضوء على `ExaSearchTool`، وإعادة تسميته من `EXASearchTool` + + ### إصلاحات الأخطاء + - إصلاح تسرب الذاكرة في `git.py` باستخدام `cached_property` + - عرض استدعاءات الأدوات المتدفقة عندما تكون `available_functions` غائبة + - ضمان تحميل أحداث `skills` للتتبع + - تصحيح مسار نقطة النهاية للحالة من `/{kickoff_id}/status` إلى `/status/{kickoff_id}` + - استعادة كتلة الشيفرة المفقودة في دليل التدفق الأول للغة البرتغالية (pt-BR) + - منع `result_as_answer` من إرجاع رسائل الخطأ أو الكتل المرتبطة كإجابة نهائية + - الحفاظ على مخرجات المهام عبر تفريغ الدفعات غير المتزامنة + - دائمًا استعادة `task.output_pydantic` في كتلة finally + - التعامل مع إدخال `BaseModel` في `convert_to_model` + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.5 + - إضافة دليل ترقية OSS و انتقال الطاقم إلى التدفق + - توثيق متغيرات البيئة الإضافية لأدوات المطور + - إضافة وثائق لـ `TavilyGetResearch` + + ### إعادة الهيكلة + - استخراج واجهة سطر الأوامر إلى حزمة مستقلة `crewai-cli` + + ## المساهمون + + @NIK-TIGER-BILL, @akaKuruma, @cgoeppinger, @github-actions[bot], @greysonlalonde, @heitorado, @irfaan101, @iris-clawd, @lorenzejay, @manisrinivasan2k1, @minasami-pr, @mislavivanda, @theCyberTech, @theishangoswami, @wishhyt + + + + + ## v1.14.5a7 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a7) + + ## ما الذي تغير + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.5a6 + + ### تغييرات كسرية + - إلغاء حقل function_calling_llm + + ## المساهمون + + @greysonlalonde, @heitorado + + + + + ## v1.14.5a6 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a6) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح استدعاءات الأدوات المتدفقة عندما تكون available_functions غائبة + - رفع اعتماد langsmith إلى الإصدار >=0.8.0 لمعالجة GHSA-3644-q5cj-c5c7 + - حل مشاكل الأماكن الشاغرة لكتل التعليمات البرمجية غير المترجمة في وثائق البرتغالية البرازيلية + + ### الوثائق + - إضافة وثائق لـ TavilyGetResearch + - تحديث سجل التغييرات والإصدار لـ v1.14.5a5 + + ## المساهمون + + @greysonlalonde, @heitorado, @iris-clawd, @lorenzejay, @manisrinivasan2k1 + + + + + ## v1.14.5a5 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a5) + + ## ما الذي تغير + + ### الميزات + - إلغاء استخدام CrewAgentExecutor، وتعيين وكلاء Crew الافتراضيين إلى AgentExecutor + - تحسين أدوات صندوق الرمل Daytona + + ### إصلاحات الأخطاء + - إصلاح كتلة الكود المفقودة في دليل التدفق الأول باللغة البرتغالية (pt-BR) + - تسجيل أخطاء المراجعة المسبقة والتقطير HITL، إضافة learn_strict + - تصحيح urllib3 للثغرات الأمنية + - تصحيح gitpython و langchain-core؛ تجاهل CVE paramiko غير المصححة + - تحديث جميع حزم مساحة العمل المنشورة على uv lock/sync + + ### الوثائق + - إضافة دليل ترحيل لـ `inputs.id` إلى `restoreFromStateId` + - إضافة دليل ترقية OSS ودليل ترحيل crew-to-flow + - تحديث سجل التغييرات والإصدار لـ v1.14.5a4 + + ## المساهمون + + @akaKuruma, @greysonlalonde, @iris-clawd, @lorenzejay, @mislavivanda + + + + + ## v1.14.5a4 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a4) + + ## ما الذي تغير + + ### الميزات + - تحديث قوائم LLM + + ### إصلاحات الأخطاء + - إصلاح مشكلة الاعتماد من خلال نقل `textual` إلى `crewai-cli` وإضافة `certifi` + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.5a3 + + ## المساهمون + + @cgoeppinger, @greysonlalonde + + + + + ## v1.14.5a3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a3) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح مسار نقطة النهاية للحالة من /{kickoff_id}/status إلى /status/{kickoff_id} + - تحديث تبعية gitpython إلى الإصدار >=3.1.47 للامتثال الأمني + + ### إعادة هيكلة + - استخراج واجهة سطر الأوامر إلى حزمة crewai-cli المستقلة + + ### الوثائق + - تحديث سجل التغييرات والإصدار للإصدار v1.14.5a2 + + ## المساهمون + + @greysonlalonde, @iris-clawd + + + + + ## v1.14.5a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a2) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح استعادة مخرجات المهام في كتلة finally + - تضمين `thoughts_token_count` في رموز الإكمال + - الحفاظ على مخرجات المهام عبر تفريغ دفعات غير متزامنة + - تمرير kwargs إلى استدعاءات المحمل في `CrewAIRagAdapter` + - منع `result_as_answer` من إرجاع رسالة كتلة الخطاف كإجابة نهائية + - منع `result_as_answer` من إرجاع خطأ كإجابة نهائية + - استخدام `acall` لتحويل المخرجات في المسارات غير المتزامنة + - منع تغيير كلمات التوقف المشتركة في LLM عبر الوكلاء + - التعامل مع مدخلات `BaseModel` في `convert_to_model` + + ### الوثائق + - توثيق متغيرات البيئة الإضافية + - تحديث سجل التغييرات والإصدار لـ v1.14.5a1 + + ## المساهمون + + @NIK-TIGER-BILL, @greysonlalonde, @lorenzejay, @minasami-pr, @theCyberTech, @wishhyt + + + + + ## v1.14.5a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.5a1) + + ## ما الذي تغير + + ### الميزات + - إضافة معلمة بدء `restore_from_state_id` + - إضافة تسليط الضوء على ExaSearchTool وإعادة تسميته من EXASearchTool + + ### إصلاحات الأخطاء + - إصلاح المواقع المفقودة لـ crewai في تدفق الإصدار + - ضمان تحميل أحداث المهارات للآثار + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.4 + + ## المساهمون + + @akaKuruma, @github-actions[bot], @greysonlalonde, @lorenzejay, @theishangoswami + + + + + ## v1.14.4 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.4) + + ## ما الذي تغير + + ### الميزات + - إضافة دعم لمفتاح الاستمرارية المخصص في @persist + - إضافة دعم واجهة برمجة التطبيقات للردود لمزود Azure OpenAI + - تمرير credential_scopes إلى عميل Azure AI Inference + - إضافة دليل إعداد هوية عبء العمل لـ Vertex AI + - إضافة Tavily Research والحصول على Research + - إضافة أدوات MCP من You.com للبحث، البحث، واستخراج المحتوى + + ### إصلاحات الأخطاء + - إصلاح مشكلة السقوط عند عدم تطابق تعبير JSON regex مع JSON صالح + - إصلاح للحفاظ على tool_calls عندما تحتوي الاستجابة أيضًا على نص + - إصلاح لتمرير base_url و api_key إلى instructor.from_provider + - إصلاح لتحذير وإرجاع فارغ عندما لا يُرجع خادم MCP الأصلي أي أدوات + - إصلاح لاستخدام متغير الرسائل الموثقة في معالجات غير البث + - إصلاح لحماية مساعدي وصف دردشة الطاقم ضد فشل LLM + - إصلاح لإعادة تعيين الرسائل والتكرارات بين الاستدعاءات + - إصلاح لتمرير ملف trained-agents من خلال replay و test + - إصلاح لاحترام ملف trained-agents المخصص في الاستدلال + - إصلاح لربط الوكلاء المخصصين بالمهام فقط بالطاقم لملفات الإدخال متعددة الأنماط + - إصلاح لتسلسل callable الحواجز كـ null لتسجيل JSON + - إصلاح إعادة تسمية force_final_answer لتجنب توجيه ذاتي + - إصلاح زيادة litellm لإصلاح SSTI؛ تجاهل CVE غير القابل للإصلاح في pip + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.4a1 + - إضافة صفحة أدوات E2B Sandbox + - إضافة وثائق أدوات صندوق Daytona + + ## المساهمون + + @EdwardIrby, @dependabot[bot], @factory-droid-oss, @factory-droid[bot], @greysonlalonde, @kunalk16, @lorenzejay, @lucasgomide, @manisrinivasan2k1, @mattatcha, @vinibrsl + + + + + ## v1.14.4a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.4a1) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح مساعدي وصف دردشة الطاقم ضد فشل LLM. + - إعادة تعيين الرسائل والتكرارات بين الاستدعاءات في المنفذ. + - تمرير ملف الوكلاء المدربين عبر إعادة التشغيل والاختبار في CLI. + - احترام ملف الوكلاء المدربين المخصص أثناء الاستدلال في الوكيل. + - ربط الوكلاء المخصصين بالمهام فقط بالطاقم لضمان وصول ملفات الإدخال متعددة الوسائط إلى LLM. + - تسلسل استدعاءات الحواجز كـ null لتسجيل النقاط في JSON. + - إعادة تسمية `force_final_answer` في agent_executor لتجنب جهاز التوجيه الذاتي الإشارة. + - تحديث `litellm` لإصلاح SSTI وتجاهل CVE pip غير القابل للإصلاح. + + ### الوثائق + - إضافة صفحة أدوات Sandbox E2B. + - إضافة وثائق أدوات Sandbox Daytona. + - إضافة دليل إعداد هوية عبء العمل لـ Vertex AI. + - إضافة أدوات MCP من You.com للبحث، البحث، واستخراج المحتوى. + - تحديث سجل التغييرات والإصدار لـ v1.14.3. + + ## المساهمون + + @EdwardIrby, @dependabot[bot], @factory-droid-oss, @factory-droid[bot], @greysonlalonde, @lorenzejay, @manisrinivasan2k1, @mattatcha + + + + + ## v1.14.3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3) + + ## ما الذي تغير + + ### الميزات + - إضافة أحداث دورة الحياة لعمليات نقطة التحقق + - إضافة دعم لـ e2b + - الرجوع إلى DefaultAzureCredential عند عدم توفير مفتاح API في تكامل Azure + - إضافة دعم Bedrock V4 + - إضافة أدوات Daytona sandbox لوظائف محسّنة + - إضافة دعم نقطة التحقق والتفرع للوكلاء المستقلين + + ### إصلاحات الأخطاء + - إصلاح execution_id ليكون منفصلًا عن state.id + - حل مشكلة إعادة تشغيل أحداث الطريقة المسجلة عند استئناف نقطة التحقق + - إصلاح تسلسل مراجع class initial_state كـ JSON schema + - الحفاظ على مهارات الوكلاء التي تحتوي على بيانات وصفية فقط + - تمرير أسماء @CrewBase الضمنية إلى أحداث الطاقم + - دمج بيانات التنفيذ عند تهيئة دفعة مكررة + - إصلاح تسلسل حقول مراجع class Task لنقاط التحقق + - التعامل مع نتيجة BaseModel في حلقة إعادة المحاولة guardrail + - الحفاظ على thought_signature في استدعاءات أدوات Gemini للبث + - إصدار task_started عند استئناف التفرع وإعادة تصميم واجهة المستخدم النصية لنقطة التحقق + - استخدام تواريخ مستقبلية في اختبارات تقليم نقطة التحقق لمنع الفشل المعتمد على الوقت + - إصلاح ترتيب التشغيل الجاف والتعامل مع الفرع القديم الذي تم التحقق منه في إصدار أدوات التطوير + - ترقية lxml إلى >=6.1.0 لرقعة الأمان + - رفع python-dotenv إلى >=1.2.2 لرقعة الأمان + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.3 + - إضافة صفحة "بناء باستخدام الذكاء الاصطناعي" وتحديث التنقل لجميع اللغات + - إزالة الأسئلة الشائعة حول التسعير من صفحة البناء باستخدام الذكاء الاصطناعي عبر جميع المواقع + + ### الأداء + - تحسين MCP SDK وأنواع الأحداث لتقليل بدء التشغيل البارد بنسبة ~29% + + ### إعادة الهيكلة + - إعادة هيكلة مساعدي نقطة التحقق للقضاء على التكرار وتشديد تلميحات نوع الحالة + + ## المساهمون + + @MatthiasHowellYopp, @akaKuruma, @alex-clawd, @github-actions[bot], @github-advanced-security[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @mattatcha, @renatonitta + + + + + ## v1.14.3a3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a3) + + ## ما الذي تغير + + ### الميزات + - إضافة دعم لـ e2b + - تنفيذ التراجع إلى DefaultAzureCredential عند عدم توفير مفتاح API + + ### إصلاحات الأخطاء + - ترقية lxml إلى >=6.1.0 لمعالجة مشكلة الأمان GHSA-vfmq-68hx-4jfw + + ### الوثائق + - إزالة الأسئلة الشائعة حول التسعير من صفحة البناء باستخدام الذكاء الاصطناعي عبر جميع اللغات + + ### الأداء + - تحسين وقت بدء التشغيل البارد بنسبة ~29% من خلال التحميل الكسول لمجموعة أدوات MCP وأنواع الأحداث + + ## المساهمون + + @alex-clawd, @github-advanced-security[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @mattatcha + + + + + ## v1.14.3a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a2) + + ## ما الذي تغير + + ### الميزات + - إضافة دعم لـ bedrock V4 + - إضافة أدوات Daytona sandbox لوظائف محسّنة + - إضافة صفحة "البناء باستخدام الذكاء الاصطناعي" — مستندات أصلية للذكاء الاصطناعي لوكلاء البرمجة + - إضافة "البناء باستخدام الذكاء الاصطناعي" إلى التنقل في صفحة "البدء" وملفات الصفحات لجميع اللغات (en, ko, pt-BR, ar) + + ### إصلاحات الأخطاء + - إصلاح انتشار أسماء @CrewBase الضمنية إلى أحداث الطاقم + - حل مشكلة تكرار تهيئة الدفعات في دمج بيانات التنفيذ الوصفية + - إصلاح تسلسل حقول مرجع فئة Task لعمليات التحقق من النقاط + - التعامل مع نتيجة BaseModel في حلقة إعادة المحاولة للحدود + - تحديث python-dotenv إلى الإصدار >=1.2.2 للامتثال الأمني + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.3a1 + - تحديث الأوصاف وتطبيق الترجمات الفعلية + + ## المساهمون + + @MatthiasHowellYopp, @github-actions[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @renatonitta + + + + + ## v1.14.3a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.3a1) + + ## ما الذي تغير + + ### الميزات + - إضافة دعم نقاط التحقق والفروع لوكلاء مستقلين + + ### إصلاحات الأخطاء + - الحفاظ على thought_signature في استدعاءات أداة البث Gemini + - إصدار task_started عند استئناف الفرع وإعادة تصميم واجهة المستخدم النصية لنقاط التحقق + - تصحيح ترتيب التشغيل الجاف ومعالجة الفرع القديم الذي تم التحقق منه في إصدار أدوات التطوير + - استخدام تواريخ مستقبلية في اختبارات تقليم نقاط التحقق لمنع الفشل المعتمد على الوقت (#5543) + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.2 + + ## المساهمون + + @alex-clawd, @greysonlalonde + + + + + ## v1.14.2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2) + + ## ما الذي تغير + + ### الميزات + - إضافة أوامر استئناف النقاط التفتيش، والاختلاف، والتنظيف مع تحسين إمكانية الاكتشاف. + - إضافة معلمة `from_checkpoint` إلى `Agent.kickoff` والطرق ذات الصلة. + - إضافة أوامر إدارة القوالب لقوالب المشاريع. + - إضافة تلميحات استئناف إلى إصدار أدوات المطور عند الفشل. + - إضافة واجهة سطر الأوامر للتحقق من النشر وتعزيز سهولة استخدام تهيئة LLM. + - إضافة تقسيم النقاط التفتيشية مع تتبع النسب. + - إثراء تتبع رموز LLM مع رموز الاستدلال ورموز إنشاء التخزين المؤقت. + + ### إصلاحات الأخطاء + - إصلاح المطالبة بشأن تعارضات الفروع القديمة في إصدار أدوات المطور. + - تصحيح الثغرات في `authlib` و `langchain-text-splitters` و `pypdf`. + - تحديد نطاق معالجات البث لمنع تلوث أجزاء التشغيل المتقاطعة. + - إرسال نقاط التفتيش عبر واجهات Flow في TUI. + - استخدام نمط البحث المتكرر لاكتشاف نقاط التفتيش بتنسيق JSON. + - التعامل مع مخططات JSON الدائرية في أداة حل MCP. + - الحفاظ على معلمات استدعاء أداة Bedrock من خلال إزالة القيمة الافتراضية الصحيحة. + - إصدار حدث flow_finished بعد استئناف HITL. + - إصلاح ثغرات متنوعة من خلال تحديث التبعيات، بما في ذلك `requests` و `cryptography` و `pytest`. + - إصلاح لإيقاف تمرير وضع صارم إلى واجهة برمجة التطبيقات Bedrock Converse. + + ### الوثائق + - توثيق المعلمات المفقودة وإضافة قسم النقاط التفتيشية. + - تحديث سجل التغييرات والإصدار للإصدار v1.14.2 ومرشحي الإصدار السابقين. + - إضافة توثيق ميزة A2A الخاصة بالشركات وتحديث وثائق A2A المفتوحة المصدر. + + ## المساهمون + + @Yanhu007، @alex-clawd، @github-actions[bot]، @greysonlalonde، @iris-clawd، @lorenzejay، @lucasgomide + + + + + ## v1.14.2rc1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2rc1) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح معالجة مخططات JSON الدائرية في أداة MCP + - إصلاح ثغرة أمنية من خلال تحديث python-multipart إلى 0.0.26 + - إصلاح ثغرة أمنية من خلال تحديث pypdf إلى 6.10.1 + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.2a5 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.14.2a5 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a5) + + ## ما الذي تغير + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.2a4 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.14.2a4 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a4) + + ## ما الذي تغير + + ### الميزات + - إضافة تلميحات استئناف إلى إصدار أدوات المطورين عند الفشل + + ### إصلاحات الأخطاء + - إصلاح توجيه وضع الصرامة إلى واجهة برمجة تطبيقات Bedrock Converse + - إصلاح إصدار pytest إلى 9.0.3 لثغرة الأمان GHSA-6w46-j5rx-g56g + - رفع الحد الأدنى لـ OpenAI إلى >=2.0.0 + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.2a3 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.14.2a3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a3) + + ## ما الذي تغير + + ### الميزات + - إضافة واجهة سطر الأوامر للتحقق من النشر + - تحسين سهولة استخدام تهيئة LLM + + ### إصلاحات الأخطاء + - تجاوز pypdf و uv إلى إصدارات مصححة لـ CVE-2026-40260 و GHSA-pjjw-68hj-v9mw + - ترقية requests إلى >=2.33.0 لمعالجة ثغرة ملف مؤقت CVE + - الحفاظ على معلمات استدعاء أداة Bedrock من خلال إزالة القيمة الافتراضية الصحيحة + - تنظيف مخططات الأدوات لوضع صارم + - إصلاح اختبار تسلسل تضمين MemoryRecord + + ### الوثائق + - تنظيف لغة A2A الخاصة بالمؤسسات + - إضافة وثائق ميزات A2A الخاصة بالمؤسسات + - تحديث وثائق A2A الخاصة بالمصادر المفتوحة + - تحديث سجل التغييرات والإصدار لـ v1.14.2a2 + + ## المساهمون + + @Yanhu007, @greysonlalonde + + + + + ## v1.14.2a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a2) + + ## ما الذي تغير + + ### الميزات + - إضافة واجهة مستخدم نصية لنقطة التحقق مع عرض شجري، ودعم التفرع، ومدخلات/مخرجات قابلة للتعديل + - إثراء تتبع رموز LLM مع رموز الاستدلال ورموز إنشاء التخزين المؤقت + - إضافة معلمة `from_checkpoint` إلى طرق الانطلاق + - تضمين `crewai_version` في نقاط التحقق مع إطار عمل الهجرة + - إضافة تفرع نقاط التحقق مع تتبع السلالة + + ### إصلاحات الأخطاء + - إصلاح توجيه الوضع الصارم إلى مزودي Anthropic وBedrock + - تعزيز NL2SQLTool مع وضع القراءة فقط الافتراضي، والتحقق من الاستعلامات، والاستعلامات المعلمة + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.2a1 + + ## المساهمون + + @alex-clawd, @github-actions[bot], @greysonlalonde, @lucasgomide + + + + + ## v1.14.2a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.2a1) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح إصدار حدث flow_finished بعد استئناف HITL + - إصلاح إصدار التشفير إلى 46.0.7 لمعالجة CVE-2026-39892 + + ### إعادة هيكلة + - إعادة هيكلة لاستخدام I18N_DEFAULT المشترك + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.1 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.14.1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.1) + + ## ما الذي تغير + + ### الميزات + - إضافة متصفح TUI لنقاط التفتيش غير المتزامنة + - إضافة دالة aclose()/close() ومدير سياق غير متزامن لمخرجات البث + + ### إصلاحات الأخطاء + - إصلاح التعبير النمطي لزيادة إصدار pyproject.toml + - تنظيف أسماء الأدوات في مرشحات زخرفة الخطاف + - إصلاح تسجيل معالجات نقاط التفتيش عند إنشاء CheckpointConfig + - رفع إصدار transformers إلى 5.5.0 لحل CVE-2026-1839 + - إزالة غلاف FilteredStream لـ stdout/stderr + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.1rc1 + + ### إعادة الهيكلة + - استبدال القائمة المحظورة الثابتة باستبعاد حقل BaseTool الديناميكي في توليد المواصفات + - استبدال التعبير النمطي بـ tomlkit في واجهة سطر أوامر أدوات التطوير + - استخدام كائن PRINTER المشترك + - جعل BaseProvider نموذجاً أساسياً مع مميز نوع المزود + + ## المساهمون + + @greysonlalonde, @iris-clawd, @joaomdmoura, @lorenzejay + + + + + ## v1.14.1rc1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.1rc1) + + ## ما الذي تغير + + ### الميزات + - إضافة متصفح TUI لنقطة التحقق غير المتزامنة + - إضافة aclose()/close() ومدير سياق غير متزامن لمخرجات البث + + ### إصلاحات الأخطاء + - إصلاح زيادة إصدارات pyproject.toml باستخدام التعبيرات العادية + - تنظيف أسماء الأدوات في مرشحات ديكور المكونات + - زيادة إصدار transformers إلى 5.5.0 لحل CVE-2026-1839 + - تسجيل معالجات نقطة التحقق عند إنشاء CheckpointConfig + + ### إعادة الهيكلة + - استبدال القائمة المحظورة الثابتة باستبعاد حقل BaseTool الديناميكي في توليد المواصفات + - استبدال التعبيرات العادية بـ tomlkit في واجهة سطر الأوامر devtools + - استخدام كائن PRINTER المشترك + - جعل BaseProvider نموذجًا أساسيًا مع مميز نوع المزود + - إزالة غلاف stdout/stderr لـ FilteredStream + - إزالة flow/config.py غير المستخدمة + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.0 + + ## المساهمون + + @greysonlalonde, @iris-clawd, @joaomdmoura + + + + + ## v1.14.0 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.0) + + ## ما الذي تغير + + ### الميزات + - إضافة أوامر CLI لقائمة/معلومات نقاط التحقق + - إضافة guardrail_type و name لتمييز التتبع + - إضافة SqliteProvider لتخزين نقاط التحقق + - إضافة CheckpointConfig للتسجيل التلقائي لنقاط التحقق + - تنفيذ تسجيل حالة وقت التشغيل، نظام الأحداث، وإعادة هيكلة المنفذ + + ### إصلاحات الأخطاء + - إضافة حماية من SSRF وتجاوز المسار + - إضافة التحقق من المسار وعنوان URL لأدوات RAG + - استبعاد متجهات التضمين من تسلسل الذاكرة لتوفير الرموز + - التأكد من وجود دليل الإخراج قبل الكتابة في قالب التدفق + - رفع litellm إلى >=1.83.0 لمعالجة CVE-2026-35030 + - إزالة حقل فهرسة SEO الذي يتسبب في عرض الصفحة العربية بشكل غير صحيح + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.0 + - تحديث أدلة البدء السريع والتثبيت لتحسين الوضوح + - إضافة قسم مزودي التخزين، تصدير JsonProvider + - إضافة دليل علامة AMP التدريبية + + ### إعادة الهيكلة + - تنظيف واجهة برمجة تطبيقات نقاط التحقق + - إزالة CodeInterpreterTool وإهمال معلمات تنفيذ الكود + + ## المساهمون + + @alex-clawd, @github-actions[bot], @greysonlalonde, @iris-clawd, @joaomdmoura, @lorenzejay, @lucasgomide + + + + + ## v1.14.0a4 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.0a4) + + ## ما الذي تغير + + ### الميزات + - إضافة guardrail_type و name لتمييز الآثار + - إضافة SqliteProvider لتخزين نقاط التحقق + - إضافة CheckpointConfig للتخزين التلقائي لنقاط التحقق + - تنفيذ نقاط التحقق لحالة التشغيل، نظام الأحداث، وإعادة هيكلة المنفذ + + ### إصلاحات الأخطاء + - استبعاد متجهات التضمين من تسلسل الذاكرة لتوفير الرموز + - رفع litellm إلى >=1.83.0 لمعالجة CVE-2026-35030 + + ### الوثائق + - تحديث أدلة البدء السريع والتثبيت لتحسين الوضوح + - إضافة قسم مقدمي التخزين وتصدير JsonProvider + + ### الأداء + - استخدام JSONB لعمود بيانات نقاط التحقق + + ### إعادة الهيكلة + - إزالة CodeInterpreterTool وإهمال معلمات تنفيذ الكود + + ## المساهمون + + @alex-clawd, @github-actions[bot], @greysonlalonde, @joaomdmoura, @lorenzejay, @lucasgomide + + + + + ## v1.14.0a3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.0a3) + + ## ما الذي تغير + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.14.0a2 + + ## المساهمون + + @joaomdmoura + + + + + ## v1.14.0a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.14.0a2) + + # ملاحظات الإصدار 1.14.0a2 + + ## التعليمات: + - ترجم جميع عناوين الأقسام والوصف بشكل طبيعي + - احتفظ بتنسيق markdown (##، ###، -، إلخ) كما هو + - احتفظ بجميع الأسماء الصحيحة، ومعرفات الشيفرة، وأسماء الفئات، والمصطلحات التقنية دون تغيير + (مثل "CrewAI"، "LiteAgent"، "ChromaDB"، "MCP"، "@username") + - احتفظ بقسم ## المساهمون وأسماء مستخدمي GitHub كما هي + - لا تضف أو تزيل أي محتوى، فقط ترجم + + ## المميزات الجديدة + - تمت إضافة دعم لـ "ChromaDB" لتحسين أداء قاعدة البيانات. + - تحسينات على "LiteAgent" لزيادة الكفاءة. + + ## الإصلاحات + - إصلاح مشكلة تتعلق بـ "MCP" التي كانت تؤدي إلى تعطل التطبيق. + - معالجة الأخطاء المتعلقة بواجهة المستخدم في "CrewAI". + + ## المساهمون + - @username1 + - @username2 + - @username3 + + + + + ## v1.13.0 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0) + + ## ما الذي تغير + + ### الميزات + - إضافة نموذج RuntimeState RootModel لتوحيد تسلسل الحالة + - تعزيز مستمع الأحداث مع نطاقات جديدة للقياس عن أحداث المهارة والذاكرة + - إضافة امتداد A2UI مع دعم v0.8/v0.9، والمخططات، والوثائق + - إصدار بيانات استخدام الرموز في حدث LLMCallCompletedEvent + - تحديث تلقائي لمستودع اختبار النشر أثناء الإصدار + - تحسين مرونة الإصدار المؤسسي وتجربة المستخدم + + ### إصلاحات الأخطاء + - إضافة بيانات اعتماد مستودع الأدوات إلى تثبيت crewai + - إضافة بيانات اعتماد مستودع الأدوات إلى بناء uv في نشر الأدوات + - تمرير بيانات التعريف عبر الإعدادات بدلاً من معلمات الأدوات + - معالجة نماذج GPT-5.x التي لا تدعم معلمة API `stop` + - إضافة GPT-5 وسلسلة o إلى بادئات الرؤية متعددة الوسائط + - مسح ذاكرة التخزين المؤقت uv للحزم التي تم نشرها حديثًا في الإصدار المؤسسي + - تحديد lancedb أقل من 0.30.1 لضمان التوافق مع Windows + - إصلاح مستويات أذونات RBAC لتتناسب مع خيارات واجهة المستخدم الفعلية + - إصلاح عدم الدقة في قدرات الوكيل عبر جميع اللغات + + ### الوثائق + - إضافة فيديو توضيحي لمهارات وكيل البرمجة إلى صفحات البدء + - إضافة دليل شامل لتكوين SSO + - إضافة مصفوفة شاملة لأذونات RBAC ودليل النشر + - تحديث سجل التغييرات والإصدار إلى v1.13.0 + + ### الأداء + - تقليل الحمل الزائد للإطار باستخدام حافلة الأحداث الكسولة، وتخطي التتبع عند تعطيله + + ### إعادة الهيكلة + - تحويل Flow إلى Pydantic BaseModel + - تحويل فئات LLM إلى Pydantic BaseModel + - استبدال InstanceOf[T] بتعليقات نوع عادية + - إزالة دليل LLM الخاص بالطرف الثالث غير المستخدم + + ## المساهمون + + @alex-clawd, @dependabot[bot], @greysonlalonde, @iris-clawd, @joaomdmoura, @lorenzejay, @lucasgomide, @thiagomoretto + + + + + ## v1.13.0a7 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0a7) + + ## ما الذي تغير + + ### الميزات + - إضافة امتداد A2UI مع دعم v0.8/v0.9، والمخططات، والوثائق + + ### إصلاحات الأخطاء + - إصلاح بادئات الرؤية متعددة الأنماط عن طريق إضافة GPT-5 وسلسلة o + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.13.0a6 + + ## المساهمون + + @alex-clawd, @greysonlalonde, @joaomdmoura + + + + + ## v1.13.0a6 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0a6) + + ## ما الذي تغير + + ### الوثائق + - إصلاح مستويات أذونات RBAC لتتوافق مع خيارات واجهة المستخدم الفعلية (#5210) + - تحديث سجل التغييرات والإصدار لـ v1.13.0a5 (#5200) + + ### الأداء + - تقليل عبء العمل على الإطار من خلال تنفيذ حافلة أحداث كسولة وتجاوز التتبع عند تعطيله (#5187) + + ## المساهمون + + @alex-clawd, @joaomdmoura, @lucasgomide + + + + + ## v1.13.0a5 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0a5) + + ## ما الذي تغير + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.13.0a4 + + ## المساهمون + + @greysonlalonde, @joaomdmoura + + + + + ## v1.13.0a4 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0a4) + + ## ما الذي تغير + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.13.0a3 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.13.0a3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0a3) + + ## ما الذي تغير + + ### الميزات + - إصدار بيانات استخدام الرمز في LLMCallCompletedEvent + - استخراج ونشر بيانات الأداة إلى AMP + + ### إصلاح الأخطاء + - التعامل مع نماذج GPT-5.x التي لا تدعم معلمة API `stop` + + ### الوثائق + - إصلاح عدم الدقة في قدرات الوكيل عبر جميع اللغات + - إضافة نظرة عامة على قدرات الوكيل وتحسين وثائق المهارات + - إضافة دليل شامل لتكوين SSO + - تحديث سجل التغييرات والإصدار لـ v1.13.0rc1 + + ### إعادة الهيكلة + - تحويل Flow إلى Pydantic BaseModel + - تحويل فئات LLM إلى Pydantic BaseModel + - استبدال InstanceOf[T] بتعليقات نوع عادية + - إزالة الطرق غير المستخدمة + + ## المساهمون + + @dependabot[bot], @greysonlalonde, @iris-clawd, @lorenzejay, @lucasgomide, @thiagomoretto + + + + + ## v1.13.0rc1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0rc1) + + ## ما الذي تغير + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.13.0a2 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.13.0a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0a2) + + ## ما الذي تغير + + ### الميزات + - تحديث تلقائي لمستودع اختبار النشر أثناء الإصدار + - تحسين مرونة إصدار المؤسسات وتجربة المستخدم + + ### الوثائق + - تحديث سجل التغييرات والإصدار للإصدار v1.13.0a1 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.13.0a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.13.0a1) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح الروابط المعطلة في سير العمل الوثائقي عن طريق تثبيت Node على LTS 22 + - مسح ذاكرة التخزين المؤقت لـ uv للحزم المنشورة حديثًا في الإصدار المؤسسي + + ### الوثائق + - إضافة مصفوفة شاملة لأذونات RBAC ودليل النشر + - تحديث سجل التغييرات والإصدار للإصدار v1.12.2 + + ## المساهمون + + @greysonlalonde, @iris-clawd, @joaomdmoura + + + + + ## v1.12.2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.2) + + ## ما الذي تغير + + ### الميزات + - إضافة مرحلة إصدار المؤسسات إلى إصدار أدوات المطورين + + ### إصلاحات الأخطاء + - الحفاظ على قيمة إرجاع الطريقة كإخراج تدفق لـ @human_feedback مع emit + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.12.1 + - مراجعة سياسة الأمان وتعليمات الإبلاغ + + ## المساهمون + + @alex-clawd, @greysonlalonde, @joaomdmoura, @theCyberTech + + + + + ## v1.12.1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.1) + + ## ما الذي تغير + + ### الميزات + - إضافة request_id إلى HumanFeedbackRequestedEvent + - إضافة Qdrant Edge كخلفية تخزين لنظام الذاكرة + - إضافة أمر docs-check لتحليل التغييرات وتوليد الوثائق مع الترجمات + - إضافة دعم اللغة العربية إلى سجل التغييرات وأدوات الإصدار + - إضافة ترجمة باللغة العربية الفصحى لجميع الوثائق + - إضافة أمر تسجيل الخروج في واجهة سطر الأوامر + - إضافة مهارات الوكيل + - تنفيذ root_scope تلقائيًا لعزل الذاكرة الهيكلية + - تنفيذ مزودين متوافقين مع OpenAI (OpenRouter، DeepSeek، Ollama، vLLM، Cerebras، Dashscope) + + ### إصلاحات الأخطاء + - إصلاح بيانات اعتماد غير صحيحة لدفع دفعات التتبع (404) + - حل العديد من الأخطاء في نظام تدفق HITL + - إصلاح حفظ ذاكرة الوكيل + - حل جميع أخطاء mypy الصارمة عبر حزمة crewai + - إصلاح استخدام __router_paths__ لطرق المستمع + الموجه في FlowMeta + - إصلاح خطأ القيمة عند عدم دعم الملفات + - تصحيح صياغة الحجر الصحي لـ litellm في الوثائق + - إصلاح جميع أخطاء mypy في crewai-files وإضافة جميع الحزم إلى فحوصات النوع في CI + - تثبيت الحد الأعلى لـ litellm على آخر إصدار تم اختباره (1.82.6) + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.12.0 + - إضافة CONTRIBUTING.md + - إضافة دليل لاستخدام CrewAI بدون LiteLLM + + ## المساهمون + + @akaKuruma، @alex-clawd، @greysonlalonde، @iris-clawd، @joaomdmoura، @lorenzejay، @lucasgomide، @nicoferdi96 + + + + + ## v1.12.0 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.0) + + ## ما الذي تغير + + ### الميزات + - إضافة واجهة تخزين Qdrant Edge لنظام الذاكرة + - إضافة أمر docs-check لتحليل التغييرات وتوليد الوثائق مع الترجمات + - إضافة دعم اللغة العربية لسجل التغييرات وأدوات الإصدار + - إضافة ترجمة اللغة العربية الفصحى لجميع الوثائق + - إضافة أمر تسجيل الخروج في واجهة سطر الأوامر + - تنفيذ مهارات الوكيل + - تنفيذ نطاق الجذر التلقائي لعزل الذاكرة الهرمية + - تنفيذ موفري خدمات متوافقين مع OpenAI (OpenRouter، DeepSeek، Ollama، vLLM، Cerebras، Dashscope) + + ### إصلاح الأخطاء + - إصلاح بيانات الاعتماد السيئة لدفع دفعات التتبع (404) + - حل العديد من الأخطاء في نظام تدفق HITL + - حل أخطاء mypy في crewai-files وإضافة جميع الحزم إلى فحوصات نوع CI + - حل جميع أخطاء mypy الصارمة عبر حزمة crewai-tools + - حل جميع أخطاء mypy عبر حزمة crewai + - إصلاح حفظ الذاكرة في الوكيل + - إصلاح استخدام __router_paths__ لطرق المستمع + الموجه في FlowMeta + - رفع خطأ القيمة عند عدم دعم الملفات + - تصحيح صياغة الحجر الصحي لـ litellm في الوثائق + - استخدام فحص None بدلاً من isinstance للذاكرة في تعلم التغذية الراجعة البشرية + - تثبيت الحد الأعلى لـ litellm على آخر إصدار تم اختباره (1.82.6) + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.12.0 + - إضافة CONTRIBUTING.md + - إضافة دليل لاستخدام CrewAI بدون LiteLLM + + ### إعادة الهيكلة + - إعادة هيكلة لتجنب تكرار تنفيذ المهام المتزامنة / غير المتزامنة وبدء التشغيل في الوكيل + - تبسيط الأنابيب الداخلية من litellm (عد الرموز، ردود النداء، اكتشاف الميزات، الأخطاء) + + ## المساهمون + + @akaKuruma، @alex-clawd، @greysonlalonde، @iris-clawd، @joaomdmoura، @lorenzejay، @nicoferdi96 + + + + + ## v1.12.0a3 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.0a3) + + ## ما الذي تغير + + ### إصلاحات الأخطاء + - إصلاح بيانات الاعتماد الخاطئة لدفع دفعات التتبع (404) + - حل العديد من الأخطاء في نظام تدفق HITL + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.12.0a2 + + ## المساهمون + + @akaKuruma, @greysonlalonde + + + + + ## v1.12.0a2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.0a2) + + ## ما الذي تغير + + ### الميزات + - إضافة واجهة تخزين Qdrant Edge لنظام الذاكرة + + ### الوثائق + - تحديث سجل التغييرات والإصدار لـ v1.12.0a1 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.12.0a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.12.0a1) + + ## ما الذي تغير + + ### الميزات + - إضافة أمر docs-check لتحليل التغييرات وتوليد الوثائق مع الترجمات + - إضافة دعم اللغة العربية لسجل التغييرات وأدوات الإصدار + - إضافة ترجمة اللغة العربية الفصحى لجميع الوثائق + - إضافة مزودي خدمات متوافقين مع OpenAI (OpenRouter، DeepSeek، Ollama، vLLM، Cerebras، Dashscope) + - إضافة مهارات الوكيل + - إضافة أمر تسجيل الخروج في واجهة سطر الأوامر + - تنفيذ نطاق الجذر التلقائي لعزل الذاكرة الهيكلية + + ### إصلاح الأخطاء + - إصلاح حفظ ذاكرة الوكيل + - حل أخطاء mypy في crewai-files وإضافة جميع الحزم إلى فحوصات نوع CI + - حل جميع أخطاء mypy الصارمة عبر حزمة crewai-tools + - حل جميع أخطاء mypy عبر حزمة crewai + - إصلاح استخدام __router_paths__ لطرق المستمع + الموجه في FlowMeta + - تثبيت الحد الأعلى لـ litellm على آخر إصدار تم اختباره (1.82.6) + - رفع خطأ القيمة عند عدم دعم الملفات + - تصحيح صياغة الحجر الصحي لـ litellm في الوثائق + + ### الوثائق + - إضافة CONTRIBUTING.md + - إضافة دليل لاستخدام CrewAI بدون LiteLLM + - تحديث سجل التغييرات والإصدار لـ v1.11.1 + + ### إعادة الهيكلة + - إعادة هيكلة لإزالة التكرار في تنفيذ المهام المتزامنة وغير المتزامنة وبدء التشغيل في الوكيل + - فصل الأنابيب الداخلية عن litellm (عد الرموز، ردود الفعل، اكتشاف الميزات، الأخطاء) + + ## المساهمون + + @alex-clawd، @greysonlalonde، @iris-clawd، @lorenzejay، @nicoferdi96 + + + + + ## v1.11.1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.11.1) + + ## ما تغيّر + + ### الميزات + - إضافة مُسلسِل flow_structure() لفحص فئة Flow. + + ### إصلاحات الأخطاء + - إصلاح ثغرات أمنية بتحديث pypdf و tinytag و langchain-core. + - الحفاظ على تهيئة LLM الكاملة عبر استئناف HITL لمزودي غير OpenAI. + - منع اجتياز المسار في FileWriterTool. + - إصلاح انهيار lock_store عندما لا تكون حزمة redis مثبتة. + - تمرير cache_function من BaseTool إلى CrewStructuredTool. + + ### التوثيق + - إضافة دليل نشر الأدوات المخصصة مع الترجمات. + - تحديث سجل التغييرات والإصدار لـ v1.11.0. + - إضافة توثيق مستمعي الأحداث المفقود. + + ### إعادة الهيكلة + - استبدال urllib بـ requests في محمّل PDF. + - استبدال حقول callback والنموذج من نوع Any بأنواع قابلة للتسلسل. + + ## المساهمون + + @alex-clawd, @danielfsbarreto, @dependabot[bot], @greysonlalonde, @lorenzejay, @lucasgomide, @mattatcha, @theCyberTech, @vinibrsl + + + + + ## v1.11.0 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.11.0) + + ## ما تغيّر + + ### التوثيق + - تحديث سجل التغييرات والإصدار لـ v1.11.0rc2 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.11.0rc2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.11.0rc2) + + ## ما تغيّر + + ### إصلاحات الأخطاء + - تحسين معالجة استجابات LLM والتسلسل. + - ترقية الاعتماديات الانتقالية المعرضة للخطر (authlib، PyJWT، snowflake-connector-python). + - استبدال `os.system` بـ `subprocess.run` في تثبيت pip بالوضع غير الآمن. + + ### التوثيق + - تحديث صفحة أداة Exa Search بتسمية ووصف وخيارات تهيئة محسّنة. + - إضافة خوادم MCP المخصصة في دليل الإرشادات. + - تحديث توثيق جامعي OTEL. + - تحديث توثيق MCP. + - تحديث سجل التغييرات والإصدار لـ v1.11.0rc1. + + ## المساهمون + + @10ishq, @greysonlalonde, @joaomdmoura, @lucasgomide, @mattatcha, @theCyberTech, @vinibrsl + + + + + ## v1.11.0rc1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.11.0rc1) + + ## ما تغيّر + + ### الميزات + - إضافة مصادقة رمز Plus API في a2a + - تنفيذ نمط التخطيط والتنفيذ + + ### إصلاحات الأخطاء + - حل مشكلة هروب صندوق حماية مفسر الكود + + ### التوثيق + - تحديث سجل التغييرات والإصدار لـ v1.10.2rc2 + + ## المساهمون + + @Copilot, @greysonlalonde, @lorenzejay, @theCyberTech + + + + + ## v1.10.2rc2 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.10.2rc2) + + ## ما تغيّر + + ### إصلاحات الأخطاء + - إزالة الأقفال الحصرية من عمليات التخزين للقراءة فقط + + ### التوثيق + - تحديث سجل التغييرات والإصدار لـ v1.10.2rc1 + + ## المساهمون + + @greysonlalonde + + + + + ## v1.10.2rc1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.10.2rc1) + + ## ما تغيّر + + ### الميزات + - إضافة أمر الإصدار وتشغيل نشر PyPI + + ### إصلاحات الأخطاء + - إصلاح القفل الآمن عبر العمليات والخيوط للإدخال/الإخراج غير المحمي + - نشر contextvars عبر جميع حدود الخيوط والمنفذين + - نشر ContextVars إلى خيوط المهام غير المتزامنة + + ### التوثيق + - تحديث سجل التغييرات والإصدار لـ v1.10.2a1 + + ## المساهمون + + @danglies007, @greysonlalonde + + + + + ## v1.10.2a1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.10.2a1) + + ## ما تغيّر + + ### الميزات + - إضافة دعم البحث عن الأدوات وتوفير الرموز وحقن الأدوات المناسبة ديناميكيًا أثناء التنفيذ لـ Anthropic. + - تقديم المزيد من أدوات Brave Search. + - إنشاء إجراء للإصدارات الليلية. + + ### إصلاحات الأخطاء + - إصلاح LockException تحت التنفيذ المتزامن متعدد العمليات. + - حل مشكلات تجميع نتائج الأدوات المتوازية في رسالة مستخدم واحدة. + - معالجة حلول أدوات MCP والقضاء على جميع الاتصالات المشتركة القابلة للتغيير. + - تحديث معالجة معاملات LLM في دالة human_feedback. + - إضافة طرق list/dict المفقودة إلى LockedListProxy و LockedDictProxy. + - نشر سياق contextvars إلى خيوط استدعاء الأدوات المتوازية. + - ترقية اعتمادية gitpython إلى >=3.1.41 لحل ثغرة اجتياز مسار CVE. + + ### إعادة الهيكلة + - إعادة هيكلة فئات الذاكرة لتكون قابلة للتسلسل. + + ### التوثيق + - تحديث سجل التغييرات والإصدار لـ v1.10.1. + + ## المساهمون + + @akaKuruma, @github-actions[bot], @giulio-leone, @greysonlalonde, @joaomdmoura, @jonathansampson, @lorenzejay, @lucasgomide, @mattatcha + + + + + ## v1.10.1 + + [عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.10.1) + + ## ما تغيّر + + ### الميزات + - ترقية Gemini GenAI + + ### إصلاحات الأخطاء + - ضبط قيمة مستمع المنفذ لتجنب التكرار + - تجميع أجزاء استجابة الدوال المتوازية في كائن Content واحد في Gemini + - إظهار مخرجات التفكير من نماذج التفكير في Gemini + - تحميل أدوات MCP والمنصة عندما تكون أدوات الوكيل None + - دعم بيئات Jupyter مع حلقات أحداث قيد التشغيل في A2A + - استخدام معرّف مجهول للتتبعات المؤقتة + - تمرير ترويسة plus بشكل مشروط + - تخطي تسجيل معالج الإشارة في الخيوط غير الرئيسية لقياس الأداء عن بعد + - حقن أخطاء الأدوات كملاحظات وحل تعارضات الأسماء + - ترقية pypdf من 4.x إلى 6.7.4 لحل تنبيهات Dependabot + - حل تنبيهات أمان Dependabot الحرجة والعالية + + ### التوثيق + - تحديث توثيق بث webhook + - ضبط لغة التوثيق من AOP إلى AMP + + ### المساهمون + @Vidit-Ostwal, @greysonlalonde, @heitorado, @joaomdmoura, @lorenzejay, @lucasgomide, @mplachta + + diff --git a/docs/v1.15.13/ar/concepts/agent-capabilities.mdx b/docs/v1.15.13/ar/concepts/agent-capabilities.mdx new file mode 100644 index 0000000000..f2a1e142c2 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/agent-capabilities.mdx @@ -0,0 +1,147 @@ +--- +title: "قدرات الوكيل" +description: "فهم الطرق الخمس لتوسيع وكلاء CrewAI: الأدوات، MCP، التطبيقات، المهارات، والمعرفة." +icon: puzzle-piece +mode: "wide" +--- + +## نظرة عامة + +يمكن توسيع وكلاء CrewAI بـ **خمسة أنواع مميزة من القدرات**، كل منها يخدم غرضًا مختلفًا. فهم متى تستخدم كل نوع — وكيف يعملون معًا — هو المفتاح لبناء وكلاء فعّالين. + + + + **دوال قابلة للاستدعاء** — تمنح الوكلاء القدرة على اتخاذ إجراءات. البحث على الويب، عمليات الملفات، استدعاءات API، تنفيذ الكود. + + + **خوادم أدوات عن بُعد** — تربط الوكلاء بخوادم أدوات خارجية عبر Model Context Protocol. نفس تأثير الأدوات، لكن مستضافة خارجيًا. + + + **تكاملات المنصة** — تربط الوكلاء بتطبيقات SaaS (Gmail، Slack، Jira، Salesforce) عبر منصة CrewAI. تعمل محليًا مع رمز تكامل المنصة. + + + **خبرة المجال** — تحقن التعليمات والإرشادات والمواد المرجعية في إرشادات الوكلاء. المهارات تخبر الوكلاء *كيف يفكرون*. + + + **حقائق مُسترجعة** — توفر للوكلاء بيانات من المستندات والملفات وعناوين URL عبر البحث الدلالي (RAG). المعرفة تعطي الوكلاء *ما يحتاجون معرفته*. + + + +--- + +## التمييز الأساسي + +أهم شيء يجب فهمه: **هذه القدرات تنقسم إلى فئتين**. + +### قدرات الإجراء (الأدوات، MCP، التطبيقات) + +تمنح الوكلاء القدرة على **فعل أشياء** — استدعاء APIs، قراءة الملفات، البحث على الويب، إرسال رسائل البريد الإلكتروني. عند التنفيذ، تتحول الأنواع الثلاثة إلى نفس التنسيق الداخلي (مثيلات `BaseTool`) وتظهر في قائمة أدوات موحدة يمكن للوكيل استدعاؤها. + +```python +from crewai import Agent +from crewai_tools import SerperDevTool, FileReadTool + +agent = Agent( + role="Researcher", + goal="Find and compile market data", + backstory="Expert market analyst", + tools=[SerperDevTool(), FileReadTool()], # أدوات محلية + mcps=["https://mcp.example.com/sse"], # أدوات خادم MCP عن بُعد + apps=["gmail", "google_sheets"], # تكاملات المنصة +) +``` + +### قدرات السياق (المهارات، المعرفة) + +تُعدّل **إرشادات** الوكيل — بحقن الخبرة أو التعليمات أو البيانات المُسترجعة قبل أن يبدأ الوكيل في التفكير. لا تمنح الوكلاء إجراءات جديدة؛ بل تُشكّل كيف يفكر الوكلاء وما هي المعلومات التي يمكنهم الوصول إليها. + +```python +from crewai import Agent + +agent = Agent( + role="Security Auditor", + goal="Audit cloud infrastructure for vulnerabilities", + backstory="Expert in cloud security with 10 years of experience", + skills=["./skills/security-audit"], # تعليمات المجال + knowledge_sources=[pdf_source, url_source], # حقائق مُسترجعة +) +``` + +--- + +## متى تستخدم ماذا + +| تحتاج إلى... | استخدم | مثال | +| :------------------------------------------------------- | :---------------- | :--------------------------------------- | +| الوكيل يبحث على الويب | **الأدوات** | `tools=[SerperDevTool()]` | +| الوكيل يستدعي API عن بُعد عبر MCP | **MCP** | `mcps=["https://api.example.com/sse"]` | +| الوكيل يرسل بريد إلكتروني عبر Gmail | **التطبيقات** | `apps=["gmail"]` | +| الوكيل يتبع إجراءات محددة | **المهارات** | `skills=["./skills/code-review"]` | +| الوكيل يرجع لمستندات الشركة | **المعرفة** | `knowledge_sources=[pdf_source]` | +| الوكيل يبحث على الويب ويتبع إرشادات المراجعة | **الأدوات + المهارات** | استخدم كليهما معًا | + +--- + +## دمج القدرات + +في الممارسة العملية، غالبًا ما يستخدم الوكلاء **أنواعًا متعددة من القدرات معًا**. إليك مثال واقعي: + +```python +from crewai import Agent +from crewai_tools import SerperDevTool, FileReadTool, CodeInterpreterTool + +# وكيل بحث مجهز بالكامل +researcher = Agent( + role="Senior Research Analyst", + goal="Produce comprehensive market analysis reports", + backstory="Expert analyst with deep industry knowledge", + + # الإجراء: ما يمكن للوكيل فعله + tools=[ + SerperDevTool(), # البحث على الويب + FileReadTool(), # قراءة الملفات المحلية + CodeInterpreterTool(), # تشغيل كود Python للتحليل + ], + mcps=["https://data-api.example.com/sse"], # الوصول لـ API بيانات عن بُعد + apps=["google_sheets"], # الكتابة في Google Sheets + + # السياق: ما يعرفه الوكيل + skills=["./skills/research-methodology"], # كيفية إجراء البحث + knowledge_sources=[company_docs], # بيانات خاصة بالشركة +) +``` + +--- + +## جدول المقارنة + +| الميزة | الأدوات | MCP | التطبيقات | المهارات | المعرفة | +| :--- | :---: | :---: | :---: | :---: | :---: | +| **يمنح الوكيل إجراءات** | ✅ | ✅ | ✅ | ❌ | ❌ | +| **يُعدّل الإرشادات** | ❌ | ❌ | ❌ | ✅ | ✅ | +| **يتطلب كود** | نعم | إعداد فقط | إعداد فقط | Markdown فقط | إعداد فقط | +| **يعمل محليًا** | نعم | يعتمد | نعم (مع متغير بيئة) | غير متاح | نعم | +| **يحتاج مفاتيح API** | لكل أداة | لكل خادم | رمز التكامل | لا | المُضمّن فقط | +| **يُعيَّن على Agent** | `tools=[]` | `mcps=[]` | `apps=[]` | `skills=[]` | `knowledge_sources=[]` | +| **يُعيَّن على Crew** | ❌ | ❌ | ❌ | `skills=[]` | `knowledge_sources=[]` | + +--- + +## تعمّق أكثر + +هل أنت مستعد لمعرفة المزيد عن كل نوع من أنواع القدرات؟ + + + + إنشاء أدوات مخصصة، استخدام كتالوج OSS مع أكثر من 75 خيارًا، تكوين التخزين المؤقت والتنفيذ غير المتزامن. + + + الاتصال بخوادم MCP عبر stdio أو SSE أو HTTP. تصفية الأدوات، تكوين المصادقة. + + + بناء حزم المهارات مع SKILL.md، حقن خبرة المجال، استخدام الكشف التدريجي. + + + إضافة المعرفة من ملفات PDF وCSV وعناوين URL والمزيد. تكوين المُضمّنات والاسترجاع. + + diff --git a/docs/v1.15.13/ar/concepts/agents.mdx b/docs/v1.15.13/ar/concepts/agents.mdx new file mode 100644 index 0000000000..685320db2d --- /dev/null +++ b/docs/v1.15.13/ar/concepts/agents.mdx @@ -0,0 +1,383 @@ +--- +title: الوكلاء +description: دليل تفصيلي حول إنشاء وإدارة الوكلاء ضمن إطار عمل CrewAI. +icon: robot +mode: "wide" +--- + +## نظرة عامة على الوكيل + +في إطار عمل CrewAI، الـ `Agent` هو وحدة مستقلة يمكنها: + +- أداء مهام محددة +- اتخاذ قرارات بناءً على دوره وهدفه +- استخدام الأدوات لتحقيق الأهداف +- التواصل والتعاون مع وكلاء آخرين +- الاحتفاظ بذاكرة التفاعلات +- تفويض المهام عند السماح بذلك + + + فكّر في الوكيل كعضو فريق متخصص بمهارات وخبرات ومسؤوليات محددة. + على سبيل المثال، قد يتفوق وكيل `Researcher` في جمع وتحليل المعلومات، + بينما قد يكون وكيل `Writer` أفضل في إنشاء المحتوى. + + + +يتضمن CrewAI AMP منشئ وكلاء مرئي يبسّط إنشاء وتهيئة الوكلاء بدون كتابة كود. صمم وكلاءك بصريًا واختبرهم في الوقت الفعلي. + +![Visual Agent Builder Screenshot](/images/enterprise/crew-studio-interface.png) + +يُمكّن منشئ الوكلاء المرئي من: + +- تهيئة وكلاء بديهية بواجهات نماذج +- اختبار والتحقق في الوقت الفعلي +- مكتبة قوالب مع أنواع وكلاء مهيأة مسبقًا +- تخصيص سهل لخصائص وسلوكيات الوكيل + + +## خصائص الوكيل + +| الخاصية | المعامل | النوع | الوصف | +| :-------------------------------------- | :----------------------- | :------------------------------------ | :------------------------------------------------------------------------------------------------------- | +| **الدور** | `role` | `str` | يحدد وظيفة الوكيل وخبرته ضمن الطاقم. | +| **الهدف** | `goal` | `str` | الهدف الفردي الذي يوجه عملية اتخاذ القرار لدى الوكيل. | +| **الخلفية** | `backstory` | `str` | يوفر سياقًا وشخصية للوكيل، مما يثري التفاعلات. | +| **LLM** _(اختياري)_ | `llm` | `Union[str, LLM, Any]` | نموذج اللغة الذي يشغّل الوكيل. افتراضيًا النموذج المحدد في `OPENAI_MODEL_NAME` أو "gpt-4". | +| **الأدوات** _(اختياري)_ | `tools` | `List[BaseTool]` | القدرات أو الوظائف المتاحة للوكيل. افتراضيًا قائمة فارغة. | +| **LLM استدعاء الدوال** _(اختياري)_ | `function_calling_llm` | `Optional[Any]` | نموذج لغة لاستدعاء الأدوات، يتجاوز LLM الطاقم إذا حُدد. | +| **الحد الأقصى للتكرارات** _(اختياري)_ | `max_iter` | `int` | الحد الأقصى للتكرارات قبل أن يقدم الوكيل أفضل إجابته. الافتراضي 20. | +| **الحد الأقصى لـ RPM** _(اختياري)_ | `max_rpm` | `Optional[int]` | الحد الأقصى للطلبات في الدقيقة لتجنب حدود المعدل. | +| **الحد الأقصى لوقت التنفيذ** _(اختياري)_ | `max_execution_time` | `Optional[int]` | الحد الأقصى للوقت (بالثواني) لتنفيذ المهمة. | +| **الوضع المفصل** _(اختياري)_ | `verbose` | `bool` | تفعيل سجلات التنفيذ المفصلة للتصحيح. الافتراضي False. | +| **السماح بالتفويض** _(اختياري)_ | `allow_delegation` | `bool` | السماح للوكيل بتفويض المهام لوكلاء آخرين. الافتراضي False. | +| **دالة الخطوة** _(اختياري)_ | `step_callback` | `Optional[Any]` | دالة تُستدعى بعد كل خطوة للوكيل، تتجاوز دالة الطاقم. | +| **التخزين المؤقت** _(اختياري)_ | `cache` | `bool` | تفعيل التخزين المؤقت لاستخدام الأدوات. الافتراضي True. | +| **قالب النظام** _(اختياري)_ | `system_template` | `Optional[str]` | قالب أمر نظام مخصص للوكيل. | +| **قالب الأمر** _(اختياري)_ | `prompt_template` | `Optional[str]` | قالب أمر مخصص للوكيل. | +| **قالب الاستجابة** _(اختياري)_ | `response_template` | `Optional[str]` | قالب استجابة مخصص للوكيل. | +| **السماح بتنفيذ الكود** _(اختياري)_ | `allow_code_execution` | `Optional[bool]` | تفعيل تنفيذ الكود للوكيل. الافتراضي False. | +| **الحد الأقصى لإعادة المحاولة** _(اختياري)_ | `max_retry_limit` | `int` | الحد الأقصى لإعادات المحاولة عند حدوث خطأ. الافتراضي 2. | +| **احترام نافذة السياق** _(اختياري)_ | `respect_context_window` | `bool` | إبقاء الرسائل تحت حجم نافذة السياق عبر التلخيص. الافتراضي True. | +| **وضع تنفيذ الكود** _(اختياري)_ | `code_execution_mode` | `Literal["safe", "unsafe"]` | وضع تنفيذ الكود: 'safe' (باستخدام Docker) أو 'unsafe' (مباشر). الافتراضي 'safe'. | +| **متعدد الوسائط** _(اختياري)_ | `multimodal` | `bool` | ما إذا كان الوكيل يدعم القدرات متعددة الوسائط. الافتراضي False. | +| **حقن التاريخ** _(اختياري)_ | `inject_date` | `bool` | ما إذا كان يتم حقن التاريخ الحالي تلقائيًا في المهام. الافتراضي False. | +| **تنسيق التاريخ** _(اختياري)_ | `date_format` | `str` | سلسلة تنسيق التاريخ عند تفعيل inject_date. الافتراضي "%Y-%m-%d" (تنسيق ISO). | +| **الاستدلال** _(اختياري)_ | `reasoning` | `bool` | ما إذا كان يجب على الوكيل التأمل وإنشاء خطة قبل تنفيذ المهمة. الافتراضي False. | +| **الحد الأقصى لمحاولات الاستدلال** _(اختياري)_ | `max_reasoning_attempts` | `Optional[int]` | الحد الأقصى لمحاولات الاستدلال قبل تنفيذ المهمة. إذا None، سيحاول حتى الاستعداد. | +| **المُضمّن** _(اختياري)_ | `embedder` | `Optional[Dict[str, Any]]` | تهيئة المُضمّن المستخدم من قبل الوكيل. | +| **مصادر المعرفة** _(اختياري)_ | `knowledge_sources` | `Optional[List[BaseKnowledgeSource]]` | مصادر المعرفة المتاحة للوكيل. | +| **استخدام أمر النظام** _(اختياري)_ | `use_system_prompt` | `Optional[bool]` | ما إذا كان يُستخدم أمر النظام (لدعم نموذج o1). الافتراضي True. | + +## إنشاء الوكلاء + +هناك طريقتان شائعتان لإنشاء الوكلاء في CrewAI: باستخدام **تهيئة JSONC (الموصى بها للـ crews الجديدة)** أو تعريفهم **مباشرة في الكود**. + +### تهيئة JSONC (موصى بها) + +المشاريع الجديدة التي تُنشأ عبر `crewai create crew ` تستخدم تهيئة JSON-first. يُعرّف كل Agent في `agents/.jsonc`، ويحدد `crew.jsonc` أي Agents تدخل في الـ crew. + +```jsonc agents/researcher.jsonc +{ + "role": "{topic} Senior Data Researcher", + "goal": "Uncover cutting-edge developments in {topic}", + "backstory": "You find the most relevant information and present it clearly.", + "llm": "openai/gpt-4o", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +استخدم `{placeholder}` داخل `role` أو `goal` أو `backstory`. ضع القيم الافتراضية في `inputs` داخل `crew.jsonc`؛ وسيطلب `crewai run` أي قيم ناقصة. يمكن وضع حقول السلوك مثل `verbose` و `allow_delegation` و `max_iter` و `memory` و `cache` و `planning_config` في المستوى الأعلى أو داخل `settings`. + + +يدعم JSONC التعليقات والفواصل النهائية. إذا وُجد `agents/.jsonc` و `agents/.json` معًا، يستخدم CrewAI ملف JSONC. + + +### تهيئة YAML الكلاسيكية + +المشاريع الكلاسيكية التي تُنشأ عبر `crewai create crew --classic` تستخدم `config/agents.yaml` وفئة `@CrewBase` في `crew.py`. + +تظل تهيئة YAML مدعومة للمشاريع الحالية المبنية بـ Python/YAML وللفِرق التي تفضل تعريف الوكلاء من خلال فئة `@CrewBase`. + +بعد إنشاء مشروع كلاسيكي، انتقل إلى ملف `src//config/agents.yaml` وعدّل القالب ليتوافق مع متطلباتك. + + +ستُستبدل المتغيرات في ملفات YAML (مثل `{topic}`) بقيم من مدخلاتك عند تشغيل الطاقم: +```python Code +crew.kickoff(inputs={'topic': 'AI Agents'}) +``` + + +إليك مثالًا على كيفية تهيئة الوكلاء باستخدام YAML: + +```yaml agents.yaml +# src//config/agents.yaml +researcher: + role: > + {topic} Senior Data Researcher + goal: > + Uncover cutting-edge developments in {topic} + backstory: > + You're a seasoned researcher with a knack for uncovering the latest + developments in {topic}. Known for your ability to find the most relevant + information and present it in a clear and concise manner. + +reporting_analyst: + role: > + {topic} Reporting Analyst + goal: > + Create detailed reports based on {topic} data analysis and research findings + backstory: > + You're a meticulous analyst with a keen eye for detail. You're known for + your ability to turn complex data into clear and concise reports, making + it easy for others to understand and act on the information you provide. +``` + +لاستخدام تهيئة YAML في الكود، أنشئ فئة طاقم ترث من `CrewBase`: + +```python Code +# src//crew.py +from crewai import Agent, Crew, Process +from crewai.project import CrewBase, agent, crew +from crewai_tools import SerperDevTool + +@CrewBase +class LatestAiDevelopmentCrew(): + """LatestAiDevelopment crew""" + + agents_config = "config/agents.yaml" + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], # type: ignore[index] + verbose=True, + tools=[SerperDevTool()] + ) + + @agent + def reporting_analyst(self) -> Agent: + return Agent( + config=self.agents_config['reporting_analyst'], # type: ignore[index] + verbose=True + ) +``` + + + يجب أن تتطابق الأسماء المستخدمة في ملفات YAML (`agents.yaml`) مع أسماء + الطرق في كود Python. + + +### تعريف مباشر في الكود + +يمكنك إنشاء الوكلاء مباشرة في الكود بإنشاء فئة `Agent`. إليك مثالًا شاملًا يوضح جميع المعاملات المتاحة: + +```python Code +from crewai import Agent +from crewai_tools import SerperDevTool + +# إنشاء وكيل بجميع المعاملات المتاحة +agent = Agent( + role="Senior Data Scientist", + goal="Analyze and interpret complex datasets to provide actionable insights", + backstory="With over 10 years of experience in data science and machine learning, " + "you excel at finding patterns in complex datasets.", + llm="gpt-4", + function_calling_llm=None, + verbose=False, + allow_delegation=False, + max_iter=20, + max_rpm=None, + max_execution_time=None, + max_retry_limit=2, + allow_code_execution=False, + code_execution_mode="safe", + respect_context_window=True, + use_system_prompt=True, + multimodal=False, + inject_date=False, + date_format="%Y-%m-%d", + reasoning=False, + max_reasoning_attempts=None, + tools=[SerperDevTool()], + knowledge_sources=None, + embedder=None, + system_template=None, + prompt_template=None, + response_template=None, + step_callback=None, +) +``` + +دعنا نستعرض بعض تركيبات المعاملات الرئيسية لحالات الاستخدام الشائعة: + +#### وكيل بحث أساسي + +```python Code +research_agent = Agent( + role="Research Analyst", + goal="Find and summarize information about specific topics", + backstory="You are an experienced researcher with attention to detail", + tools=[SerperDevTool()], + verbose=True +) +``` + +#### وكيل تطوير الكود + +```python Code +dev_agent = Agent( + role="Senior Python Developer", + goal="Write and debug Python code", + backstory="Expert Python developer with 10 years of experience", + allow_code_execution=True, + code_execution_mode="safe", + max_execution_time=300, + max_retry_limit=3 +) +``` + +#### وكيل تحليل طويل المدى + +```python Code +analysis_agent = Agent( + role="Data Analyst", + goal="Perform deep analysis of large datasets", + backstory="Specialized in big data analysis and pattern recognition", + memory=True, + respect_context_window=True, + max_rpm=10, + function_calling_llm="gpt-4o-mini" +) +``` + +### تفاصيل المعاملات + +#### المعاملات الحرجة + +- `role` و `goal` و `backstory` مطلوبة وتشكّل سلوك الوكيل +- `llm` يحدد نموذج اللغة المستخدم (افتراضي: GPT-4 من OpenAI) + +#### الذاكرة والسياق + +- `memory`: تفعيل للحفاظ على سجل المحادثة +- `respect_context_window`: يمنع مشاكل حد الرموز +- `knowledge_sources`: إضافة قواعد معرفة خاصة بالمجال + +#### التحكم في التنفيذ + +- `max_iter`: الحد الأقصى للمحاولات قبل تقديم أفضل إجابة +- `max_execution_time`: المهلة بالثواني +- `max_rpm`: تحديد معدل استدعاءات API +- `max_retry_limit`: إعادات المحاولة عند الخطأ + +#### تنفيذ الكود + + + `allow_code_execution` و`code_execution_mode` مهجوران. تمت إزالة `CodeInterpreterTool` من `crewai-tools`. استخدم خدمة بيئة معزولة مخصصة مثل [E2B](https://e2b.dev) أو [Modal](https://modal.com) لتنفيذ الكود بأمان. + + +- `allow_code_execution` _(مهجور)_: كان يُمكّن تنفيذ الكود المدمج عبر `CodeInterpreterTool`. +- `code_execution_mode` _(مهجور)_: كان يتحكم في وضع التنفيذ (`"safe"` لـ Docker، `"unsafe"` للتنفيذ المباشر). + +#### الميزات المتقدمة + +- `multimodal`: تفعيل القدرات متعددة الوسائط لمعالجة النص والمحتوى المرئي +- `reasoning`: تمكين الوكيل من التأمل وإنشاء خطط قبل تنفيذ المهام +- `inject_date`: حقن التاريخ الحالي تلقائيًا في أوصاف المهام + +#### القوالب + +- `system_template`: يحدد السلوك الأساسي للوكيل +- `prompt_template`: ينظم تنسيق الإدخال +- `response_template`: ينسّق استجابات الوكيل + + + عند استخدام القوالب المخصصة، تأكد من تعريف كل من `system_template` و + `prompt_template`. `response_template` اختياري لكن يُوصى به + لتنسيق مخرجات متسق. + + +## أدوات الوكيل + +يمكن تجهيز الوكلاء بأدوات متنوعة لتعزيز قدراتهم. يدعم CrewAI أدوات من: + +- [مجموعة أدوات CrewAI](https://github.com/joaomdmoura/crewai-tools) +- [أدوات LangChain](https://python.langchain.com/docs/integrations/tools) + +إليك كيفية إضافة أدوات لوكيل: + +```python Code +from crewai import Agent +from crewai_tools import SerperDevTool, WikipediaTools + +# إنشاء الأدوات +search_tool = SerperDevTool() +wiki_tool = WikipediaTools() + +# إضافة أدوات للوكيل +researcher = Agent( + role="AI Technology Researcher", + goal="Research the latest AI developments", + tools=[search_tool, wiki_tool], + verbose=True +) +``` + +## التفاعل المباشر مع الوكيل عبر `kickoff()` + +يمكن استخدام الوكلاء مباشرة بدون المرور بمهمة أو سير عمل طاقم باستخدام طريقة `kickoff()`. يوفر هذا طريقة أبسط للتفاعل مع وكيل عندما لا تحتاج إلى إمكانيات تنسيق الطاقم الكاملة. + +```python Code +from crewai import Agent +from crewai_tools import SerperDevTool + +# إنشاء وكيل +researcher = Agent( + role="AI Technology Researcher", + goal="Research the latest AI developments", + tools=[SerperDevTool()], + verbose=True +) + +# استخدام kickoff() للتفاعل مباشرة مع الوكيل +result = researcher.kickoff("What are the latest developments in language models?") + +# الوصول إلى الاستجابة الخام +print(result.raw) +``` + +## اعتبارات مهمة وأفضل الممارسات + +### الأمان وتنفيذ الكود + + + `allow_code_execution` و`code_execution_mode` مهجوران وتمت إزالة `CodeInterpreterTool`. استخدم خدمة بيئة معزولة مخصصة مثل [E2B](https://e2b.dev) أو [Modal](https://modal.com) لتنفيذ الكود بأمان. + + +### تحسين الأداء + +- استخدم `respect_context_window: true` لمنع مشاكل حد الرموز +- عيّن `max_rpm` مناسبًا لتجنب تحديد المعدل +- فعّل `cache: true` لتحسين الأداء للمهام المتكررة +- اضبط `max_iter` و `max_retry_limit` بناءً على تعقيد المهمة + +### إدارة الذاكرة والسياق + +- استفد من `knowledge_sources` للمعلومات الخاصة بالمجال +- هيّئ `embedder` عند استخدام نماذج تضمين مخصصة +- استخدم القوالب المخصصة للتحكم الدقيق في سلوك الوكيل + +### التعاون بين الوكلاء + +- فعّل `allow_delegation: true` عندما يحتاج الوكلاء للعمل معًا +- استخدم `step_callback` لمراقبة وتسجيل تفاعلات الوكلاء +- فكّر في استخدام نماذج LLM مختلفة لأغراض مختلفة + +### توافق النموذج + +- عيّن `use_system_prompt: false` للنماذج القديمة التي لا تدعم رسائل النظام +- تأكد من أن `llm` المختار يدعم الميزات التي تحتاجها diff --git a/docs/v1.15.13/ar/concepts/checkpointing.mdx b/docs/v1.15.13/ar/concepts/checkpointing.mdx new file mode 100644 index 0000000000..7cb52ece83 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/checkpointing.mdx @@ -0,0 +1,423 @@ +--- +title: Checkpointing +description: حفظ حالة التنفيذ تلقائيا حتى تتمكن الطواقم والتدفقات والوكلاء من الاستئناف بعد الفشل. +icon: floppy-disk +mode: "wide" +--- + +الـ Checkpointing يحفظ لقطة من حالة التنفيذ أثناء التشغيل بحيث يمكن لطاقم أو تدفق أو وكيل الاستئناف بعد الفشل أو التفرع إلى فرع بديل. + + + + كيف يعمل الـ Checkpointing: الأحداث والتخزين والوراثة. + + + دليل 5 دقائق: تشغيل، إيقاف، استئناف. + + + وصفات مركزة على المهام لسير العمل الشائع. + + + `CheckpointConfig` والأحداث والمزودات وسطر الأوامر. + + + +## الشرح + +### ما هي نقطة الحفظ + +تلتقط نقطة الحفظ كل ما يحتاجه CrewAI لإعادة إنشاء تشغيل أثناء سيره: الحالة الكاملة للطاقم أو التدفق أو الوكيل — التكوين، وذاكرة الوكلاء ومصادر المعرفة، وتقدم المهام، والمخرجات الوسيطة، والحالة الداخلية والسمات — إلى جانب مدخلات الـ kickoff، وسجل الأحداث حتى تلك النقطة، ومعرف نسب يربط نقطة الحفظ بالتشغيل الذي جاءت منه. + +الاستعادة تعيد بناء تلك الحالة وتستمر. تتخطى المهام المكتملة، وتعاد ترطيب الذاكرة والمعرفة، ويعمل العمل التابع على نفس المخرجات التي أنتجها التشغيل الأصلي. التفرع يجري نفس الاستعادة تحت نسب جديد، بحيث يكتب الفرع الجديد والتشغيل الأصلي نقاط الحفظ جنبا إلى جنب دون أن يطمس أحدهما الآخر. + +### متى تكتب نقاط الحفظ + +الـ Checkpointing مدفوع بالأحداث. يشترك وقت التشغيل في الأحداث التي تحددها عبر `on_events` ويكتب نقطة حفظ عند إطلاق أحدها. الافتراضي `task_completed` ينتج نقطة حفظ لكل مهمة منتهية — توازن معقول بين الدقة واستخدام القرص. الأحداث عالية التردد مثل `llm_call_completed` متاحة للاستعادة الدقيقة لكنها تكتب ملفات أكثر بكثير. + +### التخزين + +يتضمن CrewAI مزودين: + +- `JsonProvider` يكتب ملفا لكل نقطة حفظ. قابل للقراءة وسهل التفقد. +- `SqliteProvider` يكتب إلى قاعدة بيانات SQLite واحدة. أفضل لنقاط الحفظ عالية التردد. + +كلاهما يحذف أقدم نقاط الحفظ عند تحديد `max_checkpoints`. + + +كتابة نقاط الحفظ بأفضل جهد. فشل نقطة حفظ يسجل لكنه لا يقاطع التشغيل. + + +### نموذج الوراثة + +`Crew` و`Flow` و`Agent` كلها تقبل وسيط `checkpoint`. يرث الأبناء من الأب ما لم يحددوا قيمتهم الخاصة أو يمرروا `False` للانسحاب. فعل الـ Checkpointing مرة واحدة على الطاقم وتشارك كل الوكلاء، أو استبعد وكيلا واحدا بشكل انتقائي. + +## درس تطبيقي: استئناف طاقم فاشل + +هذا الدليل يستغرق حوالي 5 دقائق. ستشغل طاقما بمهمتين، توقفه في المنتصف، ثم تستأنف من نقطة الحفظ المحفوظة. + + + + ```python + from crewai import Agent, Crew, Task + + researcher = Agent(role="Researcher", goal="Research", backstory="Expert") + writer = Agent(role="Writer", goal="Write", backstory="Expert") + + crew = Crew( + agents=[researcher, writer], + tasks=[ + Task(description="Research AI trends", agent=researcher, expected_output="bullets"), + Task(description="Write a summary", agent=writer, expected_output="paragraph"), + ], + checkpoint=True, + ) + ``` + + + ```python + result = crew.kickoff() + ``` + + اضغط `Ctrl+C` بعد انتهاء المهمة الأولى. في `./.checkpoints/`، الملف بصيغة `_.json` هو نقطة الحفظ. + + + ```python + from crewai import CheckpointConfig + + result = crew.kickoff( + from_checkpoint=CheckpointConfig( + restore_from="./.checkpoints/_.json", + ), + ) + ``` + + يتم تخطي مهمة البحث، ويعمل الكاتب على مخرجات البحث المحفوظة، وينتهي الطاقم. + + + +## ادلة عملية + + + + ```python + crew = Crew(agents=[...], tasks=[...], checkpoint=True) + ``` + + يكتب إلى `./.checkpoints/` عند كل `task_completed`. + + + + ```python + from crewai import Crew, CheckpointConfig + + crew = Crew( + agents=[...], + tasks=[...], + checkpoint=CheckpointConfig( + location="./my_checkpoints", + on_events=["task_completed", "crew_kickoff_completed"], + max_checkpoints=5, + ), + ) + ``` + + + + + ```python JsonProvider + from crewai import Crew, CheckpointConfig + from crewai.state import JsonProvider + + crew = Crew( + agents=[...], + tasks=[...], + checkpoint=CheckpointConfig( + location="./my_checkpoints", + provider=JsonProvider(), + max_checkpoints=5, + ), + ) + ``` + ```python SqliteProvider + from crewai import Crew, CheckpointConfig + from crewai.state import SqliteProvider + + crew = Crew( + agents=[...], + tasks=[...], + checkpoint=CheckpointConfig( + location="./.checkpoints.db", + provider=SqliteProvider(), + max_checkpoints=50, + ), + ) + ``` + + + + SQLite يفعل وضع journal WAL للقراءات المتزامنة. يفضل لنقاط الحفظ عالية التردد. + + + + + ```python + crew = Crew( + agents=[ + Agent(role="Researcher", ...), + Agent(role="Writer", ..., checkpoint=False), + ], + tasks=[...], + checkpoint=True, + ) + ``` + + + + `fork()` يستعيد نقطة حفظ تحت نسب جديد بحيث لا يتصادم التشغيل الجديد مع الأصلي. + + ```python + config = CheckpointConfig(restore_from="./my_checkpoints/.json") + crew = Crew.fork(config, branch="experiment-a") + result = crew.kickoff(inputs={"strategy": "aggressive"}) + ``` + + تسمية `branch` اختيارية؛ يتم إنشاء واحدة إذا أغفلت. + + + + + + ```python + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, write_task, review_task], + checkpoint=CheckpointConfig(location="./crew_cp"), + ) + ``` + + المشغل الافتراضي: `task_completed`. + + + ```python + from crewai.flow.flow import Flow, start, listen + from crewai import CheckpointConfig + + class MyFlow(Flow): + @start() + def step_one(self): + return "data" + + @listen(step_one) + def step_two(self, data): + return process(data) + + flow = MyFlow( + checkpoint=CheckpointConfig( + location="./flow_cp", + on_events=["method_execution_finished"], + ), + ) + result = flow.kickoff() + ``` + + + ```python + agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + checkpoint=CheckpointConfig( + location="./agent_cp", + on_events=["lite_agent_execution_completed"], + ), + ) + result = agent.kickoff(messages=[{"role": "user", "content": "Research AI trends"}]) + ``` + + + + + + سجل معالجا على أي حدث واستدع `state.checkpoint()`. + + + ```python Sync + from __future__ import annotations + + from typing import TYPE_CHECKING, Any + + from crewai.events.event_bus import crewai_event_bus + from crewai.events.types.llm_events import LLMCallCompletedEvent + + if TYPE_CHECKING: + from crewai.state.runtime import RuntimeState + + + @crewai_event_bus.on(LLMCallCompletedEvent) + def on_llm_done(source: Any, event: LLMCallCompletedEvent, state: RuntimeState) -> None: + path = state.checkpoint("./my_checkpoints") + print(f"تم حفظ نقطة الحفظ: {path}") + ``` + ```python Async + from __future__ import annotations + + from typing import TYPE_CHECKING, Any + + from crewai.events.event_bus import crewai_event_bus + from crewai.events.types.llm_events import LLMCallCompletedEvent + + if TYPE_CHECKING: + from crewai.state.runtime import RuntimeState + + + @crewai_event_bus.on(LLMCallCompletedEvent) + async def on_llm_done_async(source: Any, event: LLMCallCompletedEvent, state: RuntimeState) -> None: + path = await state.acheckpoint("./my_checkpoints") + print(f"تم حفظ نقطة الحفظ: {path}") + ``` + + + يتم تمرير وسيط `state` تلقائيا عندما يقبل المعالج ثلاثة معاملات. راجع [Event Listeners](/ar/concepts/event-listener) لقائمة الأحداث الكاملة. + + + + ```bash + crewai checkpoint + crewai checkpoint --location ./my_checkpoints + crewai checkpoint --location ./.checkpoints.db + ``` + + + Checkpoint TUI tree view + + + اللوحة اليسرى تجمع نقاط الحفظ حسب الفرع؛ التفرعات تتداخل تحت أبيها. اختيار نقطة حفظ يفتح لوحة التفاصيل مع بياناتها الوصفية وحالة الكيان وتقدم المهام. **Resume** يكمل التشغيل؛ **Fork** يبدأ فرعا جديدا. + + + Checkpoint detail overview tab + + + لوحة التفاصيل تعرض منطقتين قابلتين للتحرير: + + - **Inputs** — مدخلات الـ kickoff الأصلية، معبأة مسبقا وقابلة للتحرير. + + + Editable kickoff inputs + + + - **مخرجات المهام** — مخرجات المهام المكتملة. تحرير مخرج والضغط على **Fork** يبطل المهام التابعة لتعاد بالسياق المعدل. + + + Editable task outputs + + + + Fork confirmation panel + + + + مفيد لاستكشاف "ماذا لو": تفرع، عدل، راقب. + + + + + ```bash + crewai checkpoint list ./my_checkpoints + crewai checkpoint info ./my_checkpoints/.json + crewai checkpoint info ./.checkpoints.db + ``` + + + +## المرجع + +### `CheckpointConfig` + + + وجهة التخزين. مجلد لـ `JsonProvider`، مسار ملف قاعدة بيانات لـ `SqliteProvider`. + + + + أنواع الأحداث التي تطلق نقطة حفظ. `CheckpointEventType` هو `Literal` — مدقق الأنواع يكمل تلقائيا ويرفض القيم غير المدعومة. راجع [أنواع الأحداث](#أنواع-الأحداث) للقائمة الكاملة. + + + + واجهة التخزين. `JsonProvider` أو `SqliteProvider`. + + + + الحد الاقصى لنقاط الحفظ المحتفظ بها. الأقدم تحذف بعد كل كتابة. + + + + نقطة الحفظ المراد استعادتها عند تمريرها عبر `from_checkpoint`. + + +### قيم حقل `checkpoint` + +مقبولة في `Crew` و`Flow` و`Agent`. + + + يرث من الأب. + + + + تفعيل بالإعدادات الافتراضية. + + + + انسحاب صريح. يوقف الوراثة. + + + + إعدادات مخصصة. + + +### أنواع الأحداث + +يقبل `on_events` أي مجموعة من قيم `CheckpointEventType`. الافتراضي `["task_completed"]` يكتب نقطة حفظ لكل مهمة منتهية، و`["*"]` يطابق جميع الأحداث. + + +`["*"]` والأحداث عالية التردد مثل `llm_call_completed` تكتب نقاط حفظ كثيرة وقد تضر بالاداء. استخدمها مع `max_checkpoints`. + + + + +- **Task** — `task_started`, `task_completed`, `task_failed`, `task_evaluation` +- **Crew** — `crew_kickoff_started`, `crew_kickoff_completed`, `crew_kickoff_failed`, `crew_train_started`, `crew_train_completed`, `crew_train_failed`, `crew_test_started`, `crew_test_completed`, `crew_test_failed`, `crew_test_result` +- **Agent** — `agent_execution_started`, `agent_execution_completed`, `agent_execution_error`, `lite_agent_execution_started`, `lite_agent_execution_completed`, `lite_agent_execution_error`, `agent_evaluation_started`, `agent_evaluation_completed`, `agent_evaluation_failed` +- **Flow** — `flow_created`, `flow_started`, `flow_finished`, `flow_paused`, `method_execution_started`, `method_execution_finished`, `method_execution_failed`, `method_execution_paused`, `human_feedback_requested`, `human_feedback_received`, `flow_input_requested`, `flow_input_received` +- **LLM** — `llm_call_started`, `llm_call_completed`, `llm_call_failed`, `llm_stream_chunk`, `llm_thinking_chunk` +- **LLM Guardrail** — `llm_guardrail_started`, `llm_guardrail_completed`, `llm_guardrail_failed` +- **Tool** — `tool_usage_started`, `tool_usage_finished`, `tool_usage_error`, `tool_validate_input_error`, `tool_selection_error`, `tool_execution_error` +- **Memory** — `memory_save_started`, `memory_save_completed`, `memory_save_failed`, `memory_query_started`, `memory_query_completed`, `memory_query_failed`, `memory_retrieval_started`, `memory_retrieval_completed`, `memory_retrieval_failed` +- **Knowledge** — `knowledge_search_query_started`, `knowledge_search_query_completed`, `knowledge_query_started`, `knowledge_query_completed`, `knowledge_query_failed`, `knowledge_search_query_failed` +- **Reasoning** — `agent_reasoning_started`, `agent_reasoning_completed`, `agent_reasoning_failed` +- **MCP** — `mcp_connection_started`, `mcp_connection_completed`, `mcp_connection_failed`, `mcp_tool_execution_started`, `mcp_tool_execution_completed`, `mcp_tool_execution_failed`, `mcp_config_fetch_failed` +- **Observation** — `step_observation_started`, `step_observation_completed`, `step_observation_failed`, `plan_refinement`, `plan_replan_triggered`, `goal_achieved_early` +- **Skill** — `skill_discovery_started`, `skill_discovery_completed`, `skill_loaded`, `skill_activated`, `skill_load_failed` +- **Logging** — `agent_logs_started`, `agent_logs_execution` +- **A2A** — `a2a_delegation_started`, `a2a_delegation_completed`, `a2a_conversation_started`, `a2a_conversation_completed`, `a2a_message_sent`, `a2a_response_received`, `a2a_polling_started`, `a2a_polling_status`, `a2a_push_notification_registered`, `a2a_push_notification_received`, `a2a_push_notification_sent`, `a2a_push_notification_timeout`, `a2a_streaming_started`, `a2a_streaming_chunk`, `a2a_agent_card_fetched`, `a2a_authentication_failed`, `a2a_artifact_received`, `a2a_connection_error`, `a2a_server_task_started`, `a2a_server_task_completed`, `a2a_server_task_canceled`, `a2a_server_task_failed`, `a2a_parallel_delegation_started`, `a2a_parallel_delegation_completed`, `a2a_transport_negotiated`, `a2a_content_type_negotiated`, `a2a_context_created`, `a2a_context_expired`, `a2a_context_idle`, `a2a_context_completed`, `a2a_context_pruned` +- **إشارات النظام** — `SIGTERM`, `SIGINT`, `SIGHUP`, `SIGTSTP`, `SIGCONT` +- **حرف بدل** — `"*"` يطابق جميع الأحداث. + + + +### مزودات التخزين + + + ملف واحد لكل نقطة حفظ بصيغة `_.json` داخل `location`. + + + + ملف قاعدة بيانات واحد في `location` مع journaling WAL. + + +### سطر الأوامر + +| الامر | الغرض | +|:------|:------| +| `crewai checkpoint` | تشغيل TUI؛ كشف التخزين تلقائيا. | +| `crewai checkpoint --location ` | تشغيل TUI على موقع محدد. | +| `crewai checkpoint list ` | سرد نقاط الحفظ. | +| `crewai checkpoint info ` | تفقد ملف نقطة حفظ أو آخر مدخل في قاعدة بيانات SQLite. | diff --git a/docs/v1.15.13/ar/concepts/cli.mdx b/docs/v1.15.13/ar/concepts/cli.mdx new file mode 100644 index 0000000000..e89829eb9d --- /dev/null +++ b/docs/v1.15.13/ar/concepts/cli.mdx @@ -0,0 +1,302 @@ +--- +title: واجهة سطر الأوامر +description: تعرّف على كيفية استخدام واجهة سطر أوامر CrewAI للتفاعل مع CrewAI. +icon: terminal +mode: "wide" +--- + + + منذ الإصدار 0.140.0، بدأ CrewAI AMP عملية نقل مزود تسجيل الدخول. + لذلك، تم تحديث تدفق المصادقة عبر CLI. المستخدمون الذين يسجلون الدخول + باستخدام Google، أو الذين أنشأوا حساباتهم بعد 3 يوليو 2025 لن يتمكنوا + من تسجيل الدخول مع الإصدارات القديمة من مكتبة `crewai`. + + +## نظرة عامة + +توفر واجهة سطر أوامر CrewAI مجموعة من الأوامر للتفاعل مع CrewAI، مما يتيح لك إنشاء وتدريب وتشغيل وإدارة الأطقم والتدفقات. + +## التثبيت + +لاستخدام واجهة سطر أوامر CrewAI، تأكد من تثبيت CrewAI: + +```shell Terminal +pip install crewai +``` + +## الاستخدام الأساسي + +الهيكل الأساسي لأمر CrewAI CLI هو: + +```shell Terminal +crewai [COMMAND] [OPTIONS] [ARGUMENTS] +``` + +## الأوامر المتاحة + +### 1. إنشاء + +إنشاء طاقم أو تدفق جديد. + +```shell Terminal +crewai create [OPTIONS] TYPE NAME +``` + +- `TYPE`: اختر بين "crew" أو "flow" +- `NAME`: اسم الطاقم أو التدفق + +مثال: + +```shell Terminal +crewai create crew my_new_crew +crewai create flow my_new_flow +``` + +افتراضيًا، ينشئ `crewai create crew` مشروعًا JSON-first يحتوي على `crew.jsonc` و `agents/*.jsonc`. استخدم `crewai create crew my_new_crew --classic` فقط إذا أردت البنية القديمة Python/YAML مع `crew.py` و `config/agents.yaml` و `config/tasks.yaml`. + +### 2. الإصدار + +عرض الإصدار المثبت من CrewAI. + +```shell Terminal +crewai version [OPTIONS] +``` + +- `--tools`: (اختياري) عرض الإصدار المثبت من أدوات CrewAI + +### 3. التدريب + +تدريب الطاقم لعدد محدد من التكرارات. + +```shell Terminal +crewai train [OPTIONS] +``` + +- `-n, --n_iterations INTEGER`: عدد تكرارات التدريب (افتراضي: 5) +- `-f, --filename TEXT`: مسار ملف مخصص للتدريب (افتراضي: "trained_agents_data.pkl") + +### 4. الإعادة + +إعادة تنفيذ الطاقم من مهمة محددة. + +```shell Terminal +crewai replay [OPTIONS] +``` + +- `-t, --task_id TEXT`: إعادة تنفيذ الطاقم من معرّف المهمة هذا، بما في ذلك جميع المهام اللاحقة + +### 5. سجل مخرجات المهام + +استرجاع أحدث مخرجات مهام crew.kickoff(). + +```shell Terminal +crewai log-tasks-outputs +``` + +### 6. إعادة تعيين الذاكرة + +إعادة تعيين ذاكرة الطاقم (طويلة، قصيرة، الكيانات، أحدث مخرجات التشغيل). + +```shell Terminal +crewai reset-memories [OPTIONS] +``` + +- `-l, --long`: إعادة تعيين الذاكرة طويلة المدى +- `-s, --short`: إعادة تعيين الذاكرة قصيرة المدى +- `-e, --entities`: إعادة تعيين ذاكرة الكيانات +- `-k, --kickoff-outputs`: إعادة تعيين أحدث مخرجات التشغيل +- `-kn, --knowledge`: إعادة تعيين تخزين المعرفة +- `-akn, --agent-knowledge`: إعادة تعيين تخزين معرفة الوكيل +- `-a, --all`: إعادة تعيين جميع الذاكرات + +### 7. الاختبار + +اختبار الطاقم وتقييم النتائج. + +```shell Terminal +crewai test [OPTIONS] +``` + +- `-n, --n_iterations INTEGER`: عدد تكرارات الاختبار (افتراضي: 3) +- `-m, --model TEXT`: نموذج LLM لتشغيل الاختبارات (افتراضي: "gpt-4o-mini") + +### 8. التشغيل + +تشغيل الطاقم أو التدفق. + +```shell Terminal +crewai run +``` + + + بدءًا من الإصدار 0.103.0، يمكن استخدام أمر `crewai run` لتشغيل + كل من الأطقم القياسية والتدفقات. للتدفقات، يكتشف تلقائيًا النوع + من pyproject.toml ويشغّل الأمر المناسب. هذه هي الطريقة الموصى بها + لتشغيل كل من الأطقم والتدفقات. + + +### 9. الدردشة + +بدءًا من الإصدار `0.98.0`، عند تشغيل أمر `crewai chat`، تبدأ جلسة تفاعلية مع طاقمك. سيرشدك المساعد الذكي بطلب المدخلات اللازمة لتنفيذ الطاقم. بمجرد توفير جميع المدخلات، سينفذ الطاقم مهامه. + +```shell Terminal +crewai chat +``` + + +مهم: عيّن خاصية `chat_llm` في تعريف الـ crew لتفعيل هذا الأمر. + +للـ crews بنمط JSON-first، أضفها إلى `crew.jsonc`: + +```jsonc +{ + "name": "My Crew", + "agents": ["researcher"], + "tasks": [], + "chat_llm": "openai/gpt-4o" +} +``` + +للـ crews الكلاسيكية Python/YAML، عيّنها في `crew.py`: + +```python +@crew +def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True, + chat_llm="gpt-4o", + ) +``` + + +### 10. النشر + +نشر الطاقم أو التدفق إلى [CrewAI AMP](https://app.crewai.com). + +- **المصادقة**: تحتاج لتكون مصادقًا للنشر إلى CrewAI AMP. + + ```shell Terminal + crewai login + ``` + +- **إنشاء نشر**: + ```shell Terminal + crewai deploy create + ``` + +- **نشر الطاقم**: + ```shell Terminal + crewai deploy push + ``` + +- **حالة النشر**: + ```shell Terminal + crewai deploy status + ``` + +- **سجلات النشر**: + ```shell Terminal + crewai deploy logs + ``` + +- **عرض النشرات**: + ```shell Terminal + crewai deploy list + ``` + +- **حذف النشر**: + ```shell Terminal + crewai deploy remove + ``` + +### 11. إدارة المؤسسة + +إدارة مؤسسات CrewAI AMP. + +```shell Terminal +crewai org [COMMAND] [OPTIONS] +``` + +- `list`: عرض جميع المؤسسات +- `current`: عرض المؤسسة النشطة حاليًا +- `switch`: التبديل إلى مؤسسة محددة + +### 12. تسجيل الدخول + +المصادقة مع CrewAI AMP باستخدام تدفق رمز الجهاز الآمن. + +```shell Terminal +crewai login +``` + +### 13. إدارة التهيئة + +إدارة إعدادات تهيئة CLI لـ CrewAI. + +```shell Terminal +crewai config [COMMAND] [OPTIONS] +``` + +- `list`: عرض جميع معاملات التهيئة +- `set`: تعيين معامل تهيئة +- `reset`: إعادة تعيين جميع المعاملات إلى القيم الافتراضية + +### 14. إدارة التتبع + +إدارة تفضيلات جمع التتبع لعمليات الطاقم والتدفق. + +```shell Terminal +crewai traces [COMMAND] +``` + +- `enable`: تفعيل جمع التتبع +- `disable`: تعطيل جمع التتبع +- `status`: عرض حالة جمع التتبع الحالية + +#### كيف يعمل التتبع + +يتم التحكم في جمع التتبع بفحص ثلاثة إعدادات بترتيب الأولوية: + +1. **علامة صريحة في الكود** (الأولوية الأعلى): + ```python + crew = Crew(agents=[...], tasks=[...], tracing=True) # تفعيل دائمًا + crew = Crew(agents=[...], tasks=[...], tracing=False) # تعطيل دائمًا + crew = Crew(agents=[...], tasks=[...]) # فحص الأولويات الأدنى + ``` + +2. **متغير البيئة** (الأولوية الثانية): + ```env + CREWAI_TRACING_ENABLED=true + ``` + +3. **تفضيل المستخدم** (الأولوية الأدنى): + ```shell Terminal + crewai traces enable + ``` + + +**لتفعيل التتبع**، استخدم أيًا من هذه الطرق: +- عيّن `tracing=True` في كود الطاقم/التدفق، أو +- أضف `CREWAI_TRACING_ENABLED=true` إلى ملف `.env`، أو +- شغّل `crewai traces enable` + +**لتعطيل التتبع**، استخدم أيًا من هذه الطرق: +- عيّن `tracing=False` في كود الطاقم/التدفق، أو +- أزل أو عيّن `false` لمتغير `CREWAI_TRACING_ENABLED`، أو +- شغّل `crewai traces disable` + + + + يتعامل CrewAI CLI مع المصادقة لمستودع الأدوات تلقائيًا عند + إضافة حزم إلى مشروعك. فقط أضف `crewai` قبل أي أمر `uv` + لاستخدامه. مثلًا `crewai uv add requests`. + + + + تُخزن إعدادات التهيئة في `~/.config/crewai/settings.json`. بعض + الإعدادات مثل اسم المؤسسة ومعرّفها للقراءة فقط وتُدار من خلال + أوامر المصادقة والمؤسسة. + diff --git a/docs/v1.15.13/ar/concepts/collaboration.mdx b/docs/v1.15.13/ar/concepts/collaboration.mdx new file mode 100644 index 0000000000..a0cae91393 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/collaboration.mdx @@ -0,0 +1,363 @@ +--- +title: التعاون +description: كيفية تمكين الوكلاء من العمل معًا وتفويض المهام والتواصل بفعالية داخل فرق CrewAI. +icon: screen-users +mode: "wide" +--- + +## نظرة عامة + +يُمكّن التعاون في CrewAI الوكلاء من العمل معًا كفريق عن طريق تفويض المهام وطرح الأسئلة للاستفادة من خبرات بعضهم البعض. عندما يكون `allow_delegation=True`، يحصل الوكلاء تلقائيًا على أدوات تعاون قوية. + +## البدء السريع: تفعيل التعاون + +```python +from crewai import Agent, Crew, Task + +# تفعيل التعاون للوكلاء +researcher = Agent( + role="Research Specialist", + goal="Conduct thorough research on any topic", + backstory="Expert researcher with access to various sources", + allow_delegation=True, # الإعداد الرئيسي للتعاون + verbose=True +) + +writer = Agent( + role="Content Writer", + goal="Create engaging content based on research", + backstory="Skilled writer who transforms research into compelling content", + allow_delegation=True, # يُمكّن طرح الأسئلة على الوكلاء الآخرين + verbose=True +) + +# يمكن للوكلاء الآن التعاون تلقائيًا +crew = Crew( + agents=[researcher, writer], + tasks=[...], + verbose=True +) +``` + +## كيف يعمل تعاون الوكلاء + +عندما يكون `allow_delegation=True`، يوفر CrewAI تلقائيًا للوكلاء أداتين قويتين: + +### 1. **أداة تفويض العمل** +تسمح للوكلاء بتعيين مهام لزملاء الفريق ذوي الخبرة المحددة. + +```python +# يحصل الوكيل تلقائيًا على هذه الأداة: +# Delegate work to coworker(task: str, context: str, coworker: str) +``` + +### 2. **أداة طرح الأسئلة** +تُمكّن الوكلاء من طرح أسئلة محددة لجمع المعلومات من الزملاء. + +```python +# يحصل الوكيل تلقائيًا على هذه الأداة: +# Ask question to coworker(question: str, context: str, coworker: str) +``` + +## التعاون في الممارسة + +إليك مثالًا كاملًا يوضح تعاون الوكلاء في مهمة إنشاء المحتوى: + +```python +from crewai import Agent, Crew, Task, Process + +# إنشاء وكلاء تعاونيين +researcher = Agent( + role="Research Specialist", + goal="Find accurate, up-to-date information on any topic", + backstory="""You're a meticulous researcher with expertise in finding + reliable sources and fact-checking information across various domains.""", + allow_delegation=True, + verbose=True +) + +writer = Agent( + role="Content Writer", + goal="Create engaging, well-structured content", + backstory="""You're a skilled content writer who excels at transforming + research into compelling, readable content for different audiences.""", + allow_delegation=True, + verbose=True +) + +editor = Agent( + role="Content Editor", + goal="Ensure content quality and consistency", + backstory="""You're an experienced editor with an eye for detail, + ensuring content meets high standards for clarity and accuracy.""", + allow_delegation=True, + verbose=True +) + +# إنشاء مهمة تشجع التعاون +article_task = Task( + description="""Write a comprehensive 1000-word article about 'The Future of AI in Healthcare'. + + The article should include: + - Current AI applications in healthcare + - Emerging trends and technologies + - Potential challenges and ethical considerations + - Expert predictions for the next 5 years + + Collaborate with your teammates to ensure accuracy and quality.""", + expected_output="A well-researched, engaging 1000-word article with proper structure and citations", + agent=writer # الكاتب يقود، لكن يمكنه تفويض البحث إلى الباحث +) + +# إنشاء طاقم تعاوني +crew = Crew( + agents=[researcher, writer, editor], + tasks=[article_task], + process=Process.sequential, + verbose=True +) + +result = crew.kickoff() +``` + +## أنماط التعاون + +### النمط 1: بحث ← كتابة ← تحرير +```python +research_task = Task( + description="Research the latest developments in quantum computing", + expected_output="Comprehensive research summary with key findings and sources", + agent=researcher +) + +writing_task = Task( + description="Write an article based on the research findings", + expected_output="Engaging 800-word article about quantum computing", + agent=writer, + context=[research_task] # يحصل على مخرجات البحث كسياق +) + +editing_task = Task( + description="Edit and polish the article for publication", + expected_output="Publication-ready article with improved clarity and flow", + agent=editor, + context=[writing_task] # يحصل على مسودة المقال كسياق +) +``` + +### النمط 2: مهمة واحدة تعاونية +```python +collaborative_task = Task( + description="""Create a marketing strategy for a new AI product. + + Writer: Focus on messaging and content strategy + Researcher: Provide market analysis and competitor insights + + Work together to create a comprehensive strategy.""", + expected_output="Complete marketing strategy with research backing", + agent=writer # الوكيل القائد، لكن يمكنه التفويض إلى الباحث +) +``` + +## التعاون الهرمي + +للمشاريع المعقدة، استخدم عملية هرمية مع وكيل مدير: + +```python +from crewai import Agent, Crew, Task, Process + +# وكيل المدير ينسق الفريق +manager = Agent( + role="Project Manager", + goal="Coordinate team efforts and ensure project success", + backstory="Experienced project manager skilled at delegation and quality control", + allow_delegation=True, + verbose=True +) + +# وكلاء متخصصون +researcher = Agent( + role="Researcher", + goal="Provide accurate research and analysis", + backstory="Expert researcher with deep analytical skills", + allow_delegation=False, # المتخصصون يركزون على خبرتهم + verbose=True +) + +writer = Agent( + role="Writer", + goal="Create compelling content", + backstory="Skilled writer who creates engaging content", + allow_delegation=False, + verbose=True +) + +# مهمة يقودها المدير +project_task = Task( + description="Create a comprehensive market analysis report with recommendations", + expected_output="Executive summary, detailed analysis, and strategic recommendations", + agent=manager # المدير سيفوّض إلى المتخصصين +) + +# طاقم هرمي +crew = Crew( + agents=[manager, researcher, writer], + tasks=[project_task], + process=Process.hierarchical, # المدير ينسق كل شيء + manager_llm="gpt-4o", # تحديد LLM للمدير + verbose=True +) +``` + +## أفضل ممارسات التعاون + +### 1. **تحديد الأدوار بوضوح** +```python +# جيد: أدوار محددة ومتكاملة +researcher = Agent(role="Market Research Analyst", ...) +writer = Agent(role="Technical Content Writer", ...) + +# تجنب: أدوار متداخلة أو غامضة +agent1 = Agent(role="General Assistant", ...) +agent2 = Agent(role="Helper", ...) +``` + +### 2. **تفعيل التفويض الاستراتيجي** +```python +# فعّل التفويض للمنسقين والعامين +lead_agent = Agent( + role="Content Lead", + allow_delegation=True, # يمكنه التفويض إلى المتخصصين + ... +) + +# عطّل للمتخصصين المركّزين (اختياري) +specialist_agent = Agent( + role="Data Analyst", + allow_delegation=False, # يركز على الخبرة الأساسية + ... +) +``` + +### 3. **مشاركة السياق** +```python +# استخدم معامل context لاعتماديات المهام +writing_task = Task( + description="Write article based on research", + agent=writer, + context=[research_task], # يشارك نتائج البحث + ... +) +``` + +### 4. **أوصاف المهام الواضحة** +```python +# أوصاف محددة وقابلة للتنفيذ +Task( + description="""Research competitors in the AI chatbot space. + Focus on: pricing models, key features, target markets. + Provide data in a structured format.""", + ... +) + +# تجنب: أوصاف غامضة لا توجه التعاون +Task(description="Do some research about chatbots", ...) +``` + +## استكشاف أخطاء التعاون وإصلاحها + +### المشكلة: الوكلاء لا يتعاونون +**الأعراض:** يعمل الوكلاء بمعزل، لا يحدث تفويض +```python +# الحل: تأكد من تفعيل التفويض +agent = Agent( + role="...", + allow_delegation=True, # هذا مطلوب! + ... +) +``` + +### المشكلة: كثرة الذهاب والإياب +**الأعراض:** يطرح الوكلاء أسئلة مفرطة، تقدم بطيء +```python +# الحل: وفّر سياقًا أفضل وأدوارًا محددة +Task( + description="""Write a technical blog post about machine learning. + + Context: Target audience is software developers with basic ML knowledge. + Length: 1200 words + Include: code examples, practical applications, best practices + + If you need specific technical details, delegate research to the researcher.""", + ... +) +``` + +### المشكلة: حلقات التفويض +**الأعراض:** يفوّض الوكلاء ذهابًا وإيابًا بلا نهاية +```python +# الحل: تسلسل هرمي واضح ومسؤوليات +manager = Agent(role="Manager", allow_delegation=True) +specialist1 = Agent(role="Specialist A", allow_delegation=False) # لا إعادة تفويض +specialist2 = Agent(role="Specialist B", allow_delegation=False) +``` + +## ميزات التعاون المتقدمة + +### قواعد التعاون المخصصة +```python +# تعيين إرشادات تعاون محددة في خلفية الوكيل +agent = Agent( + role="Senior Developer", + backstory="""You lead development projects and coordinate with team members. + + Collaboration guidelines: + - Delegate research tasks to the Research Analyst + - Ask the Designer for UI/UX guidance + - Consult the QA Engineer for testing strategies + - Only escalate blocking issues to the Project Manager""", + allow_delegation=True +) +``` + +### مراقبة التعاون +```python +def track_collaboration(output): + """تتبع أنماط التعاون""" + if "Delegate work to coworker" in output.raw: + print("Delegation occurred") + if "Ask question to coworker" in output.raw: + print("Question asked") + +crew = Crew( + agents=[...], + tasks=[...], + step_callback=track_collaboration, # مراقبة التعاون + verbose=True +) +``` + +## الذاكرة والتعلم + +تمكين الوكلاء من تذكر التعاونات السابقة: + +```python +agent = Agent( + role="Content Lead", + memory=True, # يتذكر التفاعلات السابقة + allow_delegation=True, + verbose=True +) +``` + +مع تفعيل الذاكرة، يتعلم الوكلاء من التعاونات السابقة ويحسّنون قرارات التفويض بمرور الوقت. + +## الخطوات التالية + +- **جرّب الأمثلة**: ابدأ بمثال التعاون الأساسي +- **جرّب أدوارًا مختلفة**: اختبر تركيبات أدوار وكلاء مختلفة +- **راقب التفاعلات**: استخدم `verbose=True` لرؤية التعاون في العمل +- **حسّن أوصاف المهام**: المهام الواضحة تؤدي إلى تعاون أفضل +- **وسّع النطاق**: جرّب العمليات الهرمية للمشاريع المعقدة + +يحوّل التعاون وكلاء الذكاء الاصطناعي الفرديين إلى فرق قوية يمكنها معالجة التحديات المعقدة ومتعددة الأوجه معًا. diff --git a/docs/v1.15.13/ar/concepts/crews.mdx b/docs/v1.15.13/ar/concepts/crews.mdx new file mode 100644 index 0000000000..178129690f --- /dev/null +++ b/docs/v1.15.13/ar/concepts/crews.mdx @@ -0,0 +1,247 @@ +--- +title: الأطقم +description: فهم واستخدام الأطقم في إطار عمل CrewAI مع خصائص ووظائف شاملة. +icon: people-group +mode: "wide" +--- + +## نظرة عامة + +يمثل الطاقم في CrewAI مجموعة تعاونية من الوكلاء يعملون معًا لتحقيق مجموعة من المهام. يحدد كل طاقم استراتيجية تنفيذ المهام وتعاون الوكلاء وسير العمل العام. + +## خصائص الطاقم + +| الخاصية | المعامل | الوصف | +| :------------------------------------ | :--------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **المهام** | `tasks` | قائمة المهام المعيّنة للطاقم. | +| **الوكلاء** | `agents` | قائمة الوكلاء الذين يشكلون جزءًا من الطاقم. | +| **العملية** _(اختياري)_ | `process` | تدفق العملية (مثل تسلسلي، هرمي) الذي يتبعه الطاقم. الافتراضي `sequential`. | +| **الوضع المفصل** _(اختياري)_ | `verbose` | مستوى التفصيل في التسجيل أثناء التنفيذ. الافتراضي `False`. | +| **LLM المدير** _(اختياري)_ | `manager_llm` | نموذج اللغة المستخدم بواسطة وكيل المدير في العملية الهرمية. **مطلوب عند استخدام العملية الهرمية.** | +| **LLM استدعاء الدوال** _(اختياري)_ | `function_calling_llm` | إذا مُرر، سيستخدم الطاقم هذا LLM لاستدعاء دوال الأدوات لجميع الوكلاء. يمكن لكل وكيل أن يكون له LLM خاص يتجاوز LLM الطاقم. | +| **التهيئة** _(اختياري)_ | `config` | إعدادات تهيئة اختيارية للطاقم، بتنسيق `Json` أو `Dict[str, Any]`. | +| **الحد الأقصى لـ RPM** _(اختياري)_ | `max_rpm` | الحد الأقصى للطلبات في الدقيقة. الافتراضي `None`. | +| **الذاكرة** _(اختياري)_ | `memory` | تُستخدم لتخزين ذاكرات التنفيذ (قصيرة المدى، طويلة المدى، ذاكرة الكيانات). | +| **التخزين المؤقت** _(اختياري)_ | `cache` | يحدد ما إذا كان يُستخدم تخزين مؤقت لنتائج تنفيذ الأدوات. الافتراضي `True`. | +| **المُضمّن** _(اختياري)_ | `embedder` | تهيئة المُضمّن المستخدم من قبل الطاقم. الافتراضي `{"provider": "openai"}`. | +| **دالة الخطوة** _(اختياري)_ | `step_callback` | دالة تُستدعى بعد كل خطوة لكل وكيل. | +| **دالة المهمة** _(اختياري)_ | `task_callback` | دالة تُستدعى بعد اكتمال كل مهمة. | +| **مشاركة الطاقم** _(اختياري)_ | `share_crew` | ما إذا كنت تريد مشاركة معلومات الطاقم الكاملة وتنفيذه مع فريق CrewAI. | +| **ملف سجل المخرجات** _(اختياري)_ | `output_log_file` | عيّن True لحفظ السجلات كـ logs.txt أو وفّر مسار ملف. الافتراضي `None`. | +| **وكيل المدير** _(اختياري)_ | `manager_agent` | يعيّن وكيلًا مخصصًا سيُستخدم كمدير. | +| **التخطيط** *(اختياري)* | `planning` | يضيف قدرة التخطيط للطاقم. | +| **LLM التخطيط** *(اختياري)* | `planning_llm` | نموذج اللغة المستخدم بواسطة AgentPlanner في عملية التخطيط. | +| **مصادر المعرفة** _(اختياري)_ | `knowledge_sources` | مصادر المعرفة المتاحة على مستوى الطاقم، يمكن لجميع الوكلاء الوصول إليها. | +| **البث** _(اختياري)_ | `stream` | تفعيل مخرجات البث لتلقي تحديثات في الوقت الفعلي. الافتراضي `False`. | + + +**الحد الأقصى لـ RPM للطاقم**: تعيّن خاصية `max_rpm` الحد الأقصى للطلبات في الدقيقة التي يمكن للطاقم تنفيذها لتجنب حدود المعدل وستتجاوز إعدادات `max_rpm` الفردية للوكلاء إذا عيّنتها. + + +## إنشاء الأطقم + +هناك طريقتان رئيسيتان لإنشاء الأطقم في CrewAI: باستخدام **تهيئة JSONC (الموصى بها للـ crews الجديدة)** أو تعريفها **مباشرة في الكود** للمشاريع الكلاسيكية والحالات المتقدمة. + +### تهيئة JSONC (موصى بها) + +المشاريع الجديدة التي تُنشأ عبر `crewai create crew ` تستخدم `crew.jsonc` لإعدادات الـ crew والمهام، وملفًا منفصلًا لكل Agent داخل `agents/`. يكتشف `crewai run` ملف `crew.jsonc` أو `crew.json`، ويحمّل الـ Agents المشار إليها، ويطلب قيم placeholders الناقصة، ثم يبدأ الـ crew. + +```jsonc crew.jsonc +{ + "name": "Market Research Crew", + "agents": ["researcher", "analyst"], + "tasks": [ + { + "name": "research", + "description": "Research {topic} and collect the most relevant facts.", + "expected_output": "Structured research notes about {topic}.", + "agent": "researcher" + }, + { + "name": "analysis", + "description": "Analyze the research and write a concise report.", + "expected_output": "A markdown report with findings and recommendations.", + "agent": "analyst", + "context": ["research"], + "output_file": "output/report.md" + } + ], + "process": "sequential", + "verbose": true, + "memory": true, + "inputs": { + "topic": "AI Agents" + } +} +``` + +كل عنصر في `agents` يُحل أولًا إلى `agents/.jsonc` ثم إلى `agents/.json`. للـ crews الهرمية، استخدم `"process": "hierarchical"` مع `manager_llm` أو `manager_agent`. + + +شغّل مشاريع JSON crew من مصادر تثق بها فقط. أدوات `custom:` ومراجع `{"python": "module.attribute"}` تنفذ كود Python محليًا عند تحميل الـ crew. + + +### تهيئة YAML الكلاسيكية + +المشاريع الكلاسيكية التي تُنشأ عبر `crewai create crew --classic` تستخدم `crew.py` و `config/agents.yaml` و `config/tasks.yaml` والمزيّنات `@CrewBase` و `@agent` و `@task` و `@crew`. + +تظل هذه الطريقة مدعومة للمشاريع الحالية المبنية بـ Python/YAML وللفِرق التي تحتاج تحكمًا صريحًا عبر decorators. + +```python code +from crewai import Agent, Crew, Task, Process +from crewai.project import CrewBase, agent, task, crew, before_kickoff, after_kickoff +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List + +@CrewBase +class YourCrewName: + """Description of your crew""" + + agents: List[BaseAgent] + tasks: List[Task] + + agents_config = 'config/agents.yaml' + tasks_config = 'config/tasks.yaml' + + @before_kickoff + def prepare_inputs(self, inputs): + inputs['additional_data'] = "Some extra information" + return inputs + + @after_kickoff + def process_output(self, output): + output.raw += "\nProcessed after kickoff." + return output + + @agent + def agent_one(self) -> Agent: + return Agent( + config=self.agents_config['agent_one'], # type: ignore[index] + verbose=True + ) + + @task + def task_one(self) -> Task: + return Task( + config=self.tasks_config['task_one'] # type: ignore[index] + ) + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True, + ) +``` + + +سيتم تنفيذ المهام بالترتيب الذي عُرّفت به. + + +فئة `CrewBase`، مع هذه المزيّنات، تؤتمت جمع الوكلاء والمهام، مما يقلل الحاجة للإدارة اليدوية. + +### تعريف مباشر في الكود (بديل) + +بدلاً من ذلك، يمكنك تعريف الطاقم مباشرة في الكود بدون ملفات تهيئة YAML. + +## مخرجات الطاقم + +تُغلّف مخرجات الطاقم في فئة `CrewOutput`. توفر هذه الفئة طريقة منظمة للوصول إلى نتائج تنفيذ الطاقم، بما في ذلك تنسيقات متنوعة مثل السلاسل النصية الخام وJSON ونماذج Pydantic. + +### خصائص مخرجات الطاقم + +| الخاصية | المعامل | النوع | الوصف | +| :--------------- | :------------- | :------------------------- | :--------------------------------------------------------------------------------------------------- | +| **Raw** | `raw` | `str` | المخرجات الخام للطاقم. هذا هو التنسيق الافتراضي. | +| **Pydantic** | `pydantic` | `Optional[BaseModel]` | كائن نموذج Pydantic يمثل المخرجات المنظمة. | +| **JSON Dict** | `json_dict` | `Optional[Dict[str, Any]]` | قاموس يمثل مخرجات JSON. | +| **Tasks Output** | `tasks_output` | `List[TaskOutput]` | قائمة كائنات `TaskOutput`، كل منها يمثل مخرجات مهمة. | +| **Token Usage** | `token_usage` | `Dict[str, Any]` | ملخص استخدام الرموز. | + +## استخدام الذاكرة + +يمكن للأطقم استخدام الذاكرة (قصيرة المدى، طويلة المدى، وذاكرة الكيانات) لتحسين تنفيذها وتعلمها بمرور الوقت. + +## استخدام التخزين المؤقت + +يمكن استخدام التخزين المؤقت لتخزين نتائج تنفيذ الأدوات، مما يجعل العملية أكثر كفاءة. + +## مقاييس استخدام الطاقم + +بعد تنفيذ الطاقم، يمكنك الوصول إلى خاصية `usage_metrics` لعرض مقاييس استخدام نموذج اللغة (LLM) لجميع المهام المنفذة. + +`total_tokens` هو الإجمالي المفوتر (`prompt_tokens + completion_tokens`). حقول التفصيل مثل `cached_prompt_tokens` و`cache_creation_tokens` تصف أجزاءً مُدرجة بالفعل ضمن تلك الإجماليات ولا تُضاف مرة أخرى إلى `total_tokens`. راجع قسم **UsageMetrics field semantics** في توثيق مفهوم Flows للحصول على العقد الكامل. + +```python Code +crew = Crew(agents=[agent1, agent2], tasks=[task1, task2]) +crew.kickoff() +print(crew.usage_metrics) +``` + +## عملية تنفيذ الطاقم + +- **العملية التسلسلية**: تُنفذ المهام واحدة تلو الأخرى، مما يسمح بتدفق عمل خطي. +- **العملية الهرمية**: ينسق وكيل مدير الطاقم، ويفوّض المهام ويتحقق من النتائج. + +### تشغيل الطاقم + +بمجرد تجميع طاقمك، ابدأ سير العمل بطريقة `kickoff()`. + +```python Code +result = my_crew.kickoff() +print(result) +``` + +### طرق مختلفة لتشغيل الطاقم + +#### الطرق المتزامنة + +- `kickoff()`: يبدأ عملية التنفيذ وفقًا لتدفق العملية المحدد. +- `kickoff_for_each()`: ينفذ المهام بالتتابع لكل مدخل. + +#### الطرق غير المتزامنة + +| الطريقة | النوع | الوصف | +|--------|------|-------------| +| `akickoff()` | غير متزامن أصلي | async/await أصلي عبر سلسلة التنفيذ بأكملها | +| `akickoff_for_each()` | غير متزامن أصلي | تنفيذ غير متزامن أصلي لكل مدخل في قائمة | +| `kickoff_async()` | مبني على الخيوط | يغلّف التنفيذ المتزامن في `asyncio.to_thread` | +| `kickoff_for_each_async()` | مبني على الخيوط | غير متزامن مبني على الخيوط لكل مدخل في قائمة | + + +لأحمال العمل عالية التزامن، يُوصى بـ `akickoff()` و `akickoff_for_each()` لأنها تستخدم async أصلي. + + +### بث تنفيذ الطاقم + +للرؤية في الوقت الفعلي لتنفيذ الطاقم، يمكنك تفعيل البث: + +```python Code +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True +) + +streaming = crew.kickoff(inputs={"topic": "AI"}) +for chunk in streaming: + print(chunk.content, end="", flush=True) + +result = streaming.result +``` + +### الإعادة من مهمة محددة + +يمكنك الآن الإعادة من مهمة محددة باستخدام أمر CLI `replay`. + +```shell +crewai log-tasks-outputs +``` + +ثم للإعادة من مهمة محددة: + +```shell +crewai replay -t +``` diff --git a/docs/v1.15.13/ar/concepts/event-listener.mdx b/docs/v1.15.13/ar/concepts/event-listener.mdx new file mode 100644 index 0000000000..7fa6d671de --- /dev/null +++ b/docs/v1.15.13/ar/concepts/event-listener.mdx @@ -0,0 +1,237 @@ +--- +title: "مستمعو الأحداث" +description: "الاستفادة من أحداث CrewAI لبناء تكاملات مخصصة ومراقبة" +icon: spinner +mode: "wide" +--- + +## نظرة عامة + +يوفر CrewAI نظام أحداث قوي يتيح لك الاستماع والتفاعل مع الأحداث المختلفة التي تحدث أثناء تنفيذ طاقمك. تُمكّنك هذه الميزة من بناء تكاملات مخصصة وحلول مراقبة وأنظمة تسجيل أو أي وظائف أخرى تحتاج للتشغيل بناءً على أحداث CrewAI الداخلية. + +## كيف يعمل + +يستخدم CrewAI بنية ناقل أحداث لإرسال الأحداث طوال دورة حياة التنفيذ. يُبنى نظام الأحداث على المكونات التالية: + +1. **CrewAIEventsBus**: ناقل أحداث فريد يدير تسجيل الأحداث وإرسالها +2. **BaseEvent**: الفئة الأساسية لجميع الأحداث في النظام +3. **BaseEventListener**: فئة أساسية مجردة لإنشاء مستمعي أحداث مخصصين + +عندما تحدث إجراءات محددة في CrewAI (مثل بدء تنفيذ طاقم، أو إكمال وكيل لمهمة، أو استخدام أداة)، يرسل النظام أحداثًا مقابلة. يمكنك تسجيل معالجات لهذه الأحداث لتنفيذ كود مخصص عند حدوثها. + + +يوفر CrewAI AMP ميزة تتبع أوامر مدمجة تستفيد من نظام الأحداث لتتبع وتخزين وتصور جميع الأوامر والاستكمالات والبيانات الوصفية المرتبطة. + +![Prompt Tracing Dashboard](/images/enterprise/traces-overview.png) + +مع تتبع الأوامر يمكنك: + +- عرض السجل الكامل لجميع الأوامر المرسلة إلى LLM +- تتبع استخدام الرموز والتكاليف +- تصحيح إخفاقات استدلال الوكيل +- مشاركة تسلسلات الأوامر مع فريقك +- مقارنة استراتيجيات الأوامر المختلفة +- تصدير التتبعات للامتثال والتدقيق + + +## إنشاء مستمع أحداث مخصص + +لإنشاء مستمع أحداث مخصص، تحتاج إلى: + +1. إنشاء فئة ترث من `BaseEventListener` +2. تنفيذ طريقة `setup_listeners` +3. تسجيل معالجات للأحداث التي تهمك +4. إنشاء مثيل من مستمعك في الملف المناسب + +إليك مثالًا بسيطًا: + +```python +from crewai.events import ( + CrewKickoffStartedEvent, + CrewKickoffCompletedEvent, + AgentExecutionCompletedEvent, +) +from crewai.events import BaseEventListener + +class MyCustomListener(BaseEventListener): + def __init__(self): + super().__init__() + + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(CrewKickoffStartedEvent) + def on_crew_started(source, event): + print(f"Crew '{event.crew_name}' has started execution!") + + @crewai_event_bus.on(CrewKickoffCompletedEvent) + def on_crew_completed(source, event): + print(f"Crew '{event.crew_name}' has completed execution!") + print(f"Output: {event.output}") + + @crewai_event_bus.on(AgentExecutionCompletedEvent) + def on_agent_execution_completed(source, event): + print(f"Agent '{event.agent.role}' completed task") + print(f"Output: {event.output}") +``` + +## تسجيل المستمع بشكل صحيح + +مجرد تعريف فئة المستمع ليس كافيًا. تحتاج لإنشاء مثيل منه والتأكد من استيراده في تطبيقك. + +```python +# في ملف crew.py +from crewai import Agent, Crew, Task +from my_listeners import MyCustomListener + +# إنشاء مثيل من المستمع +my_listener = MyCustomListener() + +class MyCustomCrew: + def crew(self): + return Crew( + agents=[...], + tasks=[...], + ) +``` + +## أنواع الأحداث المتاحة + +يوفر CrewAI مجموعة واسعة من الأحداث يمكنك الاستماع إليها: + +### أحداث الطاقم + +- **CrewKickoffStartedEvent**: يُرسل عند بدء تنفيذ الطاقم +- **CrewKickoffCompletedEvent**: يُرسل عند اكتمال تنفيذ الطاقم +- **CrewKickoffFailedEvent**: يُرسل عند فشل تنفيذ الطاقم +- **CrewTestStartedEvent**: يُرسل عند بدء اختبار الطاقم +- **CrewTestCompletedEvent**: يُرسل عند اكتمال اختبار الطاقم +- **CrewTestFailedEvent**: يُرسل عند فشل اختبار الطاقم +- **CrewTrainStartedEvent**: يُرسل عند بدء تدريب الطاقم +- **CrewTrainCompletedEvent**: يُرسل عند اكتمال تدريب الطاقم +- **CrewTrainFailedEvent**: يُرسل عند فشل تدريب الطاقم + +### أحداث الوكيل + +- **AgentExecutionStartedEvent**: يُرسل عند بدء تنفيذ وكيل لمهمة +- **AgentExecutionCompletedEvent**: يُرسل عند اكتمال تنفيذ وكيل لمهمة +- **AgentExecutionErrorEvent**: يُرسل عند مواجهة وكيل لخطأ أثناء التنفيذ +- **LiteAgentExecutionStartedEvent**: يُرسل عند بدء تنفيذ LiteAgent +- **LiteAgentExecutionCompletedEvent**: يُرسل عند اكتمال تنفيذ LiteAgent + +### أحداث المهام + +- **TaskStartedEvent**: يُرسل عند بدء تنفيذ مهمة +- **TaskCompletedEvent**: يُرسل عند اكتمال تنفيذ مهمة +- **TaskFailedEvent**: يُرسل عند فشل تنفيذ مهمة + +### أحداث استخدام الأدوات + +- **ToolUsageStartedEvent**: يُرسل عند بدء تنفيذ أداة +- **ToolUsageFinishedEvent**: يُرسل عند اكتمال تنفيذ أداة +- **ToolUsageErrorEvent**: يُرسل عند مواجهة خطأ في تنفيذ أداة + +### أحداث MCP + +- **MCPConnectionStartedEvent**: يُرسل عند بدء الاتصال بخادم MCP +- **MCPConnectionCompletedEvent**: يُرسل عند اكتمال الاتصال بخادم MCP +- **MCPConnectionFailedEvent**: يُرسل عند فشل الاتصال بخادم MCP +- **MCPToolExecutionStartedEvent**: يُرسل عند بدء تنفيذ أداة MCP +- **MCPToolExecutionCompletedEvent**: يُرسل عند اكتمال تنفيذ أداة MCP +- **MCPToolExecutionFailedEvent**: يُرسل عند فشل تنفيذ أداة MCP + +### أحداث المعرفة + +- **KnowledgeRetrievalStartedEvent**: يُرسل عند بدء استرجاع المعرفة +- **KnowledgeRetrievalCompletedEvent**: يُرسل عند اكتمال استرجاع المعرفة +- **KnowledgeQueryStartedEvent**: يُرسل عند بدء استعلام المعرفة +- **KnowledgeQueryCompletedEvent**: يُرسل عند اكتمال استعلام المعرفة +- **KnowledgeQueryFailedEvent**: يُرسل عند فشل استعلام المعرفة + +### أحداث حواجز LLM + +- **LLMGuardrailStartedEvent**: يُرسل عند بدء التحقق من الحاجز +- **LLMGuardrailCompletedEvent**: يُرسل عند اكتمال التحقق من الحاجز +- **LLMGuardrailFailedEvent**: يُرسل عند فشل التحقق من الحاجز + +### أحداث التدفق + +- **FlowCreatedEvent**: يُرسل عند إنشاء تدفق +- **FlowStartedEvent**: يُرسل عند بدء تنفيذ تدفق +- **FlowFinishedEvent**: يُرسل عند اكتمال تنفيذ تدفق +- **FlowFailedEvent**: يُرسل عند فشل تنفيذ تدفق. يحتوي على اسم التدفق والاستثناء الذي أنهى التنفيذ. +- **FlowPausedEvent**: يُرسل عند إيقاف تدفق مؤقتًا بانتظار ملاحظات بشرية + +### أحداث LLM + +- **LLMCallStartedEvent**: يُرسل عند بدء استدعاء LLM +- **LLMCallCompletedEvent**: يُرسل عند اكتمال استدعاء LLM +- **LLMCallFailedEvent**: يُرسل عند فشل استدعاء LLM +- **LLMStreamChunkEvent**: يُرسل لكل جزء مستلم أثناء بث استجابات LLM + +### أحداث الذاكرة + +- **MemoryQueryStartedEvent**: يُرسل عند بدء استعلام الذاكرة +- **MemoryQueryCompletedEvent**: يُرسل عند اكتمال استعلام الذاكرة +- **MemorySaveStartedEvent**: يُرسل عند بدء حفظ الذاكرة +- **MemorySaveCompletedEvent**: يُرسل عند اكتمال حفظ الذاكرة + +### أحداث الاستدلال + +- **AgentReasoningStartedEvent**: يُرسل عند بدء وكيل الاستدلال حول مهمة +- **AgentReasoningCompletedEvent**: يُرسل عند انتهاء عملية الاستدلال +- **AgentReasoningFailedEvent**: يُرسل عند فشل عملية الاستدلال + +### أحداث A2A (وكيل إلى وكيل) + +- **A2ADelegationStartedEvent**: يُرسل عند بدء تفويض A2A +- **A2ADelegationCompletedEvent**: يُرسل عند اكتمال تفويض A2A +- **A2AConversationStartedEvent**: يُرسل عند بدء محادثة A2A متعددة الأدوار +- **A2AConversationCompletedEvent**: يُرسل عند انتهاء محادثة A2A + +## هيكل معالج الأحداث + +يستقبل كل معالج حدث معاملين: + +1. **source**: الكائن الذي أرسل الحدث +2. **event**: مثيل الحدث، يحتوي على بيانات خاصة بالحدث + +هيكل كائن الحدث يعتمد على نوع الحدث، لكن جميع الأحداث ترث من `BaseEvent` وتتضمن: + +- **timestamp**: الوقت الذي أُرسل فيه الحدث +- **type**: معرّف نصي لنوع الحدث + +## الاستخدام المتقدم: المعالجات المحددة النطاق + +لمعالجة الأحداث المؤقتة، يمكنك استخدام مدير سياق `scoped_handlers`: + +```python +from crewai.events import crewai_event_bus, CrewKickoffStartedEvent + +with crewai_event_bus.scoped_handlers(): + @crewai_event_bus.on(CrewKickoffStartedEvent) + def temp_handler(source, event): + print("This handler only exists within this context") + + # قم بشيء يرسل أحداثًا + +# خارج السياق، يتم إزالة المعالج المؤقت +``` + +## حالات الاستخدام + +يمكن استخدام مستمعي الأحداث لأغراض متنوعة: + +1. **التسجيل والمراقبة**: تتبع تنفيذ طاقمك وتسجيل الأحداث المهمة +2. **التحليلات**: جمع بيانات عن أداء وسلوك طاقمك +3. **التصحيح**: إعداد مستمعين مؤقتين لتصحيح مشاكل محددة +4. **التكامل**: ربط CrewAI بأنظمة خارجية مثل منصات المراقبة وقواعد البيانات أو خدمات الإشعارات +5. **السلوك المخصص**: تشغيل إجراءات مخصصة بناءً على أحداث محددة + +## أفضل الممارسات + +1. **اجعل المعالجات خفيفة**: يجب أن تكون معالجات الأحداث خفيفة وتتجنب العمليات الحاجبة +2. **معالجة الأخطاء**: أدرج معالجة أخطاء مناسبة في معالجات الأحداث لمنع الاستثناءات من التأثير على التنفيذ الرئيسي +3. **التنظيف**: إذا خصص مستمعك موارد، تأكد من تنظيفها بشكل صحيح +4. **الاستماع الانتقائي**: استمع فقط للأحداث التي تحتاج فعلاً لمعالجتها +5. **الاختبار**: اختبر مستمعي الأحداث بمعزل لضمان سلوكهم كما هو متوقع + +بالاستفادة من نظام أحداث CrewAI، يمكنك توسيع وظائفه ودمجه بسلاسة مع بنيتك التحتية الحالية. diff --git a/docs/v1.15.13/ar/concepts/files.mdx b/docs/v1.15.13/ar/concepts/files.mdx new file mode 100644 index 0000000000..66516a0931 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/files.mdx @@ -0,0 +1,267 @@ +--- +title: الملفات +description: تمرير الصور وملفات PDF والصوت والفيديو والنصوص إلى وكلائك للمعالجة متعددة الوسائط. +icon: file-image +--- + +## نظرة عامة + +يدعم CrewAI مدخلات الملفات متعددة الوسائط الأصلية، مما يتيح لك تمرير الصور وملفات PDF والصوت والفيديو والنصوص مباشرة إلى وكلائك. يتم تنسيق الملفات تلقائيًا وفقًا لمتطلبات API لكل مزود LLM. + + +يتطلب دعم الملفات حزمة `crewai-files` الاختيارية. ثبّتها بـ: + +```bash +uv add 'crewai[file-processing]' +``` + + + +واجهة معالجة الملفات حاليًا في مرحلة الوصول المبكر. + + +## أنواع الملفات + +يدعم CrewAI خمسة أنواع ملفات محددة بالإضافة إلى فئة `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) +``` + +## استخدام الملفات + +يمكن تمرير الملفات على مستويات متعددة، حيث تأخذ المستويات الأكثر تحديدًا الأولوية. + +### مع الأطقم + +مرر الملفات عند تشغيل طاقم: + +```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"), + } +) +``` + +### مع المهام + +أرفق الملفات بمهام محددة: + +```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"), + } +) +``` + +### مع التدفقات + +مرر الملفات إلى التدفقات، والتي تنتقل تلقائيًا إلى الأطقم: + +```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 +``` + +على سبيل المثال، إذا عرّف كل من التدفق والمهمة ملفًا باسم `"chart"`، تُستخدم نسخة المهمة. + +## دعم المزودين + +تدعم المزودات المختلفة أنواع ملفات مختلفة. يقوم CrewAI تلقائيًا بتنسيق الملفات وفقًا لواجهة كل مزود. + +| المزود | صورة | 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) | ✓ | | ✓ | | | + + +تدعم نماذج Google Gemini جميع أنواع الملفات بما في ذلك الفيديو (حتى ساعة واحدة، 2 جيجابايت). استخدم Gemini عندما تحتاج لمعالجة محتوى الفيديو. + + + +إذا مررت نوع ملف لا يدعمه المزود (مثل الفيديو إلى OpenAI)، ستتلقى خطأ `UnsupportedFileTypeError`. اختر مزودك بناءً على أنواع الملفات التي تحتاج لمعالجتها. + + +## كيف تُرسل الملفات + +يختار CrewAI تلقائيًا الطريقة المثلى لإرسال الملفات إلى كل مزود: + +| الطريقة | الوصف | متى تُستخدم | +|:-------|:------------|:----------| +| **Inline Base64** | الملف مضمّن مباشرة في الطلب | ملفات صغيرة (< 5 ميجابايت عادة) | +| **File Upload API** | الملف يُرفع بشكل منفصل، يُشار إليه بمعرّف | ملفات كبيرة تتجاوز العتبة | +| **URL Reference** | عنوان URL مباشر يُمرر إلى النموذج | مصدر الملف هو عنوان URL بالفعل | + +### طرق الإرسال حسب المزود + +| المزود | Inline Base64 | File Upload API | URL References | +|:---------|:-------------:|:---------------:|:--------------:| +| **OpenAI** | ✓ | ✓ (> 5 MB) | ✓ | +| **Anthropic** | ✓ | ✓ (> 5 MB) | ✓ | +| **Google Gemini** | ✓ | ✓ (> 20 MB) | ✓ | +| **AWS Bedrock** | ✓ | | ✓ (S3 URIs) | +| **Azure OpenAI** | ✓ | | ✓ | + + +لا تحتاج لإدارة هذا بنفسك. يستخدم CrewAI تلقائيًا الطريقة الأكثر كفاءة بناءً على حجم الملف وقدرات المزود. المزودات بدون واجهات رفع الملفات تستخدم inline base64 لجميع الملفات. + + +## أوضاع معالجة الملفات + +تحكم في كيفية معالجة الملفات عندما تتجاوز حدود المزود: + +```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 ميجابايت، حتى 10 صور لكل طلب +- **PDF**: حد أقصى 32 ميجابايت، حتى 100 صفحة +- **الصوت**: حد أقصى 25 ميجابايت، حتى 25 دقيقة + +### Anthropic +- **الصور**: حد أقصى 5 ميجابايت، أقصى 8000x8000 بكسل، حتى 100 صورة +- **PDF**: حد أقصى 32 ميجابايت، حتى 100 صفحة + +### Google Gemini +- **الصور**: حد أقصى 100 ميجابايت +- **PDF**: حد أقصى 50 ميجابايت +- **الصوت**: حد أقصى 100 ميجابايت، حتى 9.5 ساعة +- **الفيديو**: حد أقصى 2 جيجابايت، حتى ساعة واحدة + +### AWS Bedrock +- **الصور**: حد أقصى 4.5 ميجابايت، أقصى 8000x8000 بكسل +- **PDF**: حد أقصى 3.75 ميجابايت، حتى 100 صفحة + +## الإشارة إلى الملفات في الأوامر + +استخدم اسم مفتاح الملف في أوصاف المهام للإشارة إلى الملفات: + +```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"), + } +) +``` diff --git a/docs/v1.15.13/ar/concepts/flows.mdx b/docs/v1.15.13/ar/concepts/flows.mdx new file mode 100644 index 0000000000..45d54114d2 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/flows.mdx @@ -0,0 +1,1181 @@ +--- +title: التدفقات +description: تعلّم كيفية إنشاء وإدارة سير عمل الذكاء الاصطناعي باستخدام تدفقات CrewAI. +icon: arrow-progress +mode: "wide" +--- + +## نظرة عامة + +تدفقات CrewAI هي ميزة قوية مصممة لتبسيط إنشاء وإدارة سير عمل الذكاء الاصطناعي. تتيح التدفقات للمطورين دمج وتنسيق مهام البرمجة وفرق Crew بكفاءة، مما يوفر إطار عمل متين لبناء أتمتة ذكاء اصطناعي متطورة. + +تتيح لك التدفقات إنشاء سير عمل منظم يعتمد على الأحداث. فهي توفر طريقة سلسة لربط مهام متعددة وإدارة الحالة والتحكم في تدفق التنفيذ في تطبيقات الذكاء الاصطناعي الخاصة بك. باستخدام التدفقات، يمكنك بسهولة تصميم وتنفيذ عمليات متعددة الخطوات تستفيد من الإمكانيات الكاملة لـ CrewAI. + +1. **تبسيط إنشاء سير العمل**: ربط فرق Crew والمهام المتعددة بسهولة لإنشاء سير عمل ذكاء اصطناعي معقد. + +2. **إدارة الحالة**: تجعل التدفقات إدارة ومشاركة الحالة بين المهام المختلفة في سير العمل أمرًا سهلًا للغاية. + +3. **بنية تعتمد على الأحداث**: مبنية على نموذج يعتمد على الأحداث، مما يتيح سير عمل ديناميكي وسريع الاستجابة. + +4. **تحكم مرن في التدفق**: تنفيذ المنطق الشرطي والحلقات والتفرع ضمن سير العمل. + +## البدء + +لنقم بإنشاء تدفق بسيط حيث ستستخدم OpenAI لإنشاء مدينة عشوائية في مهمة واحدة ثم استخدام تلك المدينة لإنشاء حقيقة ممتعة في مهمة أخرى. + +```python Code + +from crewai.flow.flow import Flow, listen, start +from dotenv import load_dotenv +from litellm import completion + +load_dotenv() + +class ExampleFlow(Flow): + model = "gpt-4o-mini" + + @start() + def generate_city(self): + print("Starting flow") + # Each flow state automatically gets a unique ID + print(f"Flow State ID: {self.state['id']}") + + response = completion( + model=self.model, + messages=[ + { + "role": "user", + "content": "Return the name of a random city in the world.", + }, + ], + ) + + random_city = response["choices"][0]["message"]["content"] + # Store the city in our state + self.state["city"] = random_city + print(f"Random City: {random_city}") + + return random_city + + @listen(generate_city) + def generate_fun_fact(self, random_city): + response = completion( + model=self.model, + messages=[ + { + "role": "user", + "content": f"Tell me a fun fact about {random_city}", + }, + ], + ) + + fun_fact = response["choices"][0]["message"]["content"] + # Store the fun fact in our state + self.state["fun_fact"] = fun_fact + return fun_fact + + + +flow = ExampleFlow() +flow.plot() +result = flow.kickoff() + +print(f"Generated fun fact: {result}") +``` +![Flow Visual image](/images/crewai-flow-1.png) +في المثال أعلاه، أنشأنا تدفقًا بسيطًا يولّد مدينة عشوائية باستخدام OpenAI ثم يولّد حقيقة ممتعة عن تلك المدينة. يتكون التدفق من مهمتين: `generate_city` و `generate_fun_fact`. مهمة `generate_city` هي نقطة البداية للتدفق، ومهمة `generate_fun_fact` تستمع لمخرجات مهمة `generate_city`. + +يتلقى كل مثيل من التدفق تلقائيًا معرّفًا فريدًا (UUID) في حالته، مما يساعد في تتبع وإدارة عمليات تنفيذ التدفق. يمكن للحالة أيضًا تخزين بيانات إضافية (مثل المدينة المولّدة والحقيقة الممتعة) التي تستمر طوال تنفيذ التدفق. + +عند تشغيل التدفق، سيقوم بما يلي: +1. توليد معرّف فريد لحالة التدفق +2. توليد مدينة عشوائية وتخزينها في الحالة +3. توليد حقيقة ممتعة عن تلك المدينة وتخزينها في الحالة +4. طباعة النتائج في وحدة التحكم + +يمكن أن يكون المعرّف الفريد للحالة والبيانات المخزّنة مفيدًا لتتبع عمليات تنفيذ التدفق والحفاظ على السياق بين المهام. + +**ملاحظة:** تأكد من إعداد ملف `.env` لتخزين `OPENAI_API_KEY` الخاص بك. هذا المفتاح ضروري للمصادقة على طلبات OpenAI API. + +### @start() + +يحدد المزخرف `@start()` نقاط الدخول للتدفق. يمكنك: + +- تعريف عدة نقاط بداية غير مشروطة: `@start()` +- ربط البداية بدالة سابقة أو تسمية موجّه: `@start("method_or_label")` +- توفير شرط قابل للاستدعاء للتحكم في وقت تنفيذ البداية + +جميع دوال `@start()` المستوفية للشروط ستُنفَّذ (غالبًا بالتوازي) عند بدء أو استئناف التدفق. + +### @listen() + +يُستخدم المزخرف `@listen()` لتحديد دالة كمستمع لمخرجات مهمة أخرى في التدفق. ستُنفَّذ الدالة المزخرفة بـ `@listen()` عندما تُصدر المهمة المحددة مخرجاتها. يمكن للدالة الوصول إلى مخرجات المهمة التي تستمع إليها كمعامل. + +#### الاستخدام + +يمكن استخدام المزخرف `@listen()` بعدة طرق: + +1. **الاستماع لدالة بالاسم**: يمكنك تمرير اسم الدالة التي تريد الاستماع إليها كسلسلة نصية. عند اكتمال تلك الدالة، سيتم تشغيل دالة المستمع. + + ```python Code + @listen("generate_city") + def generate_fun_fact(self, random_city): + # Implementation + ``` + +2. **الاستماع لدالة مباشرة**: يمكنك تمرير الدالة نفسها. عند اكتمال تلك الدالة، سيتم تشغيل دالة المستمع. + ```python Code + @listen(generate_city) + def generate_fun_fact(self, random_city): + # Implementation + ``` + +### مخرجات التدفق + +الوصول إلى مخرجات التدفق والتعامل معها أمر أساسي لدمج سير عمل الذكاء الاصطناعي في التطبيقات أو الأنظمة الأكبر. توفر تدفقات CrewAI آليات مباشرة لاسترداد المخرجات النهائية والوصول إلى النتائج الوسيطة وإدارة الحالة العامة للتدفق. + +#### استرداد المخرجات النهائية + +عند تشغيل تدفق، يتم تحديد المخرجات النهائية بواسطة آخر دالة تكتمل. تُعيد دالة `kickoff()` مخرجات هذه الدالة الأخيرة. + +إليك كيفية الوصول إلى المخرجات النهائية: + + +```python Code +from crewai.flow.flow import Flow, listen, start + +class OutputExampleFlow(Flow): + @start() + def first_method(self): + return "Output from first_method" + + @listen(first_method) + def second_method(self, first_output): + return f"Second method received: {first_output}" + + +flow = OutputExampleFlow() +flow.plot("my_flow_plot") +final_output = flow.kickoff() + +print("---- Final Output ----") +print(final_output) +``` + +```text Output +---- Final Output ---- +Second method received: Output from first_method +``` + + +![Flow Visual image](/images/crewai-flow-2.png) + +في هذا المثال، `second_method` هي آخر دالة تكتمل، لذا ستكون مخرجاتها هي المخرجات النهائية للتدفق. +ستُعيد دالة `kickoff()` المخرجات النهائية، التي تُطبع بعد ذلك في وحدة التحكم. ستولّد دالة `plot()` ملف HTML الذي سيساعدك على فهم التدفق. + +#### الوصول إلى الحالة وتحديثها + +بالإضافة إلى استرداد المخرجات النهائية، يمكنك أيضًا الوصول إلى الحالة وتحديثها داخل التدفق. يمكن استخدام الحالة لتخزين ومشاركة البيانات بين الدوال المختلفة في التدفق. بعد تشغيل التدفق، يمكنك الوصول إلى الحالة لاسترداد أي معلومات تمت إضافتها أو تحديثها أثناء التنفيذ. + +إليك مثال على كيفية تحديث الحالة والوصول إليها: + + + +```python Code +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + counter: int = 0 + message: str = "" + +class StateExampleFlow(Flow[ExampleState]): + + @start() + def first_method(self): + self.state.message = "Hello from first_method" + self.state.counter += 1 + + @listen(first_method) + def second_method(self): + self.state.message += " - updated by second_method" + self.state.counter += 1 + return self.state.message + +flow = StateExampleFlow() +flow.plot("my_flow_plot") +final_output = flow.kickoff() +print(f"Final Output: {final_output}") +print("Final State:") +print(flow.state) +``` + +```text Output +Final Output: Hello from first_method - updated by second_method +Final State: +counter=2 message='Hello from first_method - updated by second_method' +``` + + + +![Flow Visual image](/images/crewai-flow-2.png) + +في هذا المثال، يتم تحديث الحالة بواسطة كل من `first_method` و `second_method`. +بعد تشغيل التدفق، يمكنك الوصول إلى الحالة النهائية لرؤية التحديثات التي أجرتها هذه الدوال. + +من خلال ضمان إعادة مخرجات الدالة الأخيرة وتوفير الوصول إلى الحالة، تجعل تدفقات CrewAI من السهل دمج نتائج سير عمل الذكاء الاصطناعي في التطبيقات أو الأنظمة الأكبر، +مع الحفاظ على الوصول إلى الحالة طوال تنفيذ التدفق. + +## مقاييس استخدام التدفق + +بعد اكتمال تنفيذ التدفق، يمكنك الوصول إلى الخاصية `usage_metrics` لعرض إجمالي استخدام التوكنات عبر **كل استدعاء لنموذج اللغة** يتم خلال التشغيل — بما في ذلك الاستدعاءات من كل فريق (Crew) ينظمه التدفق، والاستدعاءات داخل أدوات الـ Agents، والاستدعاءات المباشرة لـ `LLM.call(...)` من دوال التدفق. هذا هو المكافئ على جانب الـ SDK للإجماليات المعروضة في واجهة CrewAI Enterprise. + +```python Code +from crewai import LLM +from crewai.flow.flow import Flow, listen, start + +class UsageMetricsFlow(Flow): + @start() + def run_first_crew(self): + self.state.first_result = FirstCrew().crew().kickoff() + + @listen(run_first_crew) + def call_llm_directly(self): + # استدعاء مباشر لنموذج اللغة — يُحسب أيضًا ضمن flow.usage_metrics + llm = LLM(model="openai/gpt-4o-mini") + self.state.summary = llm.call("لخّص النقاط الرئيسية.") + + @listen(call_llm_directly) + def run_second_crew(self): + self.state.second_result = SecondCrew().crew().kickoff() + +flow = UsageMetricsFlow() +flow.kickoff() + +print(flow.usage_metrics) +# UsageMetrics(total_tokens=8579, prompt_tokens=6210, completion_tokens=2369, +# cached_prompt_tokens=0, reasoning_tokens=0, +# cache_creation_tokens=0, successful_requests=5) +``` + + + `flow.usage_metrics` **ليست** نفس `flow.kickoff().token_usage`. هذه الأخيرة + ترجع فقط `CrewOutput.token_usage` لـ **آخر** دالة `@listen` أعادت + `CrewOutput`، مما يعني أنها تعكس فقط الفريق الأخير وتتجاهل الفرق السابقة + وكذلك أي استدعاءات مباشرة لـ `LLM.call(...)`. استخدم `flow.usage_metrics` + كلما احتجت إلى الإجمالي **الكامل** للتوكنات لتنفيذ التدفق. + + +### دلالات حقول UsageMetrics + +يستخدم كائن [`UsageMetrics`](https://github.com/crewAIInc/crewAI/blob/main/lib/crewai/src/crewai/types/usage_metrics.py) المُعاد عقدًا محايدًا للمزود: + +| الحقل | المعنى | +| --- | --- | +| `total_tokens` | الإجمالي المفوتر: `prompt_tokens + completion_tokens` | +| `prompt_tokens` | إجمالي رموز الإدخال/المطالبة المفوترة للطلب | +| `completion_tokens` | رموز الإخراج/الإكمال المفوترة للطلب | +| `cached_prompt_tokens` | جزء قراءة الذاكرة المؤقتة من رموز المطالبة (تفصيل فقط) | +| `cache_creation_tokens` | جزء كتابة الذاكرة المؤقتة من رموز المطالبة (تفصيل فقط، Anthropic) | +| `reasoning_tokens` | جزء التفكير/الاستدلال حيث يبلّغ المزود عنه بشكل منفصل (تفصيل فقط) | +| `successful_requests` | عدد استدعاءات LLM المُجمّعة | + +حقول التفصيل مثل `cached_prompt_tokens` و`cache_creation_tokens` و`reasoning_tokens` **لا تُضاف** فوق `total_tokens` — بل تصف أجزاءً مُدرجة بالفعل ضمن `prompt_tokens` أو `completion_tokens`. + +بالنسبة إلى Anthropic، تُدمج عدادات قراءة وكتابة الذاكرة المؤقتة ضمن `prompt_tokens`، لذا تنعكس أعباء العمل المخزنة مؤقتًا بالكامل في `total_tokens`. يُدرج مزودو OpenAI الرموز المخزنة مؤقتًا بالفعل داخل `prompt_tokens`؛ يعرض CrewAI الجزء المخزن مؤقتًا بشكل منفصل للوضوح. + +كل حقل في [`UsageMetrics`](https://github.com/crewAIInc/crewAI/blob/main/lib/crewai/src/crewai/types/usage_metrics.py) المُعاد هو مجموع جميع استدعاءات نموذج اللغة التي حدثت خلال استدعاء واحد لـ `flow.kickoff()`. تتم إعادة تعيين العدادات عند الاستدعاء التالي لـ `kickoff()` (وفي كل تكرار من `kickoff_for_each`)، لذلك لن تتكرر العدّات عبر التشغيلات المتتالية. يمكن قراءة هذه الخاصية بأمان في أي وقت بعد اكتمال `kickoff()`؛ قراءتها أثناء التنفيذ تُرجع المجموع الجزئي المتراكم حتى تلك اللحظة. + +## إدارة حالة التدفق + +إدارة الحالة بفعالية أمر بالغ الأهمية لبناء سير عمل ذكاء اصطناعي موثوق وقابل للصيانة. توفر تدفقات CrewAI آليات قوية لإدارة الحالة غير المهيكلة والمهيكلة، +مما يتيح للمطورين اختيار النهج الأنسب لاحتياجات تطبيقاتهم. + +### إدارة الحالة غير المهيكلة + +في إدارة الحالة غير المهيكلة، يتم تخزين جميع الحالات في خاصية `state` لفئة `Flow`. +يوفر هذا النهج مرونة، مما يمكّن المطورين من إضافة أو تعديل خصائص الحالة أثناء التشغيل دون تحديد مخطط صارم. +حتى مع الحالات غير المهيكلة، تولّد تدفقات CrewAI تلقائيًا معرّفًا فريدًا (UUID) لكل مثيل حالة وتحافظ عليه. + +```python Code +from crewai.flow.flow import Flow, listen, start + +class UnstructuredExampleFlow(Flow): + + @start() + def first_method(self): + # The state automatically includes an 'id' field + print(f"State ID: {self.state['id']}") + self.state['counter'] = 0 + self.state['message'] = "Hello from structured flow" + + @listen(first_method) + def second_method(self): + self.state['counter'] += 1 + self.state['message'] += " - updated" + + @listen(second_method) + def third_method(self): + self.state['counter'] += 1 + self.state['message'] += " - updated again" + + print(f"State after third_method: {self.state}") + + +flow = UnstructuredExampleFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +![Flow Visual image](/images/crewai-flow-3.png) + +**ملاحظة:** يتم توليد حقل `id` تلقائيًا والحفاظ عليه طوال تنفيذ التدفق. لا تحتاج إلى إدارته أو تعيينه يدويًا، وسيتم الحفاظ عليه حتى عند تحديث الحالة ببيانات جديدة. + +**النقاط الرئيسية:** + +- **المرونة:** يمكنك إضافة خصائص ديناميكيًا إلى `self.state` دون قيود محددة مسبقًا. +- **البساطة:** مثالي لسير العمل البسيط حيث يكون هيكل الحالة بسيطًا أو متغيرًا بشكل كبير. + +### إدارة الحالة المهيكلة + +تستفيد إدارة الحالة المهيكلة من مخططات محددة مسبقًا لضمان الاتساق وسلامة الأنواع عبر سير العمل. +باستخدام نماذج مثل `BaseModel` من Pydantic، يمكن للمطورين تحديد الشكل الدقيق للحالة، مما يتيح تحققًا أفضل وإكمالًا تلقائيًا في بيئات التطوير. + +تتلقى كل حالة في تدفقات CrewAI تلقائيًا معرّفًا فريدًا (UUID) للمساعدة في تتبع وإدارة مثيلات الحالة. يتم توليد هذا المعرّف وإدارته تلقائيًا بواسطة نظام التدفق. + +```python Code +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + + +class ExampleState(BaseModel): + # Note: 'id' field is automatically added to all states + counter: int = 0 + message: str = "" + + +class StructuredExampleFlow(Flow[ExampleState]): + + @start() + def first_method(self): + # Access the auto-generated ID if needed + print(f"State ID: {self.state.id}") + self.state.message = "Hello from structured flow" + + @listen(first_method) + def second_method(self): + self.state.counter += 1 + self.state.message += " - updated" + + @listen(second_method) + def third_method(self): + self.state.counter += 1 + self.state.message += " - updated again" + + print(f"State after third_method: {self.state}") + + +flow = StructuredExampleFlow() +flow.kickoff() +``` + +![Flow Visual image](/images/crewai-flow-3.png) + +**النقاط الرئيسية:** + +- **مخطط محدد:** يحدد `ExampleState` هيكل الحالة بوضوح، مما يعزز قابلية قراءة الكود وصيانته. +- **سلامة الأنواع:** يضمن استخدام Pydantic التزام خصائص الحالة بالأنواع المحددة، مما يقلل من أخطاء وقت التشغيل. +- **الإكمال التلقائي:** يمكن لبيئات التطوير المتكاملة توفير إكمال تلقائي أفضل وفحص أخطاء بناءً على نموذج الحالة المحدد. + +### الاختيار بين إدارة الحالة غير المهيكلة والمهيكلة + +- **استخدم إدارة الحالة غير المهيكلة عندما:** + + - يكون حالة سير العمل بسيطة أو ديناميكية للغاية. + - تكون المرونة أولوية على تعريفات الحالة الصارمة. + - يكون النماذج الأولية السريعة مطلوبة دون عبء تحديد المخططات. + +- **استخدم إدارة الحالة المهيكلة عندما:** + - يتطلب سير العمل هيكل حالة محدد جيدًا ومتسق. + - تكون سلامة الأنواع والتحقق مهمتين لموثوقية تطبيقك. + - تريد الاستفادة من ميزات بيئة التطوير المتكاملة مثل الإكمال التلقائي وفحص الأنواع لتجربة مطور أفضل. + +من خلال توفير خيارات إدارة الحالة غير المهيكلة والمهيكلة، تمكّن تدفقات CrewAI المطورين من بناء سير عمل ذكاء اصطناعي مرن ومتين في آن واحد، ملبيةً مجموعة واسعة من متطلبات التطبيقات. + +## استمرارية التدفق + +يتيح مزخرف @persist الاستمرارية التلقائية للحالة في تدفقات CrewAI، مما يسمح لك بالحفاظ على حالة التدفق عبر عمليات إعادة التشغيل أو تنفيذات سير العمل المختلفة. يمكن تطبيق هذا المزخرف على مستوى الفئة أو مستوى الدالة، مما يوفر مرونة في كيفية إدارة استمرارية الحالة. + +### الاستمرارية على مستوى الفئة + +عند التطبيق على مستوى الفئة، يقوم مزخرف @persist باستمرارية حالات جميع دوال التدفق تلقائيًا: + +```python +@persist # Using SQLiteFlowPersistence by default +class MyFlow(Flow[MyState]): + @start() + def initialize_flow(self): + # This method will automatically have its state persisted + self.state.counter = 1 + print("Initialized flow. State ID:", self.state.id) + + @listen(initialize_flow) + def next_step(self): + # The state (including self.state.id) is automatically reloaded + self.state.counter += 1 + print("Flow state is persisted. Counter:", self.state.counter) +``` + +### الاستمرارية على مستوى الدالة + +للتحكم الأكثر دقة، يمكنك تطبيق @persist على دوال محددة: + +```python +class AnotherFlow(Flow[dict]): + @persist # Persists only this method's state + @start() + def begin(self): + if "runs" not in self.state: + self.state["runs"] = 0 + self.state["runs"] += 1 + print("Method-level persisted runs:", self.state["runs"]) +``` + +### تفرع الحالة المستمرة + +يدعم `@persist` نمطين متميزين للترطيب في `kickoff` / `kickoff_async`: + +- `kickoff(inputs={"id": })` — **استئناف**: يحمّل أحدث لقطة لـ UUID المقدم ويستمر في الكتابة تحت نفس `flow_uuid`. يمتد التاريخ. +- `kickoff(restore_from_state_id=)` — **تفرع**: يحمّل أحدث لقطة لـ UUID المقدم، يرطّب حالة التشغيل الجديد منها، ثم يعيّن `state.id` جديدًا (مولّدًا تلقائيًا، أو `inputs["id"]` إذا تم تثبيته). تذهب كتابات `@persist` للتشغيل الجديد تحت `state.id` الجديد؛ يتم الحفاظ على تاريخ تدفق المصدر. + +```python +from crewai.flow.flow import Flow, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + id: str = "" + counter: int = 0 + +@persist +class CounterFlow(Flow[CounterState]): + @start() + def step(self): + self.state.counter += 1 + print(f"[id={self.state.id}] counter={self.state.counter}") + +# التشغيل 1: حالة جديدة، العداد 0 -> 1، محفوظ تحت flow_1.state.id +flow_1 = CounterFlow() +flow_1.kickoff() + +# التفرع: ترطيب من أحدث لقطة لـ flow_1، لكن باستخدام state.id جديد +flow_2 = CounterFlow() +flow_2.kickoff(restore_from_state_id=flow_1.state.id) +# يبدأ flow_2.state.counter بـ 1 (مرطّب)، ثم تزيده step() إلى 2. +# flow_2.state.id != flow_1.state.id؛ تاريخ flow_1 لم يتغيّر. +``` + +إذا لم يطابق `restore_from_state_id` المقدم أي حالة مستمرة، يعود kickoff بصمت إلى السلوك الافتراضي — نفس سلوك `inputs["id"]` عند عدم العثور عليه. الجمع بين `restore_from_state_id` و `from_checkpoint` يطلق `ValueError`؛ اختر مصدر ترطيب واحدًا. تثبيت `inputs["id"]` أثناء التفرع يشارك مفتاح الاستمرارية مع تدفق آخر — عادةً ما تريد استخدام `restore_from_state_id` فقط. + +### كيف تعمل + +1. **تعريف الحالة الفريد** + - تتلقى كل حالة تدفق UUID فريد تلقائيًا + - يتم الحفاظ على المعرّف عبر تحديثات الحالة واستدعاءات الدوال + - يدعم كلًا من الحالات المهيكلة (Pydantic BaseModel) وغير المهيكلة (القاموس) + +2. **واجهة SQLite الافتراضية** + - SQLiteFlowPersistence هي واجهة التخزين الافتراضية + - يتم حفظ الحالات تلقائيًا في قاعدة بيانات SQLite محلية + - معالجة أخطاء متينة تضمن رسائل واضحة في حالة فشل عمليات قاعدة البيانات + +3. **معالجة الأخطاء** + - رسائل خطأ شاملة لعمليات قاعدة البيانات + - تحقق تلقائي من الحالة أثناء الحفظ والتحميل + - ملاحظات واضحة عند مواجهة مشاكل في عمليات الاستمرارية + +### اعتبارات مهمة + +- **أنواع الحالة**: يتم دعم كل من الحالات المهيكلة (Pydantic BaseModel) وغير المهيكلة (القاموس) +- **المعرّف التلقائي**: يتم إضافة حقل `id` تلقائيًا إذا لم يكن موجودًا +- **استعادة الحالة**: يمكن للتدفقات الفاشلة أو المُعاد تشغيلها إعادة تحميل حالتها السابقة تلقائيًا +- **التنفيذ المخصص**: يمكنك توفير تنفيذ FlowPersistence الخاص بك لاحتياجات التخزين المتخصصة + +### المزايا التقنية + +1. **تحكم دقيق من خلال الوصول المنخفض المستوى** + - وصول مباشر لعمليات الاستمرارية لحالات الاستخدام المتقدمة + - تحكم دقيق عبر مزخرفات الاستمرارية على مستوى الدوال + - قدرات مدمجة لفحص الحالة وتصحيح الأخطاء + - رؤية كاملة لتغييرات الحالة وعمليات الاستمرارية + +2. **موثوقية معززة** + - استعادة تلقائية للحالة بعد أعطال النظام أو إعادة التشغيل + - تحديثات حالة قائمة على المعاملات لسلامة البيانات + - معالجة أخطاء شاملة مع رسائل خطأ واضحة + - تحقق متين أثناء عمليات حفظ وتحميل الحالة + +3. **بنية قابلة للتوسع** + - واجهة استمرارية قابلة للتخصيص من خلال واجهة FlowPersistence + - دعم لحلول تخزين متخصصة تتجاوز SQLite + - متوافقة مع كل من الحالات المهيكلة (Pydantic) وغير المهيكلة (dict) + - تكامل سلس مع أنماط تدفق CrewAI الحالية + +تركز بنية نظام الاستمرارية على الدقة التقنية وخيارات التخصيص، مما يتيح للمطورين الحفاظ على التحكم الكامل في إدارة الحالة مع الاستفادة من ميزات الموثوقية المدمجة. + +## التحكم في التدفق + +### المنطق الشرطي: `or` + +تتيح لك دالة `or_` في التدفقات الاستماع لعدة دوال وتشغيل دالة المستمع عندما تُصدر أي من الدوال المحددة مخرجاتها. + + + +```python Code +from crewai.flow.flow import Flow, listen, or_, start + +class OrExampleFlow(Flow): + + @start() + def start_method(self): + return "Hello from the start method" + + @listen(start_method) + def second_method(self): + return "Hello from the second method" + + @listen(or_(start_method, second_method)) + def logger(self, result): + print(f"Logger: {result}") + + + +flow = OrExampleFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +```text Output +Logger: Hello from the start method +Logger: Hello from the second method +``` + + + +![Flow Visual image](/images/crewai-flow-4.png) + +عند تشغيل هذا التدفق، سيتم تشغيل دالة `logger` بواسطة مخرجات إما `start_method` أو `second_method`. +تُستخدم دالة `or_` للاستماع لعدة دوال وتشغيل دالة المستمع عندما تُصدر أي من الدوال المحددة مخرجاتها. + +### المنطق الشرطي: `and` + +تتيح لك دالة `and_` في التدفقات الاستماع لعدة دوال وتشغيل دالة المستمع فقط عندما تُصدر جميع الدوال المحددة مخرجاتها. + + + +```python Code +from crewai.flow.flow import Flow, and_, listen, start + +class AndExampleFlow(Flow): + + @start() + def start_method(self): + self.state["greeting"] = "Hello from the start method" + + @listen(start_method) + def second_method(self): + self.state["joke"] = "What do computers eat? Microchips." + + @listen(and_(start_method, second_method)) + def logger(self): + print("---- Logger ----") + print(self.state) + +flow = AndExampleFlow() +flow.plot() +flow.kickoff() +``` + +```text Output +---- Logger ---- +{'greeting': 'Hello from the start method', 'joke': 'What do computers eat? Microchips.'} +``` + + + +![Flow Visual image](/images/crewai-flow-5.png) + +عند تشغيل هذا التدفق، سيتم تشغيل دالة `logger` فقط عندما يُصدر كل من `start_method` و `second_method` مخرجاتهما. +تُستخدم دالة `and_` للاستماع لعدة دوال وتشغيل دالة المستمع فقط عندما تُصدر جميع الدوال المحددة مخرجاتها. + +### الموجّه + +يتيح لك مزخرف `@router()` في التدفقات تحديد منطق توجيه شرطي بناءً على مخرجات دالة. +يمكنك تحديد مسارات مختلفة بناءً على مخرجات الدالة، مما يتيح لك التحكم في تدفق التنفيذ ديناميكيًا. + + + +```python Code +import random +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + success_flag: bool = False + +class RouterFlow(Flow[ExampleState]): + + @start() + def start_method(self): + print("Starting the structured flow") + random_boolean = random.choice([True, False]) + self.state.success_flag = random_boolean + + @router(start_method) + def second_method(self): + if self.state.success_flag: + return "success" + else: + return "failed" + + @listen("success") + def third_method(self): + print("Third method running") + + @listen("failed") + def fourth_method(self): + print("Fourth method running") + + +flow = RouterFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +```text Output +Starting the structured flow +Third method running +Fourth method running +``` + + + +![Flow Visual image](/images/crewai-flow-6.png) + +في المثال أعلاه، تولّد `start_method` قيمة منطقية عشوائية وتعيّنها في الحالة. +تستخدم `second_method` مزخرف `@router()` لتحديد منطق توجيه شرطي بناءً على قيمة المنطقية. +إذا كانت القيمة `True`، تُعيد الدالة `"success"`، وإذا كانت `False`، تُعيد `"failed"`. +تستمع `third_method` و `fourth_method` لمخرجات `second_method` وتُنفَّذ بناءً على القيمة المُعادة. + +عند تشغيل هذا التدفق، ستتغير المخرجات بناءً على القيمة المنطقية العشوائية المولّدة بواسطة `start_method`. + +### الإنسان في الحلقة (التغذية الراجعة البشرية) + + +يتطلب مزخرف `@human_feedback` **CrewAI الإصدار 1.8.0 أو أعلى**. + + +يتيح مزخرف `@human_feedback` سير عمل يتضمن تدخلًا بشريًا من خلال إيقاف تنفيذ التدفق مؤقتًا لجمع تغذية راجعة من إنسان. هذا مفيد لبوابات الموافقة ومراجعة الجودة ونقاط القرار التي تتطلب حكمًا بشريًا. + +```python Code +from crewai.flow.flow import Flow, start, listen +from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult + +class ReviewFlow(Flow): + @start() + @human_feedback( + message="Do you approve this content?", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + def generate_content(self): + return "Content to be reviewed..." + + @listen("approved") + def on_approval(self, result: HumanFeedbackResult): + print(f"Approved! Feedback: {result.feedback}") + + @listen("rejected") + def on_rejection(self, result: HumanFeedbackResult): + print(f"Rejected. Reason: {result.feedback}") +``` + +عند تحديد `emit`، يتم تفسير التغذية الراجعة الحرة للإنسان بواسطة LLM وتُختصر إلى إحدى النتائج المحددة، والتي تُشغل بعد ذلك مزخرف `@listen` المقابل. + +يمكنك أيضًا استخدام `@human_feedback` دون توجيه لجمع التغذية الراجعة ببساطة: + +```python Code +@start() +@human_feedback(message="Any comments on this output?") +def my_method(self): + return "Output for review" + +@listen(my_method) +def next_step(self, result: HumanFeedbackResult): + # Access feedback via result.feedback + # Access original output via result.output + pass +``` + +يمكنك الوصول إلى جميع التغذيات الراجعة المُجمّعة أثناء التدفق عبر `self.last_human_feedback` (الأحدث) أو `self.human_feedback_history` (جميع التغذيات الراجعة كقائمة). + +للحصول على دليل كامل حول التغذية الراجعة البشرية في التدفقات، بما في ذلك **التغذية الراجعة غير المتزامنة/غير الحاجبة** مع مزودين مخصصين (Slack، webhooks، إلخ)، انظر [التغذية الراجعة البشرية في التدفقات](/ar/learn/human-feedback-in-flows). + +## إضافة Agents إلى التدفقات + +يمكن دمج Agents بسلاسة في تدفقاتك، مما يوفر بديلًا خفيف الوزن لفرق Crew الكاملة عندما تحتاج إلى تنفيذ مهام أبسط وأكثر تركيزًا. إليك مثال على كيفية استخدام Agent ضمن تدفق لإجراء أبحاث السوق: + +```python +import asyncio +from typing import Any, Dict, List + +from crewai_tools import SerperDevTool +from pydantic import BaseModel, Field + +from crewai.agent import Agent +from crewai.flow.flow import Flow, listen, start + + +# Define a structured output format +class MarketAnalysis(BaseModel): + key_trends: List[str] = Field(description="List of identified market trends") + market_size: str = Field(description="Estimated market size") + competitors: List[str] = Field(description="Major competitors in the space") + + +# Define flow state +class MarketResearchState(BaseModel): + product: str = "" + analysis: MarketAnalysis | None = None + + +# Create a flow class +class MarketResearchFlow(Flow[MarketResearchState]): + @start() + def initialize_research(self) -> Dict[str, Any]: + print(f"Starting market research for {self.state.product}") + return {"product": self.state.product} + + @listen(initialize_research) + async def analyze_market(self) -> Dict[str, Any]: + # Create an Agent for market research + analyst = Agent( + role="Market Research Analyst", + goal=f"Analyze the market for {self.state.product}", + backstory="You are an experienced market analyst with expertise in " + "identifying market trends and opportunities.", + tools=[SerperDevTool()], + verbose=True, + ) + + # Define the research query + query = f""" + Research the market for {self.state.product}. Include: + 1. Key market trends + 2. Market size + 3. Major competitors + + Format your response according to the specified structure. + """ + + # Execute the analysis with structured output format + result = await analyst.kickoff_async(query, response_format=MarketAnalysis) + if result.pydantic: + print("result", result.pydantic) + else: + print("result", result) + + # Return the analysis to update the state + return {"analysis": result.pydantic} + + @listen(analyze_market) + def present_results(self, analysis) -> None: + print("\nMarket Analysis Results") + print("=====================") + + if isinstance(analysis, dict): + # If we got a dict with 'analysis' key, extract the actual analysis object + market_analysis = analysis.get("analysis") + else: + market_analysis = analysis + + if market_analysis and isinstance(market_analysis, MarketAnalysis): + print("\nKey Market Trends:") + for trend in market_analysis.key_trends: + print(f"- {trend}") + + print(f"\nMarket Size: {market_analysis.market_size}") + + print("\nMajor Competitors:") + for competitor in market_analysis.competitors: + print(f"- {competitor}") + else: + print("No structured analysis data available.") + print("Raw analysis:", analysis) + + +# Usage example +async def run_flow(): + flow = MarketResearchFlow() + flow.plot("MarketResearchFlowPlot") + result = await flow.kickoff_async(inputs={"product": "AI-powered chatbots"}) + return result + + +# Run the flow +if __name__ == "__main__": + asyncio.run(run_flow()) +``` + +![Flow Visual image](/images/crewai-flow-7.png) + +يوضح هذا المثال عدة ميزات رئيسية لاستخدام Agents في التدفقات: + +1. **المخرجات المهيكلة**: استخدام نماذج Pydantic لتحديد تنسيق المخرجات المتوقع (`MarketAnalysis`) يضمن سلامة الأنواع والبيانات المهيكلة في جميع أنحاء التدفق. + +2. **إدارة الحالة**: تحافظ حالة التدفق (`MarketResearchState`) على السياق بين الخطوات وتخزّن كلًا من المدخلات والمخرجات. + +3. **تكامل الأدوات**: يمكن لـ Agents استخدام أدوات (مثل `WebsiteSearchTool`) لتعزيز قدراتهم. + +## إضافة فرق Crew إلى التدفقات + +إنشاء تدفق مع فرق Crew متعددة في CrewAI أمر مباشر. + +يمكنك إنشاء مشروع CrewAI جديد يتضمن جميع الهيكلية اللازمة لإنشاء تدفق مع فرق Crew متعددة عن طريق تشغيل الأمر التالي: + +```bash +crewai create flow name_of_flow +``` + +سيولّد هذا الأمر مشروع CrewAI جديد مع هيكل المجلدات اللازم. يتضمن المشروع المولّد فريق Crew مُعد مسبقًا يُسمى `poem_crew` ويعمل بالفعل. يستخدم الـ embedded crew الابتدائي بنية Python/YAML الكلاسيكية؛ أما crews المستقلة الجديدة التي تُنشأ عبر `crewai create crew` فتستخدم بنية JSON-first. + +### هيكل المجلدات + +بعد تشغيل أمر `crewai create flow name_of_flow`، سترى هيكل مجلدات مشابه للتالي: + +| المجلد/الملف | الوصف | +| :--------------------- | :----------------------------------------------------------------- | +| `name_of_flow/` | المجلد الجذر للتدفق. | +| ├── `crews/` | يحتوي على مجلدات لفرق Crew المحددة. | +| │ └── `poem_crew/` | مجلد لـ "poem_crew" مع إعداداته وسكربتاته. | +| │ ├── `config/` | مجلد ملفات الإعداد لـ "poem_crew". | +| │ │ ├── `agents.yaml` | ملف YAML يحدد الـ Agents لـ "poem_crew". | +| │ │ └── `tasks.yaml` | ملف YAML يحدد المهام لـ "poem_crew". | +| │ ├── `poem_crew.py` | سكربت وظائف "poem_crew". | +| ├── `tools/` | مجلد للأدوات الإضافية المُستخدمة في التدفق. | +| │ └── `custom_tool.py` | تنفيذ أداة مخصصة. | +| ├── `main.py` | السكربت الرئيسي لتشغيل التدفق. | +| ├── `README.md` | وصف المشروع والتعليمات. | +| ├── `pyproject.toml` | ملف إعداد تبعيات المشروع والإعدادات. | +| └── `.gitignore` | يحدد الملفات والمجلدات المراد تجاهلها في التحكم بالإصدارات. | + +### بناء فرق Crew الخاصة بك + +في مجلد `crews`، يمكنك تحديد فرق Crew متعددة. سيكون لكل فريق مجلده الخاص الذي يحتوي على ملفات الإعداد وملف تعريف الفريق. على سبيل المثال، يحتوي مجلد `poem_crew` على: + +- `config/agents.yaml`: يحدد الـ Agents للفريق. +- `config/tasks.yaml`: يحدد المهام للفريق. +- `poem_crew.py`: يحتوي على تعريف الفريق، بما في ذلك الـ Agents والمهام والفريق نفسه. + +يمكنك نسخ ولصق وتعديل `poem_crew` لإنشاء crews كلاسيكية مضمّنة أخرى. + +للـ crews المضمّنة بنمط JSON-first، استخدم مجلدًا يحتوي على `crew.jsonc` و `agents/*.jsonc`: + +```text +crews/ +└── research_crew/ + ├── agents/ + │ └── researcher.jsonc + └── crew.jsonc +``` + +ثم حمّلها من خطوة في Flow: + +```python +from pathlib import Path +from crewai.project import load_crew + +crew, default_inputs = load_crew( + Path(__file__).parent / "crews" / "research_crew" / "crew.jsonc" +) +result = crew.kickoff(inputs={**default_inputs, "topic": "AI Agents"}) +``` + +### ربط فرق Crew في `main.py` + +ملف `main.py` هو حيث تنشئ التدفق وتربط فرق Crew معًا. يمكنك تحديد التدفق باستخدام فئة `Flow` والمزخرفات `@start` و `@listen` لتحديد تدفق التنفيذ. + +إليك مثال على كيفية ربط `poem_crew` في ملف `main.py`: + +```python Code +#!/usr/bin/env python +from random import randint + +from pydantic import BaseModel +from crewai.flow.flow import Flow, listen, start +from .crews.poem_crew.poem_crew import PoemCrew + + +class PoemState(BaseModel): + sentence_count: int = 1 + poem: str = "" + +class PoemFlow(Flow[PoemState]): + + @start() + def generate_sentence_count(self): + print("Generating sentence count") + self.state.sentence_count = randint(1, 5) + + @listen(generate_sentence_count) + def generate_poem(self): + print("Generating poem") + result = PoemCrew().crew().kickoff(inputs={"sentence_count": self.state.sentence_count}) + + print("Poem generated", result.raw) + self.state.poem = result.raw + + @listen(generate_poem) + def save_poem(self): + print("Saving poem") + with open("poem.txt", "w") as f: + f.write(self.state.poem) + +def kickoff(): + poem_flow = PoemFlow() + poem_flow.kickoff() + + +def plot(): + poem_flow = PoemFlow() + poem_flow.plot("PoemFlowPlot") + +if __name__ == "__main__": + kickoff() + plot() +``` + +في هذا المثال، تحدد فئة `PoemFlow` تدفقًا يولّد عدد الجمل، ويستخدم `PoemCrew` لتوليد قصيدة، ثم يحفظ القصيدة في ملف. يتم بدء التدفق باستدعاء دالة `kickoff()`. سيتم توليد PoemFlowPlot بواسطة دالة `plot()`. + +![Flow Visual image](/images/crewai-flow-8.png) + +### تشغيل التدفق + +(اختياري) قبل تشغيل التدفق، يمكنك تثبيت التبعيات بتشغيل: + +```bash +crewai install +``` + +بمجرد تثبيت جميع التبعيات، تحتاج إلى تفعيل البيئة الافتراضية بتشغيل: + +```bash +source .venv/bin/activate +``` + +بعد تفعيل البيئة الافتراضية، يمكنك تشغيل التدفق بتنفيذ أحد الأوامر التالية: + +```bash +crewai run +``` + +أو + +```bash +uv run kickoff +``` + +سيُنفَّذ التدفق، ويجب أن ترى المخرجات في وحدة التحكم. + +## رسم التدفقات + +يمكن أن يوفر تصوير سير عمل الذكاء الاصطناعي رؤى قيمة حول هيكل ومسارات تنفيذ تدفقاتك. تقدم CrewAI أداة تصوير قوية تتيح لك إنشاء رسوم بيانية تفاعلية لتدفقاتك، مما يسهّل فهم وتحسين سير عمل الذكاء الاصطناعي. + +### ما هي الرسوم البيانية؟ + +الرسوم البيانية في CrewAI هي تمثيلات بصرية لسير عمل الذكاء الاصطناعي. تعرض المهام المختلفة واتصالاتها وتدفق البيانات بينها. يساعد هذا التصوير في فهم تسلسل العمليات وتحديد الاختناقات وضمان توافق منطق سير العمل مع توقعاتك. + +### كيفية إنشاء رسم بياني + +توفر CrewAI طريقتين مريحتين لإنشاء رسوم بيانية لتدفقاتك: + +#### الخيار 1: استخدام دالة `plot()` + +إذا كنت تعمل مباشرة مع مثيل تدفق، يمكنك إنشاء رسم بياني باستدعاء دالة `plot()` على كائن التدفق. ستُنشئ هذه الدالة ملف HTML يحتوي على الرسم البياني التفاعلي لتدفقك. + +```python Code +# Assuming you have a flow instance +flow.plot("my_flow_plot") +``` + +سيُنشئ هذا ملفًا باسم `my_flow_plot.html` في مجلدك الحالي. يمكنك فتح هذا الملف في متصفح ويب لعرض الرسم البياني التفاعلي. + +#### الخيار 2: استخدام سطر الأوامر + +إذا كنت تعمل ضمن مشروع CrewAI منظم، يمكنك إنشاء رسم بياني باستخدام سطر الأوامر. هذا مفيد بشكل خاص للمشاريع الأكبر حيث تريد تصوير إعداد التدفق بالكامل. + +```bash +crewai flow plot +``` + +سيُنشئ هذا الأمر ملف HTML مع الرسم البياني لتدفقك، مشابهًا لدالة `plot()`. سيتم حفظ الملف في مجلد مشروعك، ويمكنك فتحه في متصفح ويب لاستكشاف التدفق. + +### فهم الرسم البياني + +سيعرض الرسم البياني المولّد عُقدًا تمثل المهام في تدفقك، مع حواف موجّهة تشير إلى تدفق التنفيذ. الرسم البياني تفاعلي، مما يتيح لك التكبير والتصغير والتمرير فوق العقد لرؤية تفاصيل إضافية. + +من خلال تصوير تدفقاتك، يمكنك الحصول على فهم أوضح لهيكل سير العمل، مما يسهّل تصحيح الأخطاء وتحسين عمليات الذكاء الاصطناعي والتواصل بشأنها مع الآخرين. + +### الخلاصة + +رسم تدفقاتك هو ميزة قوية في CrewAI تعزز قدرتك على تصميم وإدارة سير عمل الذكاء الاصطناعي المعقدة. سواء اخترت استخدام دالة `plot()` أو سطر الأوامر، فإن إنشاء الرسوم البيانية سيوفر لك تمثيلًا بصريًا لسير عملك، مما يساعد في التطوير والعرض. + +## الخطوات التالية + +إذا كنت مهتمًا باستكشاف أمثلة إضافية للتدفقات، لدينا مجموعة متنوعة من التوصيات في مستودع الأمثلة. إليك أربعة أمثلة تدفق محددة، كل منها يعرض حالات استخدام فريدة لمساعدتك في مطابقة نوع مشكلتك الحالية مع مثال محدد: + +1. **تدفق الرد التلقائي على البريد الإلكتروني**: يوضح هذا المثال حلقة لا نهائية حيث تعمل مهمة خلفية باستمرار لأتمتة ردود البريد الإلكتروني. إنها حالة استخدام رائعة للمهام التي تحتاج إلى التنفيذ بشكل متكرر دون تدخل يدوي. [عرض المثال](https://github.com/crewAIInc/crewAI-examples/tree/main/email_auto_responder_flow) + +2. **تدفق تقييم العملاء المحتملين**: يعرض هذا التدفق إضافة تغذية راجعة بشرية والتعامل مع فروع شرطية مختلفة باستخدام الموجّه. إنه مثال ممتاز لكيفية دمج اتخاذ القرارات الديناميكية والرقابة البشرية في سير عملك. [عرض المثال](https://github.com/crewAIInc/crewAI-examples/tree/main/lead-score-flow) + +3. **تدفق كتابة كتاب**: يتفوق هذا المثال في ربط فرق Crew متعددة معًا، حيث تُستخدم مخرجات فريق واحد بواسطة فريق آخر. على وجه التحديد، يقوم فريق واحد بوضع مخطط لكتاب كامل، ويقوم فريق آخر بإنشاء فصول بناءً على المخطط. في النهاية، يتم ربط كل شيء لإنتاج كتاب كامل. هذا التدفق مثالي للعمليات المعقدة متعددة الخطوات التي تتطلب تنسيقًا بين مهام مختلفة. [عرض المثال](https://github.com/crewAIInc/crewAI-examples/tree/main/write_a_book_with_flows) + +4. **تدفق مساعد الاجتماعات**: يوضح هذا التدفق كيفية بث حدث واحد لتشغيل إجراءات متابعة متعددة. على سبيل المثال، بعد اكتمال اجتماع، يمكن للتدفق تحديث لوحة Trello وإرسال رسالة Slack وحفظ النتائج. إنه مثال رائع للتعامل مع نتائج متعددة من حدث واحد، مما يجعله مثاليًا لإدارة المهام الشاملة وأنظمة الإشعارات. [عرض المثال](https://github.com/crewAIInc/crewAI-examples/tree/main/meeting_assistant_flow) + +من خلال استكشاف هذه الأمثلة، يمكنك الحصول على رؤى حول كيفية الاستفادة من تدفقات CrewAI لحالات استخدام متنوعة، من أتمتة المهام المتكررة إلى إدارة العمليات المعقدة متعددة الخطوات مع اتخاذ القرارات الديناميكية والتغذية الراجعة البشرية. + +أيضًا، شاهد فيديو YouTube الخاص بنا حول كيفية استخدام التدفقات في CrewAI أدناه! + + + +## تشغيل التدفقات + +هناك طريقتان لتشغيل التدفق: + +### استخدام واجهة Flow API + +يمكنك تشغيل تدفق برمجيًا عن طريق إنشاء مثيل من فئة التدفق واستدعاء دالة `kickoff()`: + +```python +flow = ExampleFlow() +result = flow.kickoff() +``` + +### بث تنفيذ التدفق + +للحصول على رؤية فورية لتنفيذ التدفق، يمكنك تفعيل البث لتلقي المخرجات فور توليدها: + +```python +class StreamingFlow(Flow): + stream = True # Enable streaming + + @start() + def research(self): + # Your flow implementation + pass + +# Iterate over streaming output +flow = StreamingFlow() +streaming = flow.kickoff() +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# Access final result +result = streaming.result +``` + +تعرّف على المزيد حول البث في دليل [بث تنفيذ التدفق](/ar/learn/streaming-flow-execution). + +## الذاكرة في التدفقات + +يتمتع كل تدفق تلقائيًا بإمكانية الوصول إلى نظام [الذاكرة](/concepts/memory) الموحد في CrewAI. يمكنك تخزين الذكريات واسترجاعها واستخراجها مباشرة داخل أي دالة تدفق باستخدام ثلاث دوال مساعدة مدمجة. + +### الدوال المدمجة + +| الدالة | الوصف | +| :--- | :--- | +| `self.remember(content, **kwargs)` | تخزين المحتوى في الذاكرة. تقبل `scope` و `categories` و `metadata` و `importance` اختياريًا. | +| `self.recall(query, **kwargs)` | استرجاع الذكريات ذات الصلة. تقبل `scope` و `categories` و `limit` و `depth` اختياريًا. | +| `self.extract_memories(content)` | تفكيك النص الخام إلى عبارات ذاكرة منفصلة ومستقلة. | + +يتم إنشاء مثيل `Memory()` افتراضي تلقائيًا عند تهيئة التدفق. يمكنك أيضًا تمرير مثيل مخصص: + +```python +from crewai.flow.flow import Flow +from crewai import Memory + +custom_memory = Memory( + recency_weight=0.5, + recency_half_life_days=7, + embedder={"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}, +) + +flow = MyFlow(memory=custom_memory) +``` + +### مثال: تدفق البحث والتحليل + +```python +from crewai.flow.flow import Flow, listen, start + + +class ResearchAnalysisFlow(Flow): + @start() + def gather_data(self): + # Simulate research findings + findings = ( + "PostgreSQL handles 10k concurrent connections with connection pooling. " + "MySQL caps at around 5k. MongoDB scales horizontally but adds complexity." + ) + + # Extract atomic facts and remember each one + memories = self.extract_memories(findings) + for mem in memories: + self.remember(mem, scope="/research/databases") + + return findings + + @listen(gather_data) + def analyze(self, raw_findings): + # Recall relevant past research (from this run or previous runs) + past = self.recall("database performance and scaling", limit=10, depth="shallow") + + context_lines = [f"- {m.record.content}" for m in past] + context = "\n".join(context_lines) if context_lines else "No prior context." + + return { + "new_findings": raw_findings, + "prior_context": context, + "total_memories": len(past), + } + + +flow = ResearchAnalysisFlow() +result = flow.kickoff() +print(result) +``` + +نظرًا لأن الذاكرة تستمر عبر عمليات التشغيل (مدعومة بـ LanceDB على القرص)، فإن خطوة `analyze` ستستدعي النتائج من عمليات التنفيذ السابقة أيضًا -- مما يتيح تدفقات تتعلم وتراكم المعرفة بمرور الوقت. + +انظر [وثائق الذاكرة](/concepts/memory) لمزيد من التفاصيل حول النطاقات والشرائح والتسجيل المركب وإعداد المُضمِّن والمزيد. + +### استخدام CLI + +بدءًا من الإصدار 0.103.0، يمكنك تشغيل التدفقات باستخدام أمر `crewai run`: + +```shell +crewai run +``` + +يكتشف هذا الأمر تلقائيًا ما إذا كان مشروعك تدفقًا (بناءً على إعداد `type = "flow"` في pyproject.toml الخاص بك) ويشغّله وفقًا لذلك. هذه هي الطريقة الموصى بها لتشغيل التدفقات من سطر الأوامر. + +أمر `crewai flow kickoff` القديم deprecated. استخدم `crewai run` لكل من فرق Crew والتدفقات. diff --git a/docs/v1.15.13/ar/concepts/knowledge.mdx b/docs/v1.15.13/ar/concepts/knowledge.mdx new file mode 100644 index 0000000000..807e0801e9 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/knowledge.mdx @@ -0,0 +1,1095 @@ +--- +title: المعرفة +description: ما هي المعرفة في CrewAI وكيفية استخدامها. +icon: book +mode: "wide" +--- + +## نظرة عامة + +المعرفة في CrewAI هي نظام قوي يتيح لوكلاء الذكاء الاصطناعي الوصول إلى مصادر المعلومات الخارجية واستخدامها أثناء مهامهم. +فكّر فيها كمنح وكلائك مكتبة مرجعية يمكنهم الرجوع إليها أثناء العمل. + + + الفوائد الرئيسية لاستخدام المعرفة: + - تعزيز الوكلاء بمعلومات خاصة بالمجال + - دعم القرارات ببيانات من العالم الحقيقي + - الحفاظ على السياق عبر المحادثات + - بناء الاستجابات على معلومات واقعية + + +## أمثلة البدء السريع + + +لمصادر المعرفة المستندة إلى الملفات، تأكد من وضع ملفاتك في مجلد `knowledge` في جذر مشروعك. +أيضًا، استخدم المسارات النسبية من مجلد `knowledge` عند إنشاء المصدر. + + +### إعداد عميل المتجه (RAG) + +يوفر CrewAI تجريدًا لعميل RAG محايد بالنسبة للمزود لمتاجر المتجهات. المزود الافتراضي هو ChromaDB، ويتم دعم Qdrant أيضًا. يمكنك التبديل بين المزودين باستخدام أدوات الإعداد. + +المدعوم حاليًا: +- ChromaDB (افتراضي) +- Qdrant + +```python Code +from crewai.rag.config.utils import set_rag_config, get_rag_client, clear_rag_config + +# ChromaDB (default) +from crewai.rag.chromadb.config import ChromaDBConfig +set_rag_config(ChromaDBConfig()) +chromadb_client = get_rag_client() + +# Qdrant +from crewai.rag.qdrant.config import QdrantConfig +set_rag_config(QdrantConfig()) +qdrant_client = get_rag_client() + +# Example operations (same API for any provider) +client = qdrant_client # or chromadb_client +client.create_collection(collection_name="docs") +client.add_documents( + collection_name="docs", + documents=[{"id": "1", "content": "CrewAI enables collaborative AI agents."}], +) +results = client.search(collection_name="docs", query="collaborative agents", limit=3) + +clear_rag_config() # optional reset +``` + +عميل RAG هذا منفصل عن التخزين المدمج في المعرفة. استخدمه عندما تحتاج إلى تحكم مباشر في متجر المتجهات أو خطوط أنابيب استرجاع مخصصة. + +### مثال المعرفة النصية الأساسية + +```python Code +from crewai import Agent, Task, Crew, Process, LLM +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create a knowledge source +content = "Users name is John. He is 30 years old and lives in San Francisco." +string_source = StringKnowledgeSource(content=content) + +# Create an LLM with a temperature of 0 to ensure deterministic outputs +llm = LLM(model="gpt-4o-mini", temperature=0) + +# Create an agent with the knowledge store +agent = Agent( + role="About User", + goal="You know everything about the user.", + backstory="You are a master at understanding people and their preferences.", + verbose=True, + allow_delegation=False, + llm=llm, +) + +task = Task( + description="Answer the following questions about the user: {question}", + expected_output="An answer to the question.", + agent=agent, +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True, + process=Process.sequential, + knowledge_sources=[string_source], # Enable knowledge by adding the sources here +) + +result = crew.kickoff(inputs={"question": "What city does John live in and how old is he?"}) +``` + +### مثال معرفة محتوى الويب + + + تحتاج إلى تثبيت `docling` لكي يعمل المثال التالي: `uv add docling` + + +```python Code +from crewai import LLM, Agent, Crew, Process, Task +from crewai.knowledge.source.crew_docling_source import CrewDoclingSource + +# Create a knowledge source from web content +content_source = CrewDoclingSource( + file_paths=[ + "https://lilianweng.github.io/posts/2024-11-28-reward-hacking", + "https://lilianweng.github.io/posts/2024-07-07-hallucination", + ], +) + +# Create an LLM with a temperature of 0 to ensure deterministic outputs +llm = LLM(model="gpt-4o-mini", temperature=0) + +# Create an agent with the knowledge store +agent = Agent( + role="About papers", + goal="You know everything about the papers.", + backstory="You are a master at understanding papers and their content.", + verbose=True, + allow_delegation=False, + llm=llm, +) + +task = Task( + description="Answer the following questions about the papers: {question}", + expected_output="An answer to the question.", + agent=agent, +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True, + process=Process.sequential, + knowledge_sources=[content_source], +) + +result = crew.kickoff( + inputs={"question": "What is the reward hacking paper about? Be sure to provide sources."} +) +``` + +## مصادر المعرفة المدعومة + +يدعم CrewAI أنواعًا متعددة من مصادر المعرفة جاهزة للاستخدام: + + + + - سلاسل نصية خام + - ملفات نصية (.txt) + - مستندات PDF + + + - ملفات CSV + - جداول بيانات Excel + - مستندات JSON + + + +### مصدر معرفة الملفات النصية +```python +from crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource + +text_source = TextFileKnowledgeSource( + file_paths=["document.txt", "another.txt"] +) +``` + +### مصدر معرفة PDF +```python +from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource + +pdf_source = PDFKnowledgeSource( + file_paths=["document.pdf", "another.pdf"] +) +``` + +### مصدر معرفة CSV +```python +from crewai.knowledge.source.csv_knowledge_source import CSVKnowledgeSource + +csv_source = CSVKnowledgeSource( + file_paths=["data.csv"] +) +``` + +### مصدر معرفة Excel +```python +from crewai.knowledge.source.excel_knowledge_source import ExcelKnowledgeSource + +excel_source = ExcelKnowledgeSource( + file_paths=["spreadsheet.xlsx"] +) +``` + +### مصدر معرفة JSON +```python +from crewai.knowledge.source.json_knowledge_source import JSONKnowledgeSource + +json_source = JSONKnowledgeSource( + file_paths=["data.json"] +) +``` + + + يُرجى التأكد من إنشاء مجلد ./knowledge. يجب وضع جميع ملفات المصادر (مثل .txt و .pdf و .xlsx و .json) في هذا المجلد للإدارة المركزية. + + +## معرفة Agent مقابل معرفة Crew: دليل شامل + + +**فهم مستويات المعرفة**: يدعم CrewAI المعرفة على مستوى كل من Agent و Crew. يوضح هذا القسم بالضبط كيف يعمل كل منهما، ومتى يتم تهيئتهما، ويعالج المفاهيم الخاطئة الشائعة حول التبعيات. + + +### كيف تعمل تهيئة المعرفة فعليًا + +إليك ما يحدث بالضبط عند استخدام المعرفة: + +#### معرفة على مستوى Agent (مستقلة) +```python +from crewai import Agent, Task, Crew +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Agent with its own knowledge - NO crew knowledge needed +specialist_knowledge = StringKnowledgeSource( + content="Specialized technical information for this agent only" +) + +specialist_agent = Agent( + role="Technical Specialist", + goal="Provide technical expertise", + backstory="Expert in specialized technical domains", + knowledge_sources=[specialist_knowledge] # Agent-specific knowledge +) + +task = Task( + description="Answer technical questions", + agent=specialist_agent, + expected_output="Technical answer" +) + +# No crew-level knowledge required +crew = Crew( + agents=[specialist_agent], + tasks=[task] +) + +result = crew.kickoff() # Agent knowledge works independently +``` + +#### ما يحدث أثناء `crew.kickoff()` + +عند استدعاء `crew.kickoff()`، إليك التسلسل الدقيق: + +```python +# During kickoff +for agent in self.agents: + agent.crew = self # Agent gets reference to crew + agent.set_knowledge(crew_embedder=self.embedder) # Agent knowledge initialized + agent.create_agent_executor() +``` + +#### استقلالية التخزين + +يستخدم كل مستوى معرفة مجموعات تخزين مستقلة: + +```python +# Agent knowledge storage +agent_collection_name = agent.role # e.g., "Technical Specialist" + +# Crew knowledge storage +crew_collection_name = "crew" + +# Both stored in same ChromaDB instance but different collections +# Path: ~/.local/share/CrewAI/{project}/knowledge/ +# ├── crew/ # Crew knowledge collection +# ├── Technical Specialist/ # Agent knowledge collection +# └── Another Agent Role/ # Another agent's collection +``` + +### أمثلة عملية كاملة + +#### المثال 1: معرفة Agent فقط +```python +from crewai import Agent, Task, Crew +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Agent-specific knowledge +agent_knowledge = StringKnowledgeSource( + content="Agent-specific information that only this agent needs" +) + +agent = Agent( + role="Specialist", + goal="Use specialized knowledge", + backstory="Expert with specific knowledge", + knowledge_sources=[agent_knowledge], + embedder={ # Agent can have its own embedder + "provider": "openai", + "config": {"model": "text-embedding-3-small"} + } +) + +task = Task( + description="Answer using your specialized knowledge", + agent=agent, + expected_output="Answer based on agent knowledge" +) + +# No crew knowledge needed +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() # Works perfectly +``` + +#### المثال 2: معرفة Agent و Crew معًا +```python +# Crew-wide knowledge (shared by all agents) +crew_knowledge = StringKnowledgeSource( + content="Company policies and general information for all agents" +) + +# Agent-specific knowledge +specialist_knowledge = StringKnowledgeSource( + content="Technical specifications only the specialist needs" +) + +specialist = Agent( + role="Technical Specialist", + goal="Provide technical expertise", + backstory="Technical expert", + knowledge_sources=[specialist_knowledge] # Agent-specific +) + +generalist = Agent( + role="General Assistant", + goal="Provide general assistance", + backstory="General helper" + # No agent-specific knowledge +) + +crew = Crew( + agents=[specialist, generalist], + tasks=[...], + knowledge_sources=[crew_knowledge] # Crew-wide knowledge +) + +# Result: +# - specialist gets: crew_knowledge + specialist_knowledge +# - generalist gets: crew_knowledge only +``` + +#### المثال 3: عدة Agents بمعارف مختلفة +```python +# Different knowledge for different agents +sales_knowledge = StringKnowledgeSource(content="Sales procedures and pricing") +tech_knowledge = StringKnowledgeSource(content="Technical documentation") +support_knowledge = StringKnowledgeSource(content="Support procedures") + +sales_agent = Agent( + role="Sales Representative", + knowledge_sources=[sales_knowledge], + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}} +) + +tech_agent = Agent( + role="Technical Expert", + knowledge_sources=[tech_knowledge], + embedder={"provider": "ollama", "config": {"model": "mxbai-embed-large"}} +) + +support_agent = Agent( + role="Support Specialist", + knowledge_sources=[support_knowledge] + # Will use crew embedder as fallback +) + +crew = Crew( + agents=[sales_agent, tech_agent, support_agent], + tasks=[...], + embedder={ # Fallback embedder for agents without their own + "provider": "google-generativeai", + "config": {"model_name": "gemini-embedding-001"} + } +) + +# Each agent gets only their specific knowledge +# Each can use different embedding providers +``` + + +على عكس الاسترجاع من قاعدة بيانات متجهات باستخدام أداة، فإن الوكلاء المُحمّلين مسبقًا بالمعرفة لن يحتاجوا إلى شخصية أو مهمة استرجاع. +ما عليك سوى إضافة مصادر المعرفة ذات الصلة التي يحتاجها Agent أو Crew للعمل. + +يمكن إضافة مصادر المعرفة على مستوى Agent أو Crew. +مصادر المعرفة على مستوى Crew سيستخدمها **جميع الوكلاء** في الفريق. +مصادر المعرفة على مستوى Agent سيستخدمها **الوكيل المحدد** المُحمّل بالمعرفة. + + +## إعداد المعرفة + +يمكنك تهيئة إعداد المعرفة لـ Crew أو Agent. + +```python Code +from crewai.knowledge.knowledge_config import KnowledgeConfig + +knowledge_config = KnowledgeConfig(results_limit=10, score_threshold=0.5) + +agent = Agent( + ... + knowledge_config=knowledge_config +) +``` + + + `results_limit`: هو عدد المستندات ذات الصلة المُعادة. القيمة الافتراضية هي 3. + `score_threshold`: هو الحد الأدنى لدرجة اعتبار المستند ذا صلة. القيمة الافتراضية هي 0.35. + + +## معاملات المعرفة المدعومة + + + قائمة مصادر المعرفة التي توفر المحتوى للتخزين والاستعلام. يمكن أن تشمل ملفات PDF و CSV و Excel و JSON والملفات النصية أو المحتوى النصي. + + + اسم المجموعة التي سيتم تخزين المعرفة فيها. يُستخدم لتحديد مجموعات معرفة مختلفة. القيمة الافتراضية هي "knowledge" إذا لم يتم تحديدها. + + +إعداد تخزين مخصص لإدارة كيفية تخزين المعرفة واسترجاعها. إذا لم يتم تحديده، سيتم إنشاء تخزين افتراضي. + + +## شفافية تخزين المعرفة + + +**فهم تخزين المعرفة**: يخزّن CrewAI مصادر المعرفة تلقائيًا في مجلدات خاصة بالمنصة باستخدام ChromaDB للتخزين المتجهي. فهم هذه المواقع والإعدادات الافتراضية يساعد في النشر في بيئة الإنتاج وتصحيح الأخطاء وإدارة التخزين. + + +### أين يخزّن CrewAI ملفات المعرفة + +بشكل افتراضي، يستخدم CrewAI نفس نظام التخزين مثل الذاكرة، حيث يخزّن المعرفة في مجلدات خاصة بالمنصة: + +#### مواقع التخزين الافتراضية حسب المنصة + +**macOS:** +``` +~/Library/Application Support/CrewAI/{project_name}/ +└── knowledge/ # Knowledge ChromaDB files + ├── chroma.sqlite3 # ChromaDB metadata + ├── {collection_id}/ # Vector embeddings + └── knowledge_{collection}/ # Named collections +``` + +**Linux:** +``` +~/.local/share/CrewAI/{project_name}/ +└── knowledge/ + ├── chroma.sqlite3 + ├── {collection_id}/ + └── knowledge_{collection}/ +``` + +**Windows:** +``` +C:\Users\{username}\AppData\Local\CrewAI\{project_name}\ +└── knowledge\ + ├── chroma.sqlite3 + ├── {collection_id}\ + └── knowledge_{collection}\ +``` + +### معرفة موقع تخزين المعرفة + +لرؤية المكان الذي يخزّن فيه CrewAI ملفات المعرفة بالضبط: + +```python +from crewai.utilities.paths import db_storage_path +import os + +# Get the knowledge storage path +knowledge_path = os.path.join(db_storage_path(), "knowledge") +print(f"Knowledge storage location: {knowledge_path}") + +# List knowledge collections and files +if os.path.exists(knowledge_path): + print("\nKnowledge storage contents:") + for item in os.listdir(knowledge_path): + item_path = os.path.join(knowledge_path, item) + if os.path.isdir(item_path): + print(f"📁 Collection: {item}/") + # Show collection contents + try: + for subitem in os.listdir(item_path): + print(f" └── {subitem}") + except PermissionError: + print(f" └── (permission denied)") + else: + print(f"📄 {item}") +else: + print("No knowledge storage found yet.") +``` + +### التحكم في مواقع تخزين المعرفة + +#### الخيار 1: متغير البيئة (موصى به) +```python +import os +from crewai import Crew + +# Set custom storage location for all CrewAI data +os.environ["CREWAI_STORAGE_DIR"] = "./my_project_storage" + +# All knowledge will now be stored in ./my_project_storage/knowledge/ +crew = Crew( + agents=[...], + tasks=[...], + knowledge_sources=[...] +) +``` + +#### الخيار 2: تخزين معرفة مخصص +```python +from crewai.knowledge.storage.knowledge_storage import KnowledgeStorage +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create custom storage with specific embedder +custom_storage = KnowledgeStorage( + embedder={ + "provider": "ollama", + "config": {"model": "mxbai-embed-large"} + }, + collection_name="my_custom_knowledge" +) + +# Use with knowledge sources +knowledge_source = StringKnowledgeSource( + content="Your knowledge content here" +) +knowledge_source.storage = custom_storage +``` + +#### الخيار 3: تخزين معرفة خاص بالمشروع +```python +import os +from pathlib import Path + +# Store knowledge in project directory +project_root = Path(__file__).parent +knowledge_dir = project_root / "knowledge_storage" + +os.environ["CREWAI_STORAGE_DIR"] = str(knowledge_dir) + +# Now all knowledge will be stored in your project directory +``` + +### سلوك مزود التضمين الافتراضي + + +**مزود التضمين الافتراضي**: يستخدم CrewAI افتراضيًا تضمينات OpenAI (`text-embedding-3-small`) لتخزين المعرفة، حتى عند استخدام مزودي LLM مختلفين. يمكنك تخصيص هذا بسهولة ليتوافق مع إعدادك. + + +#### فهم السلوك الافتراضي +```python +from crewai import Agent, Crew, LLM +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# When using Claude as your LLM... +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + llm=LLM(provider="anthropic", model="claude-3-sonnet") # Using Claude +) + +# CrewAI will still use OpenAI embeddings by default for knowledge +# This ensures consistency but may not match your LLM provider preference +knowledge_source = StringKnowledgeSource(content="Research data...") + +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source] + # Default: Uses OpenAI embeddings even with Claude LLM +) +``` + +#### تخصيص مزودي تضمين المعرفة +```python +# Option 1: Use Voyage AI (recommended by Anthropic for Claude users) +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source], + embedder={ + "provider": "voyageai", # Recommended for Claude users + "config": { + "api_key": "your-voyage-api-key", + "model": "voyage-3" # or "voyage-3-large" for best quality + } + } +) + +# Option 2: Use local embeddings (no external API calls) +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source], + embedder={ + "provider": "ollama", + "config": { + "model": "mxbai-embed-large", + "url": "http://localhost:11434/api/embeddings" + } + } +) + +# Option 3: Agent-level embedding customization +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + knowledge_sources=[knowledge_source], + embedder={ + "provider": "google-generativeai", + "config": { + "model_name": "gemini-embedding-001", + "api_key": "your-google-key" + } + } +) +``` + +#### إعداد تضمينات Azure OpenAI + +عند استخدام تضمينات Azure OpenAI: +1. تأكد من نشر نموذج التضمين في منصة Azure أولًا +2. ثم تحتاج إلى استخدام الإعداد التالي: + +```python +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + knowledge_sources=[knowledge_source], + embedder={ + "provider": "azure", + "config": { + "api_key": "your-azure-api-key", + "model": "text-embedding-ada-002", # change to the model you are using and is deployed in Azure + "api_base": "https://your-azure-endpoint.openai.azure.com/", + "api_version": "2024-02-01" + } + } +) +``` + +## الميزات المتقدمة + +### إعادة صياغة الاستعلام + +ينفذ CrewAI آلية إعادة صياغة استعلام ذكية لتحسين استرجاع المعرفة. عندما يحتاج وكيل إلى البحث في مصادر المعرفة، يتم تحويل موجّه المهمة الخام تلقائيًا إلى استعلام بحث أكثر فعالية. + +#### كيف تعمل إعادة صياغة الاستعلام + +1. عندما ينفذ وكيل مهمة بمصادر معرفة متاحة، يتم تشغيل دالة `_get_knowledge_search_query` +2. يُستخدم LLM الخاص بالوكيل لتحويل موجّه المهمة الأصلي إلى استعلام بحث محسّن +3. يُستخدم هذا الاستعلام المحسّن بعد ذلك لاسترجاع المعلومات ذات الصلة من مصادر المعرفة + +#### فوائد إعادة صياغة الاستعلام + + + + من خلال التركيز على المفاهيم الرئيسية وإزالة المحتوى غير ذي الصلة، تساعد إعادة صياغة الاستعلام في استرجاع معلومات أكثر صلة. + + + تم تصميم الاستعلامات المُعاد صياغتها لتكون أكثر تحديدًا ووعيًا بالسياق لاسترجاع قاعدة بيانات المتجهات. + + + +#### مثال + +```python +# Original task prompt +task_prompt = "Answer the following questions about the user's favorite movies: What movie did John watch last week? Format your answer in JSON." + +# Behind the scenes, this might be rewritten as: +rewritten_query = "What movies did John watch last week?" +``` + +الاستعلام المُعاد صياغته أكثر تركيزًا على الحاجة الأساسية للمعلومات ويزيل التعليمات غير ذات الصلة حول تنسيق المخرجات. + + + هذه الآلية تلقائية بالكامل ولا تتطلب أي إعداد من المستخدمين. يُستخدم LLM الخاص بالوكيل لتنفيذ إعادة صياغة الاستعلام، لذا فإن استخدام LLM أكثر قدرة يمكن أن يحسّن جودة الاستعلامات المُعاد صياغتها. + + +### أحداث المعرفة + +يُصدر CrewAI أحداثًا أثناء عملية استرجاع المعرفة يمكنك الاستماع إليها باستخدام نظام الأحداث. تتيح لك هذه الأحداث مراقبة وتصحيح أخطاء وتحليل كيفية استرجاع المعرفة واستخدامها بواسطة وكلائك. + +#### أحداث المعرفة المتاحة + +- **KnowledgeRetrievalStartedEvent**: يُصدر عندما يبدأ وكيل في استرجاع المعرفة من المصادر +- **KnowledgeRetrievalCompletedEvent**: يُصدر عند اكتمال استرجاع المعرفة، بما في ذلك الاستعلام المُستخدم والمحتوى المُسترجع +- **KnowledgeQueryStartedEvent**: يُصدر عند بدء استعلام مصادر المعرفة +- **KnowledgeQueryCompletedEvent**: يُصدر عند اكتمال الاستعلام بنجاح +- **KnowledgeQueryFailedEvent**: يُصدر عند فشل استعلام مصادر المعرفة +- **KnowledgeSearchQueryFailedEvent**: يُصدر عند فشل استعلام بحث + +#### مثال: مراقبة استرجاع المعرفة + +```python +from crewai.events import ( + KnowledgeRetrievalStartedEvent, + KnowledgeRetrievalCompletedEvent, + BaseEventListener, +) + +class KnowledgeMonitorListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(KnowledgeRetrievalStartedEvent) + def on_knowledge_retrieval_started(source, event): + print(f"Agent '{event.agent.role}' started retrieving knowledge") + + @crewai_event_bus.on(KnowledgeRetrievalCompletedEvent) + def on_knowledge_retrieval_completed(source, event): + print(f"Agent '{event.agent.role}' completed knowledge retrieval") + print(f"Query: {event.query}") + print(f"Retrieved {len(event.retrieved_knowledge)} knowledge chunks") + +# Create an instance of your listener +knowledge_monitor = KnowledgeMonitorListener() +``` + +لمزيد من المعلومات حول استخدام الأحداث، انظر وثائق [مستمعي الأحداث](/ar/concepts/event-listener). + +### مصادر المعرفة المخصصة + +يتيح لك CrewAI إنشاء مصادر معرفة مخصصة لأي نوع من البيانات عن طريق توسيع فئة `BaseKnowledgeSource`. لنقم بإنشاء مثال عملي يجلب ويعالج مقالات أخبار الفضاء. + +#### مثال مصدر معرفة أخبار الفضاء + + + +```python Code +from crewai import Agent, Task, Crew, Process, LLM +from crewai.knowledge.source.base_knowledge_source import BaseKnowledgeSource +import requests +from datetime import datetime +from typing import Dict, Any +from pydantic import BaseModel, Field + +class SpaceNewsKnowledgeSource(BaseKnowledgeSource): + """Knowledge source that fetches data from Space News API.""" + + api_endpoint: str = Field(description="API endpoint URL") + limit: int = Field(default=10, description="Number of articles to fetch") + + def load_content(self) -> Dict[Any, str]: + """Fetch and format space news articles.""" + try: + response = requests.get( + f"{self.api_endpoint}?limit={self.limit}" + ) + response.raise_for_status() + + data = response.json() + articles = data.get('results', []) + + formatted_data = self.validate_content(articles) + return {self.api_endpoint: formatted_data} + except Exception as e: + raise ValueError(f"Failed to fetch space news: {str(e)}") + + def validate_content(self, articles: list) -> str: + """Format articles into readable text.""" + formatted = "Space News Articles:\n\n" + for article in articles: + formatted += f""" + Title: {article['title']} + Published: {article['published_at']} + Summary: {article['summary']} + News Site: {article['news_site']} + URL: {article['url']} + -------------------""" + return formatted + + def add(self) -> None: + """Process and store the articles.""" + content = self.load_content() + for _, text in content.items(): + chunks = self._chunk_text(text) + self.chunks.extend(chunks) + + self._save_documents() + +# Create knowledge source +recent_news = SpaceNewsKnowledgeSource( + api_endpoint="https://api.spaceflightnewsapi.net/v4/articles", + limit=10, +) + +# Create specialized agent +space_analyst = Agent( + role="Space News Analyst", + goal="Answer questions about space news accurately and comprehensively", + backstory="""You are a space industry analyst with expertise in space exploration, + satellite technology, and space industry trends. You excel at answering questions + about space news and providing detailed, accurate information.""", + knowledge_sources=[recent_news], + llm=LLM(model="gpt-4", temperature=0.0) +) + +# Create task that handles user questions +analysis_task = Task( + description="Answer this question about space news: {user_question}", + expected_output="A detailed answer based on the recent space news articles", + agent=space_analyst +) + +# Create and run the crew +crew = Crew( + agents=[space_analyst], + tasks=[analysis_task], + verbose=True, + process=Process.sequential +) + +# Example usage +result = crew.kickoff( + inputs={"user_question": "What are the latest developments in space exploration?"} +) +``` + +```output Output +# Agent: Space News Analyst +## Task: Answer this question about space news: What are the latest developments in space exploration? + + +# Agent: Space News Analyst +## Final Answer: +The latest developments in space exploration, based on recent space news articles, include the following: + +1. SpaceX has received the final regulatory approvals to proceed with the second integrated Starship/Super Heavy launch, scheduled for as soon as the morning of Nov. 17, 2023. This is a significant step in SpaceX's ambitious plans for space exploration and colonization. [Source: SpaceNews](https://spacenews.com/starship-cleared-for-nov-17-launch/) + +2. SpaceX has also informed the US Federal Communications Commission (FCC) that it plans to begin launching its first next-generation Starlink Gen2 satellites. This represents a major upgrade to the Starlink satellite internet service, which aims to provide high-speed internet access worldwide. [Source: Teslarati](https://www.teslarati.com/spacex-first-starlink-gen2-satellite-launch-2022/) + +3. AI startup Synthetaic has raised $15 million in Series B funding. The company uses artificial intelligence to analyze data from space and air sensors, which could have significant applications in space exploration and satellite technology. [Source: SpaceNews](https://spacenews.com/ai-startup-synthetaic-raises-15-million-in-series-b-funding/) + +4. The Space Force has formally established a unit within the U.S. Indo-Pacific Command, marking a permanent presence in the Indo-Pacific region. This could have significant implications for space security and geopolitics. [Source: SpaceNews](https://spacenews.com/space-force-establishes-permanent-presence-in-indo-pacific-region/) + +5. Slingshot Aerospace, a space tracking and data analytics company, is expanding its network of ground-based optical telescopes to increase coverage of low Earth orbit. This could improve our ability to track and analyze objects in low Earth orbit, including satellites and space debris. [Source: SpaceNews](https://spacenews.com/slingshots-space-tracking-network-to-extend-coverage-of-low-earth-orbit/) + +6. The National Natural Science Foundation of China has outlined a five-year project for researchers to study the assembly of ultra-large spacecraft. This could lead to significant advancements in spacecraft technology and space exploration capabilities. [Source: SpaceNews](https://spacenews.com/china-researching-challenges-of-kilometer-scale-ultra-large-spacecraft/) + +7. The Center for AEroSpace Autonomy Research (CAESAR) at Stanford University is focusing on spacecraft autonomy. The center held a kickoff event on May 22, 2024, to highlight the industry, academia, and government collaboration it seeks to foster. This could lead to significant advancements in autonomous spacecraft technology. [Source: SpaceNews](https://spacenews.com/stanford-center-focuses-on-spacecraft-autonomy/) +``` + + + +## تصحيح الأخطاء واستكشاف المشاكل + +### تصحيح مشاكل المعرفة + +#### التحقق من تهيئة معرفة Agent +```python +from crewai import Agent, Crew, Task +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +knowledge_source = StringKnowledgeSource(content="Test knowledge") + +agent = Agent( + role="Test Agent", + goal="Test knowledge", + backstory="Testing", + knowledge_sources=[knowledge_source] +) + +crew = Crew(agents=[agent], tasks=[Task(...)]) + +# Before kickoff - knowledge not initialized +print(f"Before kickoff - Agent knowledge: {getattr(agent, 'knowledge', None)}") + +crew.kickoff() + +# After kickoff - knowledge initialized +print(f"After kickoff - Agent knowledge: {agent.knowledge}") +print(f"Agent knowledge collection: {agent.knowledge.storage.collection_name}") +print(f"Number of sources: {len(agent.knowledge.sources)}") +``` + +#### التحقق من مواقع تخزين المعرفة +```python +import os +from crewai.utilities.paths import db_storage_path + +# Check storage structure +storage_path = db_storage_path() +knowledge_path = os.path.join(storage_path, "knowledge") + +if os.path.exists(knowledge_path): + print("Knowledge collections found:") + for collection in os.listdir(knowledge_path): + collection_path = os.path.join(knowledge_path, collection) + if os.path.isdir(collection_path): + print(f" - {collection}/") + # Show collection contents + for item in os.listdir(collection_path): + print(f" └── {item}") +``` + +#### اختبار استرجاع المعرفة +```python +# Test agent knowledge retrieval +if hasattr(agent, 'knowledge') and agent.knowledge: + test_query = ["test query"] + results = agent.knowledge.query(test_query) + print(f"Agent knowledge results: {len(results)} documents found") + + # Test crew knowledge retrieval (if exists) + if hasattr(crew, 'knowledge') and crew.knowledge: + crew_results = crew.query_knowledge(test_query) + print(f"Crew knowledge results: {len(crew_results)} documents found") +``` + +#### فحص مجموعات المعرفة +```python +import chromadb +from crewai.utilities.paths import db_storage_path +import os + +# Connect to CrewAI's knowledge ChromaDB +knowledge_path = os.path.join(db_storage_path(), "knowledge") + +if os.path.exists(knowledge_path): + client = chromadb.PersistentClient(path=knowledge_path) + collections = client.list_collections() + + print("Knowledge Collections:") + for collection in collections: + print(f" - {collection.name}: {collection.count()} documents") + + # Sample a few documents to verify content + if collection.count() > 0: + sample = collection.peek(limit=2) + print(f" Sample content: {sample['documents'][0][:100]}...") +else: + print("No knowledge storage found") +``` + +#### التحقق من معالجة المعرفة +```python +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create a test knowledge source +test_source = StringKnowledgeSource( + content="Test knowledge content for debugging", + chunk_size=100, # Small chunks for testing + chunk_overlap=20 +) + +# Check chunking behavior +print(f"Original content length: {len(test_source.content)}") +print(f"Chunk size: {test_source.chunk_size}") +print(f"Chunk overlap: {test_source.chunk_overlap}") + +# Process and inspect chunks +test_source.add() +print(f"Number of chunks created: {len(test_source.chunks)}") +for i, chunk in enumerate(test_source.chunks[:3]): # Show first 3 chunks + print(f"Chunk {i+1}: {chunk[:50]}...") +``` + +### مشاكل تخزين المعرفة الشائعة + +**أخطاء "الملف غير موجود":** +```python +# Ensure files are in the correct location +from crewai.utilities.constants import KNOWLEDGE_DIRECTORY +import os + +knowledge_dir = KNOWLEDGE_DIRECTORY # Usually "knowledge" +file_path = os.path.join(knowledge_dir, "your_file.pdf") + +if not os.path.exists(file_path): + print(f"File not found: {file_path}") + print(f"Current working directory: {os.getcwd()}") + print(f"Expected knowledge directory: {os.path.abspath(knowledge_dir)}") +``` + +**أخطاء "عدم تطابق أبعاد التضمين":** +```python +# This happens when switching embedding providers +# Reset knowledge storage to clear old embeddings +crew.reset_memories(command_type='knowledge') + +# Or use consistent embedding providers +crew = Crew( + agents=[...], + tasks=[...], + knowledge_sources=[...], + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}} +) +``` + +**أخطاء "رفض إذن ChromaDB":** +```bash +# Fix storage permissions +chmod -R 755 ~/.local/share/CrewAI/ +``` + +**المعرفة لا تستمر بين عمليات التشغيل:** +```python +# Verify storage location consistency +import os +from crewai.utilities.paths import db_storage_path + +print("CREWAI_STORAGE_DIR:", os.getenv("CREWAI_STORAGE_DIR")) +print("Computed storage path:", db_storage_path()) +print("Knowledge path:", os.path.join(db_storage_path(), "knowledge")) +``` + +### أوامر إعادة تعيين المعرفة + +```python +# Reset only agent-specific knowledge +crew.reset_memories(command_type='agent_knowledge') + +# Reset both crew and agent knowledge +crew.reset_memories(command_type='knowledge') + +# CLI commands +# crewai reset-memories --agent-knowledge # Agent knowledge only +# crewai reset-memories --knowledge # All knowledge +``` + +### مسح المعرفة + +إذا كنت بحاجة إلى مسح المعرفة المخزّنة في CrewAI، يمكنك استخدام أمر `crewai reset-memories` مع خيار `--knowledge`. + +```bash Command +crewai reset-memories --knowledge +``` + +هذا مفيد عندما تكون قد حدّثت مصادر المعرفة وتريد التأكد من أن الوكلاء يستخدمون أحدث المعلومات. + +## أفضل الممارسات + + + + - حافظ على أحجام القطع مناسبة لنوع المحتوى + - ضع في اعتبارك تداخل المحتوى للحفاظ على السياق + - نظّم المعلومات ذات الصلة في مصادر معرفة منفصلة + + + + - اضبط أحجام القطع بناءً على تعقيد المحتوى + - أعدّ نماذج تضمين مناسبة + - ضع في اعتبارك استخدام مزودي تضمين محليين لمعالجة أسرع + + + + - مع هيكل الملفات النموذجي الذي يوفره CrewAI، يتم تضمين مصادر المعرفة في كل مرة يتم فيها تشغيل kickoff. + - إذا كانت مصادر المعرفة كبيرة، فإن هذا يؤدي إلى عدم كفاءة وزيادة وقت الاستجابة، حيث يتم تضمين نفس البيانات في كل مرة. + - لحل هذه المشكلة، قم بتهيئة معامل knowledge مباشرة بدلاً من معامل knowledge_sources. + - رابط للمشكلة للحصول على فكرة كاملة [Github Issue](https://github.com/crewAIInc/crewAI/issues/2755) + + + + - استخدم المعرفة على مستوى Agent للمعلومات الخاصة بالدور + - استخدم المعرفة على مستوى Crew للمعلومات المشتركة التي يحتاجها جميع الوكلاء + - عيّن المُضمّنات على مستوى Agent إذا كنت بحاجة إلى استراتيجيات تضمين مختلفة + - استخدم تسمية مجموعات متسقة بالحفاظ على أدوار Agent وصفية + - اختبر تهيئة المعرفة بالتحقق من agent.knowledge بعد kickoff + - راقب مواقع التخزين لفهم أين يتم تخزين المعرفة + - أعد تعيين المعرفة بشكل مناسب باستخدام أنواع الأوامر الصحيحة + + + + - عيّن `CREWAI_STORAGE_DIR` إلى موقع معروف في الإنتاج + - اختر مزودي تضمين صريحين ليتوافقوا مع إعداد LLM وتجنب تعارضات مفاتيح API + - راقب حجم تخزين المعرفة مع نموه مع إضافات المستندات + - نظّم مصادر المعرفة حسب المجال أو الغرض باستخدام أسماء المجموعات + - ضمّن مجلدات المعرفة في استراتيجيات النسخ الاحتياطي والنشر + - عيّن أذونات ملفات مناسبة لملفات المعرفة ومجلدات التخزين + - استخدم متغيرات البيئة لمفاتيح API والإعدادات الحساسة + + diff --git a/docs/v1.15.13/ar/concepts/llms.mdx b/docs/v1.15.13/ar/concepts/llms.mdx new file mode 100644 index 0000000000..a2b3d9653a --- /dev/null +++ b/docs/v1.15.13/ar/concepts/llms.mdx @@ -0,0 +1,1352 @@ +--- +title: 'نماذج اللغة الكبيرة (LLMs)' +description: 'دليل شامل لإعداد واستخدام نماذج اللغة الكبيرة (LLMs) في مشاريع CrewAI' +icon: 'microchip-ai' +mode: "wide" +--- + +## نظرة عامة + +يتكامل CrewAI مع مزودي LLM متعددين من خلال حزم SDK الأصلية للمزودين، مما يمنحك المرونة لاختيار النموذج المناسب لحالة الاستخدام الخاصة بك. سيساعدك هذا الدليل على فهم كيفية إعداد واستخدام مزودي LLM المختلفين في مشاريع CrewAI. + + +## ما هي نماذج اللغة الكبيرة؟ + +نماذج اللغة الكبيرة (LLMs) هي الذكاء الأساسي وراء وكلاء CrewAI. تمكّن الوكلاء من فهم السياق واتخاذ القرارات وتوليد استجابات شبيهة بالبشر. إليك ما تحتاج معرفته: + + + + نماذج اللغة الكبيرة هي أنظمة ذكاء اصطناعي مدربة على كميات هائلة من البيانات النصية. تدعم ذكاء وكلاء CrewAI، مما يمكّنهم من فهم وتوليد نصوص شبيهة بالبشر. + + + تحدد نافذة السياق مقدار النص الذي يمكن لـ LLM معالجته في وقت واحد. النوافذ الأكبر (مثل 128K رمز) تتيح سياقًا أكثر لكنها قد تكون أكثر تكلفة وأبطأ. + + + درجة الحرارة هي أداة للتحكم في أخذ العينات تدعمها بعض النماذج. تجعل القيم المنخفضة أخذ العينات أكثر تركيزًا عمومًا، بينما تزيد القيم الأعلى التباين. تتجاهل بعض نماذج الاستدلال الأحدث هذا المعامل أو توقف دعمه أو ترفضه، لذا راجع وثائق النموذج المحدد قبل ضبطه. + + + يقدم كل مزود LLM (مثل OpenAI و Anthropic و Google) نماذج مختلفة بقدرات وأسعار وميزات متفاوتة. اختر بناءً على احتياجاتك من الدقة والسرعة والتكلفة. + + + +## إعداد LLM الخاص بك + +هناك أماكن مختلفة في كود CrewAI حيث يمكنك تحديد النموذج المُستخدم. بمجرد تحديد النموذج، ستحتاج إلى توفير الإعداد (مثل مفتاح API) لكل مزود نموذج تستخدمه. انظر قسم [أمثلة إعداد المزودين](#أمثلة-إعداد-المزودين) لمزودك. + + + + أبسط طريقة للبدء. عيّن النموذج في بيئتك مباشرة، من خلال ملف `.env` أو في كود تطبيقك. إذا استخدمت `crewai create` لبدء مشروعك، سيكون مُعيّنًا بالفعل. + + ```bash .env + MODEL=provider/model-id # e.g. openai/gpt-5.6-terra + + # Be sure to set your API keys here too. See the Provider + # section below. + ``` + + + لا تقم أبدًا بتأكيد مفاتيح API في التحكم بالإصدارات. استخدم ملفات البيئة (.env) أو إدارة أسرار نظامك. + + + + أنشئ ملف YAML لتعريف إعدادات الوكلاء. هذه الطريقة رائعة للتحكم بالإصدارات والتعاون بين الفريق: + + ```yaml agents.yaml {6} + researcher: + role: Research Specialist + goal: Conduct comprehensive research and analysis + backstory: A dedicated research professional with years of experience + verbose: true + llm: provider/model-id # e.g. anthropic/claude-sonnet-4-6 + # (see provider configuration examples below for more) + ``` + + + يتيح لك إعداد YAML: + - التحكم بإصدارات إعدادات الوكلاء + - التبديل بسهولة بين النماذج المختلفة + - مشاركة الإعدادات بين أعضاء الفريق + - توثيق خيارات النماذج وأغراضها + + + + لأقصى مرونة، أعدّ LLMs مباشرة في كود Python: + + ```python {4,8} + from crewai import LLM + + # Basic configuration + llm = LLM(model="provider/model-id") # e.g. gemini/gemini-3.6-flash + + # Advanced configuration with detailed parameters + llm = LLM( + model="provider/model-id", + timeout=120, + max_tokens=4000, + response_format={"type": "json"}, # For structured outputs + ) + ``` + + + شرح المعاملات: + - `timeout`: أقصى وقت انتظار للاستجابة + - `max_tokens`: تحدد طول الاستجابة + - `response_format`: تحدد هيكل المخرجات + + عناصر التحكم في أخذ العينات مثل `temperature` و`top_p`، ومعاملات العقوبة، وأسماء حدود الرموز، وعناصر التحكم في الاستدلال خاصة بكل نموذج. أضفها فقط عندما يدعمها المزود والنموذج المحددان. راجع أمثلة المزودين أدناه ووثائق النموذج لدى المزود. + + + + + + يوفر CrewAI تكاملات SDK أصلية لـ OpenAI و Anthropic و Google (Gemini API) و Azure و AWS Bedrock و Snowflake Cortex -- لا حاجة لتثبيت إضافي بخلاف الملحقات الخاصة بالمزود (مثل `uv add "crewai[openai]"`). + + جميع المزودين الآخرين مدعومون بواسطة **LiteLLM**. إذا كنت تخطط لاستخدام أي منهم، أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + +## أمثلة إعداد المزودين + +يدعم CrewAI العديد من مزودي LLM، كل منهم يقدم ميزات فريدة وطرق مصادقة وقدرات نماذج. +في هذا القسم، ستجد أمثلة مفصلة تساعدك في اختيار وإعداد وتحسين LLM الأنسب لاحتياجات مشروعك. + + + يتغير توفر النماذج باستمرار وقد يختلف حسب الحساب والمنطقة والمنصة السحابية. تستخدم الأمثلة أدناه نماذج متاحة وقت كتابة هذا الدليل، لكنها ليست قوائم دعم شاملة. قبل النشر، تحقق من معرّف النموذج وحالة دورة حياته في كتالوج المزود المرتبط. + + + + + يوفر CrewAI تكاملًا أصليًا مع OpenAI من خلال OpenAI Python SDK. + + ```toml Code + # Required + OPENAI_API_KEY=sk-... + + # Optional + OPENAI_BASE_URL= + ``` + + **الاستخدام الأساسي:** + ```python Code + from crewai import LLM + + llm = LLM( + model="openai/gpt-5.6-terra", + api_key="your-api-key", # Or set OPENAI_API_KEY + reasoning_effort="medium", + max_completion_tokens=4000 + ) + ``` + + **الإعداد المتقدم:** + ```python Code + from crewai import LLM + + llm = LLM( + model="openai/gpt-5.6-terra", + api_key="your-api-key", + base_url="https://api.openai.com/v1", # Optional custom endpoint + organization="org-...", # Optional organization ID + project="proj_...", # Optional project ID + max_completion_tokens=4000, + reasoning_effort="medium", + stream=True, # Enable streaming + timeout=60.0, # Request timeout in seconds + max_retries=3 # Maximum retry attempts + ) + ``` + + **المخرجات المهيكلة:** + ```python Code + from pydantic import BaseModel + from crewai import LLM + + class ResponseFormat(BaseModel): + name: str + age: int + summary: str + + llm = LLM( + model="openai/gpt-5.6-terra", + ) + ``` + + **متغيرات البيئة المدعومة:** + - `OPENAI_API_KEY`: مفتاح OpenAI API (مطلوب) + - `OPENAI_BASE_URL`: عنوان URL مخصص لـ OpenAI API (اختياري) + + **الميزات:** + - دعم أصلي لاستدعاء الدوال + - مخرجات منظمة مع JSON schema + - دعم البث للاستجابات في الوقت الفعلي + - تتبع استخدام الرموز + - عناصر تحكم في التوليد خاصة بالمزود + - احتمالات السجل لرؤى على مستوى الرموز + - التحكم في جهد الاستدلال للنماذج المتوافقة + + تضيف OpenAI نماذج جديدة وتسحب snapshots قديمة بانتظام. راجع [كتالوج نماذج OpenAI](https://developers.openai.com/api/docs/models) للحصول على معرّفات النماذج الحالية ونوافذ السياق وتوافق endpoints ومعلومات دورة الحياة. + + **Responses API:** + + تقدم OpenAI واجهتي API: Chat Completions (الافتراضية) و Responses API الأحدث. تم تصميم Responses API من الأساس مع دعم أصلي متعدد الوسائط -- النص والصور والصوت واستدعاءات الدوال كلها مكوّنات أساسية. توفر أداءً أفضل مع نماذج الاستدلال وتدعم ميزات إضافية مثل السلسلة التلقائية والأدوات المدمجة. + + ```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:** + - `api`: عيّن إلى `"responses"` لاستخدام Responses API (الافتراضي: `"completions"`) + - `instructions`: تعليمات على مستوى النظام (Responses API فقط) + - `store`: ما إذا كان يجب تخزين الاستجابات للمحادثات متعددة الأدوار + - `previous_response_id`: معرّف الاستجابة السابقة للمحادثات متعددة الأدوار + - `include`: بيانات إضافية لتضمينها في الاستجابة (مثل `["reasoning.encrypted_content"]`) + - `builtin_tools`: قائمة أدوات OpenAI المدمجة: `"web_search"`, `"file_search"`, `"code_interpreter"`, `"computer_use"` + - `parse_tool_outputs`: إعادة `ResponsesAPIResult` منظمة مع مخرجات أدوات مدمجة محللة + - `auto_chain`: تتبع واستخدام معرّفات الاستجابة تلقائيًا للمحادثات متعددة الأدوار + - `auto_chain_reasoning`: تتبع عناصر الاستدلال المشفرة للامتثال لـ ZDR + + + استخدم Responses API للمشاريع الجديدة، خاصة عند العمل مع نماذج الاستدلال (o1, o3, o4) أو عندما تحتاج دعمًا أصليًا متعدد الوسائط لـ [الملفات](/ar/concepts/files). + + + **ملاحظة:** لاستخدام OpenAI، ثبّت التبعيات المطلوبة: + ```bash + uv add "crewai[openai]" + ``` + + + + توفر Meta Llama API الوصول إلى عائلة نماذج اللغة الكبيرة من Meta. + الـ API متاحة عبر [Meta Llama API](https://llama.developer.meta.com?utm_source=partner-crewai&utm_medium=website). + عيّن متغيرات البيئة التالية في ملف `.env`: + + ```toml Code + # Meta Llama API Key Configuration + LLAMA_API_KEY=LLM|your_api_key_here + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + from crewai import LLM + + # Initialize Meta Llama LLM + llm = LLM( + model="meta_llama/Llama-4-Scout-17B-16E-Instruct-FP8", + temperature=0.8, + stop=["END"], + seed=42 + ) + ``` + + راجع [نظرة عامة على نماذج Meta Llama](https://ai.meta.com/llama/get-started/) للتعرّف على عائلات النماذج والوسائط وإرشادات حدود السياق الحالية. + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + يوفر CrewAI تكاملًا أصليًا مع Snowflake Cortex REST API عبر endpoint Chat Completions المتوافق مع OpenAI. تستخدم نماذج `snowflake/...` هذا المسار بدون fallback إلى LiteLLM. يدعم Snowflake Cortex في CrewAI حاليًا Chat Completions فقط، لذلك استخدم وضع `api` الافتراضي ولا تضبط `api="responses"`. + + ```toml Code + # Required + SNOWFLAKE_PAT= + SNOWFLAKE_ACCOUNT_URL=https://.snowflakecomputing.com + + # Alternative account configuration + SNOWFLAKE_ACCOUNT= + ``` + + **الاستخدام الأساسي:** + ```python Code + from crewai import LLM + + llm = LLM( + model="snowflake/openai-gpt-4.1", + temperature=0.7, + max_completion_tokens=1024, + ) + ``` + + **نماذج Claude على Cortex:** + ```python Code + from crewai import LLM + + llm = LLM( + model="snowflake/claude-sonnet-4-5", + max_completion_tokens=1024, + stream=True, + ) + ``` + + **متغيرات البيئة المدعومة:** + - `SNOWFLAKE_PAT` أو `SNOWFLAKE_TOKEN` أو `SNOWFLAKE_JWT`: الرمز المستخدم كاعتماد Bearer + - `SNOWFLAKE_ACCOUNT_URL`: عنوان URL الكامل لحساب Snowflake + - `SNOWFLAKE_ACCOUNT` أو `SNOWFLAKE_ACCOUNT_ID` أو `SNOWFLAKE_ACCOUNT_IDENTIFIER`: معرف الحساب المستخدم لبناء URL + + تستخدم طلبات Snowflake REST الدور الافتراضي للمستخدم. تأكد من أن هذا الدور لديه `SNOWFLAKE.CORTEX_USER` أو `SNOWFLAKE.CORTEX_REST_API_USER`. لا يتطلب endpoint Cortex REST Chat Completions معاملات database أو schema أو warehouse أو role صريح. + + **الميزات:** + - اختيار provider أصلي باستخدام `model="snowflake/"` + - Chat Completions مع streaming وبدونه فقط؛ `api="responses"` غير مدعوم + - تتبع استخدام الرموز + - استدعاء الدوال لنماذج OpenAI و Claude المستضافة في Snowflake + - إزالة assistant prefill النهائي غير الصالح تلقائيًا لنماذج Claude في Snowflake + + + + يوفر CrewAI تكاملًا أصليًا مع Anthropic من خلال Anthropic Python SDK. + + ```toml Code + # Required + ANTHROPIC_API_KEY=sk-ant-... + ``` + + **الاستخدام الأساسي:** + ```python Code + from crewai import LLM + + llm = LLM( + model="anthropic/claude-sonnet-4-6", + api_key="your-api-key", # Or set ANTHROPIC_API_KEY + max_tokens=4096 # Required for Anthropic + ) + ``` + + **الإعداد المتقدم:** + ```python Code + from crewai import LLM + + llm = LLM( + model="anthropic/claude-sonnet-4-6", + api_key="your-api-key", + base_url="https://api.anthropic.com", # Optional custom endpoint + max_tokens=4096, # Required parameter + stop_sequences=["END", "STOP"], # Anthropic uses stop_sequences + stream=True, # Enable streaming + timeout=60.0, # Request timeout in seconds + max_retries=3 # Maximum retry attempts + ) + ``` + + **التفكير الموسّع:** + + يدعم CrewAI ميزة التفكير الموسّع من Anthropic، التي تتيح لـ Claude التفكير في المشكلات بطريقة أكثر شبهًا بالبشر قبل الاستجابة. مفيد بشكل خاص لمهام الاستدلال والتحليل وحل المشكلات المعقدة. + + ```python Code + from crewai import LLM + + # Enable extended thinking with default settings + llm = LLM( + model="anthropic/claude-sonnet-4-6", + thinking={"type": "enabled"}, + max_tokens=10000 + ) + + # Configure thinking with budget control + llm = LLM( + model="anthropic/claude-sonnet-4-6", + thinking={ + "type": "enabled", + "budget_tokens": 5000 # Limit thinking tokens + }, + max_tokens=10000 + ) + ``` + + **خيارات إعداد التفكير:** + - `type`: عيّن إلى `"enabled"` لتفعيل وضع التفكير الموسّع + - `budget_tokens` (اختياري): أقصى رموز للتفكير (يساعد في التحكم بالتكاليف) + + تختلف أوضاع التفكير والمعاملات المقبولة بين أجيال Claude. تحقق من قدرات النموذج المحدد قبل تفعيل `thinking`. + + **متى تستخدم التفكير الموسّع:** + - الاستدلال المعقد وحل المشكلات متعددة الخطوات + - الحسابات الرياضية والبراهين + - تحليل الكود وتصحيح الأخطاء + - التخطيط الاستراتيجي واتخاذ القرارات + - البحث والمهام التحليلية + + **ملاحظة:** يستهلك التفكير الموسّع رموزًا إضافية لكنه يمكن أن يحسّن جودة الاستجابة بشكل كبير للمهام المعقدة. + + **متغيرات البيئة المدعومة:** + - `ANTHROPIC_API_KEY`: مفتاح Anthropic API (مطلوب) + + **الميزات:** + - دعم استخدام الأدوات الأصلي لنماذج Claude 3+ + - دعم التفكير الموسّع لنماذج Claude المتوافقة + - دعم البث للاستجابات في الوقت الفعلي + - معالجة تلقائية لرسائل النظام + - تسلسلات التوقف للتحكم في المخرجات + - تتبع استخدام الرموز + - محادثات استخدام أدوات متعددة الأدوار + + **استخدام الرموز والتخزين المؤقت للمطالبة:** + + يُبلّغ Anthropic عن الإدخال المفوتر في عدادات منفصلة — `input_tokens` (غير المخزن مؤقتًا)، و`cache_read_input_tokens`، و`cache_creation_input_tokens`. يدمج CrewAI الثلاثة ضمن `prompt_tokens` (و`input_tokens` الأصلي في استجابات المزود) بحيث يعكس `total_tokens` الاستخدام المفوتر الكامل على أعباء العمل المخزنة مؤقتًا. + + يسجّل `cached_prompt_tokens` جزء قراءة الذاكرة المؤقتة كتفصيل فقط؛ وهو مُدرج بالفعل ضمن `prompt_tokens` ولا يجب إضافته مرة أخرى إلى `total_tokens`. يسجّل `cache_creation_tokens` عمليات الكتابة في الذاكرة المؤقتة بنفس الطريقة. + + ```python Code + usage = llm.get_token_usage_summary() + # total_tokens == prompt_tokens + completion_tokens + # prompt_tokens includes cache read + cache write for Anthropic + ``` + + راجع قسم **UsageMetrics field semantics** في توثيق مفهوم Flows + للحصول على العقد المحايد للمزود المستخدم في `crew.usage_metrics` + و`flow.usage_metrics`. + + **ملاحظات مهمة:** + - `max_tokens` معامل **مطلوب** لجميع نماذج Anthropic + - يستخدم Claude `stop_sequences` بدلاً من `stop` + - يتم التعامل مع رسائل النظام بشكل منفصل عن رسائل المحادثة + - يجب أن تكون الرسالة الأولى من المستخدم (يتم التعامل معها تلقائيًا) + - يجب أن تتناوب الرسائل بين المستخدم والمساعد + + راجع [نظرة عامة على نماذج Anthropic](https://platform.claude.com/docs/en/about-claude/models/overview) للحصول على معرّفات النماذج وقدراتها الحالية، وراجع [جدول إيقاف النماذج](https://platform.claude.com/docs/en/about-claude/model-deprecations) قبل تثبيت نموذج في الإنتاج. + + **ملاحظة:** لاستخدام Anthropic، ثبّت التبعيات المطلوبة: + ```bash + uv add "crewai[anthropic]" + ``` + + + + يوفر CrewAI تكاملًا أصليًا مع Google Gemini من خلال Google Gen AI Python SDK. + + عيّن مفتاح API في ملف `.env`. إذا كنت بحاجة إلى مفتاح، تحقق من [AI Studio](https://aistudio.google.com/apikey). + + ```toml .env + # Required (one of the following) + GOOGLE_API_KEY= + GEMINI_API_KEY= + + # For Vertex AI Express mode (API key authentication) + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_API_KEY= + + # For Vertex AI with service account + GOOGLE_CLOUD_PROJECT= + GOOGLE_CLOUD_LOCATION= # Defaults to us-central1 + ``` + + **الاستخدام الأساسي:** + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash", + api_key="your-api-key", # Or set GOOGLE_API_KEY/GEMINI_API_KEY + ) + ``` + + **الإعداد المتقدم:** + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash", + api_key="your-api-key", + max_output_tokens=8192, + stop_sequences=["END", "STOP"], + stream=True, # Enable streaming + safety_settings={ + "HARM_CATEGORY_HARASSMENT": "BLOCK_NONE", + "HARM_CATEGORY_HATE_SPEECH": "BLOCK_NONE" + } + ) + ``` + + **وضع Vertex AI Express (مصادقة بمفتاح API):** + + يتيح لك وضع Vertex AI Express استخدام Vertex AI مع مصادقة بسيطة بمفتاح API بدلاً من بيانات اعتماد حساب الخدمة. هذه أسرع طريقة للبدء مع Vertex AI. + + لتفعيل وضع Express، عيّن متغيري البيئة في ملف `.env`: + ```toml .env + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_API_KEY= + ``` + + ثم استخدم LLM كالمعتاد: + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash" + ) + ``` + + + للحصول على مفتاح API لوضع Express: + - مستخدمو Google Cloud الجدد: احصل على [مفتاح API لوضع Express](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). + + + **إعداد Vertex AI (حساب خدمة):** + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash", + project="your-gcp-project-id", + location="us-central1" # GCP region + ) + ``` + + **متغيرات البيئة المدعومة:** + - `GOOGLE_API_KEY` أو `GEMINI_API_KEY`: مفتاح Google API (مطلوب لـ Gemini API ووضع Vertex AI Express) + - `GOOGLE_GENAI_USE_VERTEXAI`: عيّن إلى `true` لاستخدام Vertex AI (مطلوب لوضع Express) + - `GOOGLE_CLOUD_PROJECT`: معرّف مشروع Google Cloud (لـ Vertex AI مع حساب خدمة) + - `GOOGLE_CLOUD_LOCATION`: موقع GCP (الافتراضي `us-central1`) + + **الميزات:** + - دعم أصلي لاستدعاء الدوال لنماذج Gemini المتوافقة + - دعم البث للاستجابات في الوقت الفعلي + - قدرات متعددة الوسائط (نص، صور، فيديو) + - إعداد إعدادات الأمان + - دعم لكل من Gemini API و Vertex AI + - معالجة تلقائية لتعليمات النظام + - تتبع استخدام الرموز + + تنشر Google معرّفات Gemini الحالية وقدراتها ومراحل دورة حياتها في [كتالوج نماذج Gemini](https://ai.google.dev/gemini-api/docs/models). تحقق من [جدول الإيقاف](https://ai.google.dev/gemini-api/docs/deprecations) قبل اختيار نموذج مستقر أو preview. وتستضيف Gemini API أيضًا [نماذج Gemma](https://ai.google.dev/gemma/docs). + + **ملاحظة:** لاستخدام Google Gemini، ثبّت التبعيات المطلوبة: + ```bash + uv add "crewai[google-genai]" + ``` + + + + + صادِق باستخدام [بيانات الاعتماد التلقائية للتطبيق](https://cloud.google.com/docs/authentication/provide-credentials-adc)، ثم اضبط مزود Gemini الأصلي لاستخدام Vertex AI: + ```toml .env + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_CLOUD_PROJECT= + GOOGLE_CLOUD_LOCATION= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash" + ) + ``` + + تختلف إتاحة Vertex AI باختلاف المنطقة. استخدم [كتالوج نماذج Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models) للتحقق من معرّف النموذج والمنطقة قبل النشر. + + **ملاحظة:** يستخدم هذا المسار تكامل Gemini الأصلي في CrewAI. أضفه كتبعية لمشروعك: + ```bash + uv add "crewai[google-genai]" + ``` + + + + يوفر CrewAI تكاملًا أصليًا مع Azure AI Inference و Azure OpenAI من خلال Azure AI Inference Python SDK. + + ```toml Code + # Required + AZURE_API_KEY= + AZURE_ENDPOINT= + + # Optional + AZURE_API_VERSION= # Defaults to 2024-06-01 + ``` + + **الاستخدام الأساسي:** + ```python Code + llm = LLM( + model="azure/gpt-4", + api_key="", # Or set AZURE_API_KEY + endpoint="", + api_version="2024-06-01" + ) + ``` + + **ملاحظة:** لاستخدام Azure AI Inference، ثبّت التبعيات المطلوبة: + ```bash + uv add "crewai[azure-ai-inference]" + ``` + + + + يوفر CrewAI تكاملًا أصليًا مع AWS Bedrock من خلال boto3 SDK باستخدام Converse API. + + ```toml Code + # Required + AWS_ACCESS_KEY_ID= + AWS_SECRET_ACCESS_KEY= + + # Optional + AWS_SESSION_TOKEN= # For temporary credentials + AWS_DEFAULT_REGION= # Defaults to us-east-1 + AWS_REGION_NAME= # Alternative configuration for backwards compatibility with LiteLLM. Defaults to us-east-1 + ``` + + **الاستخدام الأساسي:** + ```python Code + from crewai import LLM + + llm = LLM( + model="bedrock/us.anthropic.claude-sonnet-4-6", + region_name="us-east-1" + ) + ``` + + **الإعداد المتقدم:** + ```python Code + from crewai import LLM + + llm = LLM( + model="bedrock/us.anthropic.claude-sonnet-4-6", + aws_access_key_id="your-access-key", # Or set AWS_ACCESS_KEY_ID + aws_secret_access_key="your-secret-key", # Or set AWS_SECRET_ACCESS_KEY + aws_session_token="your-session-token", # For temporary credentials + region_name="us-east-1", + temperature=0.7, + max_tokens=4096, + top_p=0.9, + top_k=250, # For Claude models + stop_sequences=["END", "STOP"], + stream=True, # Enable streaming + guardrail_config={ # Optional content filtering + "guardrailIdentifier": "your-guardrail-id", + "guardrailVersion": "1" + }, + additional_model_request_fields={ # Model-specific parameters + "top_k": 250 + } + ) + ``` + + **متغيرات البيئة المدعومة:** + - `AWS_ACCESS_KEY_ID`: مفتاح وصول AWS (مطلوب) + - `AWS_SECRET_ACCESS_KEY`: مفتاح AWS السري (مطلوب) + - `AWS_SESSION_TOKEN`: رمز جلسة AWS لبيانات الاعتماد المؤقتة (اختياري) + - `AWS_DEFAULT_REGION`: منطقة AWS (الافتراضي `us-east-1`) + - `AWS_REGION_NAME`: منطقة AWS (الافتراضي `us-east-1`). إعداد بديل للتوافق مع LiteLLM + + **الميزات:** + - دعم استدعاء الأدوات الأصلي عبر Converse API + - استجابات بث وبدون بث + - معالجة أخطاء شاملة مع منطق إعادة المحاولة + - إعداد حواجز الحماية لتصفية المحتوى + - معاملات خاصة بالنموذج عبر `additional_model_request_fields` + - تتبع استخدام الرموز وتسجيل سبب التوقف + - دعم جميع نماذج Bedrock الأساسية + - معالجة تلقائية لتنسيق المحادثة + + **ملاحظات مهمة:** + - يستخدم Converse API الحديث للوصول الموحد للنماذج + - معالجة تلقائية لمتطلبات المحادثة الخاصة بالنموذج + - يتم التعامل مع رسائل النظام بشكل منفصل عن المحادثة + - يجب أن تكون الرسالة الأولى من المستخدم (يتم التعامل معها تلقائيًا) + - بعض النماذج (مثل Cohere) تتطلب أن تنتهي المحادثة برسالة المستخدم + + تختلف إتاحة نماذج Amazon Bedrock ومعرّفاتها باختلاف المنطقة. استخدم مرجع + [النماذج والمناطق المدعومة](https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html) + لاختيار نموذج والتحقق من دعم Converse API. + + **ملاحظة:** لاستخدام AWS Bedrock، ثبّت التبعيات المطلوبة: + ```bash + uv add "crewai[bedrock]" + ``` + + + + ```toml Code + AWS_ACCESS_KEY_ID= + AWS_SECRET_ACCESS_KEY= + AWS_DEFAULT_REGION= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="sagemaker/" + ) + ``` + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + MISTRAL_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="mistral/mistral-large-latest", + temperature=0.7 + ) + ``` + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + NVIDIA_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="nvidia_nim/nvidia/nvidia-nemotron-3-ultra-550b-a55b", + temperature=0.7 + ) + ``` + + يتغير كتالوج NVIDIA NIM المستضاف باستمرار. استخدم [كتالوج نماذج NVIDIA NIM](https://build.nvidia.com/models) لاختيار endpoint حالي والتحقق من معرّف النموذج والوسائط وحدود السياق. + + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + + يتيح لك NVIDIA NIM تشغيل نماذج LLM قوية محليًا على جهاز Windows باستخدام WSL2 (نظام Windows الفرعي لـ Linux). + يتيح لك هذا النهج الاستفادة من وحدة GPU من NVIDIA لاستدلال ذكاء اصطناعي خاص وآمن وفعال من حيث التكلفة دون الاعتماد على الخدمات السحابية. + مثالي لسيناريوهات التطوير والاختبار أو الإنتاج حيث تكون خصوصية البيانات أو القدرات غير المتصلة مطلوبة. + + إليك دليلًا خطوة بخطوة لإعداد نموذج NVIDIA NIM محلي: + + 1. اتبع تعليمات التثبيت من [موقع NVIDIA](https://docs.nvidia.com/nim/wsl2/latest/getting-started.html) + + 2. ثبّت النموذج المحلي. لـ Llama 3.1-8b اتبع [التعليمات](https://build.nvidia.com/meta/llama-3_1-8b-instruct/deploy) + + 3. أعدّ نماذج crewai المحلية: + + ```python Code + from crewai.llm import LLM + + local_nvidia_nim_llm = LLM( + model="openai/meta/llama-3.1-8b-instruct", # it's an openai-api compatible model + base_url="http://localhost:8000/v1", + api_key="", # api_key is required, but you can use any text + ) + + # Then you can use it in your crew: + + @CrewBase + class MyCrew(): + # ... + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], # type: ignore[index] + llm=local_nvidia_nim_llm + ) + + # ... + ``` + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + + ```toml Code + GROQ_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="groq/qwen/qwen3.6-27b", + temperature=0.7 + ) + ``` + + تميز Groq بين نماذج production وpreview وتسحب معرّفات النماذج بانتظام. تحقق من [كتالوج نماذج Groq](https://console.groq.com/docs/models) و[صفحة الإيقاف](https://console.groq.com/docs/deprecations) قبل اختيار نموذج للإنتاج. + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + # Required + WATSONX_URL= + WATSONX_APIKEY= + WATSONX_PROJECT_ID= + + # Optional + WATSONX_TOKEN= + WATSONX_DEPLOYMENT_SPACE_ID= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="watsonx/meta-llama/llama-3-1-70b-instruct", + base_url="https://api.watsonx.ai/v1" + ) + ``` + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + 1. ثبّت Ollama: [ollama.ai](https://ollama.ai/) + 2. شغّل نموذجًا: `ollama run llama3` + 3. أعدّ: + + ```python Code + llm = LLM( + model="ollama/llama3:70b", + base_url="http://localhost:11434" + ) + ``` + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + FIREWORKS_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="fireworks_ai/accounts/fireworks/models/llama-v3-70b-instruct", + temperature=0.7 + ) + ``` + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + PERPLEXITY_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="perplexity/sonar-pro" + ) + ``` + + راجع [كتالوج نماذج Perplexity](https://docs.perplexity.ai/getting-started/models) و[changelog](https://docs.perplexity.ai/docs/resources/changelog) للحصول على معرّفات النماذج الحالية وإشعارات الإيقاف. + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + HF_TOKEN= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct" + ) + ``` + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + + ```toml Code + SAMBANOVA_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="sambanova/Meta-Llama-3.3-70B-Instruct", + temperature=0.7 + ) + ``` + + قد تتغير النماذج المستضافة في SambaNova Cloud بصورة مستقلة عن CrewAI. استعلم من [models endpoint](https://docs.sambanova.ai/docs/api-reference/models/get-environments-available-model-list-metadata) وراجع [دليل الإيقاف](https://docs.sambanova.ai/docs/en/models/deprecations) قبل النشر. + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + # Required + CEREBRAS_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="cerebras/gpt-oss-120b", + temperature=0.7, + max_tokens=8192 + ) + ``` + + + ميزات Cerebras: + - سرعات استدلال عالية + - أسعار تنافسية + - توازن جيد بين السرعة والجودة + - دعم نوافذ سياق طويلة + + + راجع [كتالوج نماذج Cerebras](https://inference-docs.cerebras.ai/models/overview) و[إشعارات الإيقاف](https://inference-docs.cerebras.ai/support/deprecation) للحصول على معرّفات endpoints العامة الحالية. + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + OPENROUTER_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="openrouter/deepseek/deepseek-r1", + base_url="https://openrouter.ai/api/v1", + api_key=OPENROUTER_API_KEY + ) + ``` + + + نماذج Open Router: + - openrouter/deepseek/deepseek-r1 + - openrouter/deepseek/deepseek-chat + + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + + عيّن متغيرات البيئة التالية في ملف `.env`: + ```toml Code + NEBIUS_API_KEY= + ``` + + مثال الاستخدام في مشروع CrewAI: + ```python Code + llm = LLM( + model="nebius/Qwen/Qwen3-30B-A3B" + ) + ``` + + + ميزات Nebius AI Studio: + - مجموعة كبيرة من النماذج مفتوحة المصدر + - حدود معدل أعلى + - أسعار تنافسية + - توازن جيد بين السرعة والجودة + + + **ملاحظة:** يستخدم هذا المزود LiteLLM. أضفه كتبعية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + + + +## بث الاستجابات + +يدعم CrewAI بث الاستجابات من LLMs، مما يتيح لتطبيقك تلقي ومعالجة المخرجات في الوقت الفعلي فور توليدها. + + + + فعّل البث بتعيين معامل `stream` إلى `True` عند تهيئة LLM: + + ```python + from crewai import LLM + + # Create an LLM with streaming enabled + llm = LLM( + model="openai/gpt-5.6-terra", + stream=True # Enable streaming + ) + ``` + + عند تفعيل البث، يتم تسليم الاستجابات في أجزاء فور توليدها، مما يخلق تجربة مستخدم أكثر استجابة. + + + + يُصدر CrewAI أحداثًا لكل جزء يتم تلقيه أثناء البث: + + ```python + from crewai.events import ( + LLMStreamChunkEvent + ) + from crewai.events import BaseEventListener + + class MyCustomListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(LLMStreamChunkEvent) + def on_llm_stream_chunk(self, event: LLMStreamChunkEvent): + # Process each chunk as it arrives + print(f"Received chunk: {event.chunk}") + + my_listener = MyCustomListener() + ``` + + + [انقر هنا](/ar/concepts/event-listener#event-listeners) لمزيد من التفاصيل + + + + + جميع أحداث LLM في CrewAI تتضمن معلومات Agent والمهمة، مما يتيح لك تتبع وتصفية تفاعلات LLM بواسطة وكلاء أو مهام محددة: + + ```python + from crewai import LLM, Agent, Task, Crew + from crewai.events import LLMStreamChunkEvent + from crewai.events import BaseEventListener + + class MyCustomListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(LLMStreamChunkEvent) + def on_llm_stream_chunk(source, event): + if researcher.id == event.agent_id: + print("\n==============\n Got event:", event, "\n==============\n") + + + my_listener = MyCustomListener() + + llm = LLM(model="openai/gpt-5.6-terra", stream=True) + + researcher = Agent( + role="About User", + goal="You know everything about the user.", + backstory="""You are a master at understanding people and their preferences.""", + llm=llm, + ) + + search = Task( + description="Answer the following questions about the user: {question}", + expected_output="An answer to the question.", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[search]) + + result = crew.kickoff( + inputs={"question": "..."} + ) + ``` + + + هذه الميزة مفيدة بشكل خاص لـ: + - تصحيح سلوكيات وكلاء محددة + - تسجيل استخدام LLM حسب نوع المهمة + - مراجعة أي الوكلاء يجرون أنواع استدعاءات LLM + - مراقبة أداء مهام محددة + + + + +## استدعاءات LLM غير المتزامنة + +يدعم CrewAI استدعاءات LLM غير المتزامنة لأداء وتزامن محسّنين في سير عمل الذكاء الاصطناعي. تتيح لك الاستدعاءات غير المتزامنة تشغيل طلبات LLM متعددة بشكل متزامن دون حجب، مما يجعلها مثالية لتطبيقات الإنتاجية العالية وعمليات الوكلاء المتوازية. + + + + استخدم دالة `acall` لطلبات LLM غير المتزامنة: + + ```python + import asyncio + from crewai import LLM + + async def main(): + llm = LLM(model="openai/gpt-4o") + + # Single async call + response = await llm.acall("What is the capital of France?") + print(response) + + asyncio.run(main()) + ``` + + تدعم دالة `acall` جميع المعاملات نفسها كدالة `call` المتزامنة، بما في ذلك الرسائل والأدوات ودوال الاسترجاع. + + + + اجمع بين الاستدعاءات غير المتزامنة والبث للاستجابات المتزامنة في الوقت الفعلي: + + ```python + import asyncio + from crewai import LLM + + async def stream_async(): + llm = LLM(model="openai/gpt-4o", stream=True) + + response = await llm.acall("Write a short story about AI") + + print(response) + + asyncio.run(stream_async()) + ``` + + + +## استدعاءات LLM المهيكلة + +يدعم CrewAI الاستجابات المهيكلة من استدعاءات LLM من خلال السماح لك بتحديد `response_format` باستخدام نموذج Pydantic. يمكّن هذا الإطار من تحليل المخرجات والتحقق منها تلقائيًا، مما يسهّل دمج الاستجابة في تطبيقك دون معالجة لاحقة يدوية. + +يختلف دعم المخرجات المهيكلة باختلاف المزوّد والنموذج. اختبر النموذج الذي اخترته قبل الاعتماد على الاستجابات المهيكلة في بيئة الإنتاج. + +```python Code +from crewai import LLM + +class Dog(BaseModel): + name: str + age: int + breed: str + + +llm = LLM(model="openai/gpt-5.6-terra", response_format=Dog) + +response = llm.call( + "Analyze the following messages and return the name, age, and breed. " + "Meet Kona! She is 3 years old and is a black german shepherd." +) +print(response) + +# Output: +# Dog(name='Kona', age=3, breed='black german shepherd') +``` + +## الميزات المتقدمة والتحسين + +تعلّم كيفية الاستفادة القصوى من إعداد LLM: + + + + يتضمن CrewAI ميزات إدارة سياق ذكية: + + ```python + from crewai import LLM + + # CrewAI automatically handles: + # 1. Token counting and tracking + # 2. Content summarization when needed + # 3. Task splitting for large contexts + + llm = LLM( + model="openai/gpt-5.6-terra", + max_completion_tokens=4000, # Limit response length + ) + ``` + + + أفضل الممارسات لإدارة السياق: + 1. اختر نماذج بنوافذ سياق مناسبة + 2. عالج المدخلات الطويلة مسبقًا عند الإمكان + 3. استخدم التقسيم للمستندات الكبيرة + 4. راقب استخدام الرموز لتحسين التكاليف + + + + + + + اختر نافذة السياق المناسبة لمهمتك: + - المهام الصغيرة (حتى 4K رمز): النماذج القياسية + - المهام المتوسطة (بين 4K-32K): النماذج المحسّنة + - المهام الكبيرة (أكثر من 32K): نماذج السياق الكبير + + ```python + # Configure model with appropriate settings + llm = LLM( + model="openai/gpt-5.6-terra", + reasoning_effort="medium", + max_completion_tokens=4096, + timeout=300 + ) + ``` + + استخدم عناصر التحكم التي يدعمها النموذج المحدد. حسب المزود، قد تكون `temperature` أو مستوى reasoning أو thinking، أو تعليمات prompt تحدد الأسلوب والتباين المطلوبين. + + + + + 1. راقب استخدام الرموز + 2. نفّذ تحديد المعدل + 3. استخدم التخزين المؤقت عند الإمكان + 4. عيّن حدود max_tokens مناسبة + + + + + تذكّر مراقبة استخدام الرموز بانتظام وضبط إعداداتك حسب الحاجة لتحسين التكاليف والأداء. + + + + + يستخدم CrewAI داخليًا حزم SDK أصلية لاستدعاءات LLM، مما يتيح لك إسقاط معاملات إضافية غير مطلوبة لحالة الاستخدام الخاصة بك. يمكن أن يساعد هذا في تبسيط كودك وتقليل تعقيد إعداد LLM. + + ```python + from crewai import LLM + import os + + os.environ["OPENAI_API_KEY"] = "" + + o3_llm = LLM( + model="o3", + drop_params=True, + additional_drop_params=["stop"] + ) + ``` + + + + يوفر CrewAI معترضات رسائل لعدة مزودين، مما يتيح لك الربط بدورات الطلب/الاستجابة على مستوى طبقة النقل. + + **المزودون المدعومون:** + - OpenAI + - Anthropic + + **الاستخدام الأساسي:** + ```python +import httpx +from crewai import LLM +from crewai.llms.hooks import BaseInterceptor + +class CustomInterceptor(BaseInterceptor[httpx.Request, httpx.Response]): + """Custom interceptor to modify requests and responses.""" + + def on_outbound(self, request: httpx.Request) -> httpx.Request: + """Print request before sending to the LLM provider.""" + print(request) + return request + + def on_inbound(self, response: httpx.Response) -> httpx.Response: + """Process response after receiving from the LLM provider.""" + print(f"Status: {response.status_code}") + print(f"Response time: {response.elapsed}") + return response + +# Use the interceptor with an LLM +llm = LLM( + model="openai/gpt-4o", + interceptor=CustomInterceptor() +) + ``` + + **ملاحظات مهمة:** + - يجب على كلتا الدالتين إعادة الكائن المستلم أو نوعه. + - تعديل الكائنات المستلمة قد يؤدي إلى سلوك غير متوقع أو أعطال في التطبيق. + - ليس كل المزودين يدعمون المعترضات -- تحقق من قائمة المزودين المدعومين أعلاه + + + تعمل المعترضات على مستوى طبقة النقل. مفيدة بشكل خاص لـ: + - تحويل الرسائل وتصفيتها + - تصحيح تفاعلات API + + + + +## المشاكل الشائعة والحلول + + + + + يمكن حل معظم مشاكل المصادقة بالتحقق من تنسيق مفتاح API وأسماء متغيرات البيئة. + + + ```bash + # OpenAI + OPENAI_API_KEY=sk-... + + # Anthropic + ANTHROPIC_API_KEY=sk-ant-... + ``` + + + + ضمّن دائمًا بادئة المزود في أسماء النماذج + + + ```python + # Correct + llm = LLM(model="openai/gpt-4") + + # Incorrect + llm = LLM(model="gpt-4") + ``` + + + + استخدم نماذج سياق أكبر للمهام الواسعة + + + ```python + # Large context model + llm = LLM(model="openai/gpt-4o") # 128K tokens + ``` + + diff --git a/docs/v1.15.13/ar/concepts/memory.mdx b/docs/v1.15.13/ar/concepts/memory.mdx new file mode 100644 index 0000000000..541f2967a7 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/memory.mdx @@ -0,0 +1,878 @@ +--- +title: الذاكرة +description: الاستفادة من نظام الذاكرة الموحد في CrewAI لتعزيز قدرات الوكلاء. +icon: database +mode: "wide" +--- + +## نظرة عامة + +يوفر CrewAI **نظام ذاكرة موحد** -- فئة `Memory` واحدة تستبدل أنواع الذاكرة المنفصلة (قصيرة المدى، طويلة المدى، ذاكرة الكيانات، والخارجية) بواجهة برمجة تطبيقات ذكية واحدة. تستخدم الذاكرة LLM لتحليل المحتوى عند الحفظ (استنتاج النطاق والفئات والأهمية) وتدعم الاسترجاع متعدد العمق مع تسجيل مركب يمزج بين التشابه الدلالي والحداثة والأهمية. + +يمكنك استخدام الذاكرة بأربع طرق: **مستقلة** (سكربتات، دفاتر ملاحظات)، **مع فرق Crew**، **مع Agents**، أو **داخل التدفقات**. + +## البدء السريع + +```python +from crewai import Memory + +memory = Memory() + +# Store -- the LLM infers scope, categories, and importance +memory.remember("We decided to use PostgreSQL for the user database.") + +# Retrieve -- results ranked by composite score (semantic + recency + importance) +matches = memory.recall("What database did we choose?") +for m in matches: + print(f"[{m.score:.2f}] {m.record.content}") + +# Tune scoring for a fast-moving project +memory = Memory(recency_weight=0.5, recency_half_life_days=7) + +# Forget +memory.forget(scope="/project/old") + +# Explore the self-organized scope tree +print(memory.tree()) +print(memory.info("/")) +``` + +## أربع طرق لاستخدام الذاكرة + +### مستقلة + +استخدم الذاكرة في السكربتات ودفاتر الملاحظات وأدوات سطر الأوامر أو كقاعدة معرفة مستقلة -- لا حاجة لوكلاء أو فرق Crew. + +```python +from crewai import Memory + +memory = Memory() + +# Build up knowledge +memory.remember("The API rate limit is 1000 requests per minute.") +memory.remember("Our staging environment uses port 8080.") +memory.remember("The team agreed to use feature flags for all new releases.") + +# Later, recall what you need +matches = memory.recall("What are our API limits?", limit=5) +for m in matches: + print(f"[{m.score:.2f}] {m.record.content}") + +# Extract atomic facts from a longer text +raw = """Meeting notes: We decided to migrate from MySQL to PostgreSQL +next quarter. The budget is $50k. Sarah will lead the migration.""" + +facts = memory.extract_memories(raw) +# ["Migration from MySQL to PostgreSQL planned for next quarter", +# "Database migration budget is $50k", +# "Sarah will lead the database migration"] + +for fact in facts: + memory.remember(fact) +``` + +### مع فرق Crew + +مرّر `memory=True` للإعدادات الافتراضية، أو مرّر مثيل `Memory` مُعدّ للسلوك المخصص. + +```python +from crewai import Crew, Agent, Task, Process, Memory + +# Option 1: Default memory +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + memory=True, + verbose=True, +) + +# Option 2: Custom memory with tuned scoring +memory = Memory( + recency_weight=0.4, + semantic_weight=0.4, + importance_weight=0.2, + recency_half_life_days=14, +) +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + memory=memory, +) +``` + +عند استخدام `memory=True`، ينشئ الفريق مثيل `Memory()` افتراضيًا ويمرر إعداد `embedder` الخاص بالفريق تلقائيًا. يشترك جميع الوكلاء في الفريق في ذاكرة الفريق ما لم يكن لدى الوكيل ذاكرته الخاصة. + +بعد كل مهمة، يستخرج الفريق تلقائيًا حقائق منفصلة من مخرجات المهمة ويخزّنها. قبل كل مهمة، يسترجع الوكيل السياق ذا الصلة من الذاكرة ويحقنه في موجّه المهمة. + +### مع Agents + +يمكن للوكلاء استخدام ذاكرة الفريق المشتركة (افتراضيًا) أو تلقي عرض محدد النطاق للسياق الخاص. + +```python +from crewai import Agent, Memory + +memory = Memory() + +# Researcher gets a private scope -- only sees /agent/researcher +researcher = Agent( + role="Researcher", + goal="Find and analyze information", + backstory="Expert researcher with attention to detail", + memory=memory.scope("/agent/researcher"), +) + +# Writer uses crew shared memory (no agent-level memory set) +writer = Agent( + role="Writer", + goal="Produce clear, well-structured content", + backstory="Experienced technical writer", + # memory not set -- uses crew._memory when crew has memory enabled +) +``` + +يمنح هذا النمط الباحث نتائج خاصة بينما يقرأ الكاتب من ذاكرة الفريق المشتركة. + +### مع التدفقات + +كل تدفق يحتوي على ذاكرة مدمجة. استخدم `self.remember()` و `self.recall()` و `self.extract_memories()` داخل أي دالة تدفق. + +```python +from crewai.flow.flow import Flow, listen, start + +class ResearchFlow(Flow): + @start() + def gather_data(self): + findings = "PostgreSQL handles 10k concurrent connections. MySQL caps at 5k." + self.remember(findings, scope="/research/databases") + return findings + + @listen(gather_data) + def write_report(self, findings): + # Recall past research to provide context + past = self.recall("database performance benchmarks") + context = "\n".join(f"- {m.record.content}" for m in past) + return f"Report:\nNew findings: {findings}\nPrevious context:\n{context}" +``` + +انظر [وثائق التدفقات](/concepts/flows) لمزيد من المعلومات حول الذاكرة في التدفقات. + + +## النطاقات الهرمية + +### ما هي النطاقات + +يتم تنظيم الذكريات في شجرة هرمية من النطاقات، مشابهة لنظام الملفات. كل نطاق هو مسار مثل `/` أو `/project/alpha` أو `/agent/researcher/findings`. + +``` +/ + /company + /company/engineering + /company/product + /project + /project/alpha + /project/beta + /agent + /agent/researcher + /agent/writer +``` + +توفر النطاقات **ذاكرة تعتمد على السياق** -- عند الاسترجاع ضمن نطاق، تبحث فقط في ذلك الفرع من الشجرة، مما يحسّن كلًا من الدقة والأداء. + +### كيف يعمل استنتاج النطاق + +عند استدعاء `remember()` دون تحديد نطاق، يحلل LLM المحتوى وشجرة النطاقات الحالية، ثم يقترح أفضل موضع. إذا لم يكن هناك نطاق حالي مناسب، ينشئ واحدًا جديدًا. بمرور الوقت، تنمو شجرة النطاقات عضويًا من المحتوى نفسه -- لا تحتاج إلى تصميم مخطط مسبقًا. + +```python +memory = Memory() + +# LLM infers scope from content +memory.remember("We chose PostgreSQL for the user database.") +# -> might be placed under /project/decisions or /engineering/database + +# You can also specify scope explicitly +memory.remember("Sprint velocity is 42 points", scope="/team/metrics") +``` + +### تصوير شجرة النطاقات + +```python +print(memory.tree()) +# / (15 records) +# /project (8 records) +# /project/alpha (5 records) +# /project/beta (3 records) +# /agent (7 records) +# /agent/researcher (4 records) +# /agent/writer (3 records) + +print(memory.info("/project/alpha")) +# ScopeInfo(path='/project/alpha', record_count=5, +# categories=['architecture', 'database'], +# oldest_record=datetime(...), newest_record=datetime(...), +# child_scopes=[]) +``` + +### MemoryScope: عروض الأشجار الفرعية + +يقيّد `MemoryScope` جميع العمليات على فرع من الشجرة. يمكن للوكيل أو الكود الذي يستخدمه الرؤية والكتابة فقط ضمن تلك الشجرة الفرعية. + +```python +memory = Memory() + +# Create a scope for a specific agent +agent_memory = memory.scope("/agent/researcher") + +# Everything is relative to /agent/researcher +agent_memory.remember("Found three relevant papers on LLM memory.") +# -> stored under /agent/researcher + +agent_memory.recall("relevant papers") +# -> searches only under /agent/researcher + +# Narrow further with subscope +project_memory = agent_memory.subscope("project-alpha") +# -> /agent/researcher/project-alpha +``` + +### أفضل الممارسات لتصميم النطاقات + +- **ابدأ بشكل مسطح، ودع LLM ينظّم.** لا تبالغ في هندسة تسلسل النطاقات مسبقًا. ابدأ بـ `memory.remember(content)` ودع استنتاج النطاق في LLM ينشئ الهيكل مع تراكم المحتوى. + +- **استخدم أنماط `/{entity_type}/{identifier}`.** تنشأ التسلسلات الطبيعية من أنماط مثل `/project/alpha` و `/agent/researcher` و `/company/engineering` و `/customer/acme-corp`. + +- **حدد النطاق حسب الاهتمام، وليس حسب نوع البيانات.** استخدم `/project/alpha/decisions` بدلاً من `/decisions/project/alpha`. هذا يبقي المحتوى ذا الصلة معًا. + +- **حافظ على العمق ضحلًا (2-3 مستويات).** النطاقات المتداخلة بعمق تصبح متفرقة جدًا. `/project/alpha/architecture` جيد؛ `/project/alpha/architecture/decisions/databases/postgresql` عميق جدًا. + +- **استخدم النطاقات الصريحة عندما تعرف، ودع LLM يستنتج عندما لا تعرف.** إذا كنت تخزّن قرار مشروع معروف، مرّر `scope="/project/alpha/decisions"`. إذا كنت تخزّن مخرجات وكيل حرة الشكل، اترك النطاق ودع LLM يحدده. + +### أمثلة حالات الاستخدام + +**فريق متعدد المشاريع:** +```python +memory = Memory() +# Each project gets its own branch +memory.remember("Using microservices architecture", scope="/project/alpha/architecture") +memory.remember("GraphQL API for client apps", scope="/project/beta/api") + +# Recall across all projects +memory.recall("API design decisions") + +# Or within a specific project +memory.recall("API design", scope="/project/beta") +``` + +**سياق خاص لكل وكيل مع معرفة مشتركة:** +```python +memory = Memory() + +# Researcher has private findings +researcher_memory = memory.scope("/agent/researcher") + +# Writer can read from both its own scope and shared company knowledge +writer_view = memory.slice( + scopes=["/agent/writer", "/company/knowledge"], + read_only=True, +) +``` + +**دعم العملاء (سياق لكل عميل):** +```python +memory = Memory() + +# Each customer gets isolated context +memory.remember("Prefers email communication", scope="/customer/acme-corp") +memory.remember("On enterprise plan, 50 seats", scope="/customer/acme-corp") + +# Shared product docs are accessible to all agents +memory.remember("Rate limit is 1000 req/min on enterprise plan", scope="/product/docs") +``` + + +## شرائح الذاكرة + +### ما هي الشرائح + +`MemorySlice` هو عرض عبر نطاقات متعددة، ربما متباعدة. على عكس النطاق (الذي يقيّد على شجرة فرعية واحدة)، تتيح لك الشريحة الاسترجاع من عدة فروع في وقت واحد. + +### متى تستخدم الشرائح مقابل النطاقات + +- **النطاق**: استخدمه عندما يجب تقييد وكيل أو كتلة كود على شجرة فرعية واحدة. مثال: وكيل يرى فقط `/agent/researcher`. +- **الشريحة**: استخدمها عندما تحتاج إلى دمج السياق من عدة فروع. مثال: وكيل يقرأ من نطاقه الخاص بالإضافة إلى معرفة الشركة المشتركة. + +### شرائح القراءة فقط + +النمط الأكثر شيوعًا: منح وكيل إمكانية القراءة من فروع متعددة دون السماح له بالكتابة في المناطق المشتركة. + +```python +memory = Memory() + +# Agent can recall from its own scope AND company knowledge, +# but cannot write to company knowledge +agent_view = memory.slice( + scopes=["/agent/researcher", "/company/knowledge"], + read_only=True, +) + +matches = agent_view.recall("company security policies", limit=5) +# Searches both /agent/researcher and /company/knowledge, merges and ranks results + +agent_view.remember("new finding") # Raises PermissionError (read-only) +``` + +### شرائح القراءة والكتابة + +عند تعطيل القراءة فقط، يمكنك الكتابة في أي من النطاقات المضمّنة، لكن يجب تحديد النطاق صراحة. + +```python +view = memory.slice(scopes=["/team/alpha", "/team/beta"], read_only=False) + +# Must specify scope when writing +view.remember("Cross-team decision", scope="/team/alpha", categories=["decisions"]) +``` + + +## التسجيل المركب + +يتم ترتيب نتائج الاسترجاع بواسطة مزيج مرجّح من ثلاث إشارات: + +``` +composite = semantic_weight * similarity + recency_weight * decay + importance_weight * importance +``` + +حيث: +- **similarity** = `1 / (1 + distance)` من فهرس المتجهات (0 إلى 1) +- **decay** = `0.5^(age_days / half_life_days)` -- اضمحلال أُسي (1.0 لليوم، 0.5 عند نصف العمر) +- **importance** = درجة أهمية السجل (0 إلى 1)، يتم تعيينها وقت الترميز + +قم بإعدادها مباشرة على منشئ `Memory`: + +```python +# Sprint retrospective: favor recent memories, short half-life +memory = Memory( + recency_weight=0.5, + semantic_weight=0.3, + importance_weight=0.2, + recency_half_life_days=7, +) + +# Architecture knowledge base: favor important memories, long half-life +memory = Memory( + recency_weight=0.1, + semantic_weight=0.5, + importance_weight=0.4, + recency_half_life_days=180, +) +``` + +يتضمن كل `MemoryMatch` قائمة `match_reasons` حتى تتمكن من رؤية سبب ترتيب نتيجة معينة في موضعها (مثل `["semantic", "recency", "importance"]`). + + +## طبقة تحليل LLM + +تستخدم الذاكرة LLM بثلاث طرق: + +1. **عند الحفظ** -- عندما تحذف النطاق أو الفئات أو الأهمية، يحلل LLM المحتوى ويقترح النطاق والفئات والأهمية والبيانات الوصفية (الكيانات والتواريخ والموضوعات). +2. **عند الاسترجاع** -- للاسترجاع العميق/التلقائي، يحلل LLM الاستعلام (الكلمات المفتاحية، تلميحات الوقت، النطاقات المقترحة، التعقيد) لتوجيه الاسترجاع. +3. **استخراج الذكريات** -- `extract_memories(content)` يقسم النص الخام (مثل مخرجات المهمة) إلى عبارات ذاكرة منفصلة. يستخدم الوكلاء هذا قبل استدعاء `remember()` على كل عبارة حتى يتم تخزين حقائق ذرية بدلاً من كتلة كبيرة واحدة. + +جميع التحليلات تتدهور بسلاسة عند فشل LLM -- انظر [سلوك الفشل](#سلوك-الفشل). + + +## توحيد الذاكرة + +عند حفظ محتوى جديد، يتحقق خط أنابيب الترميز تلقائيًا من وجود سجلات مماثلة في التخزين. إذا كان التشابه أعلى من `consolidation_threshold` (الافتراضي 0.85)، يقرر LLM ما يجب فعله: + +- **keep** -- السجل الحالي لا يزال دقيقًا وغير مكرر. +- **update** -- يجب تحديث السجل الحالي بمعلومات جديدة (يوفر LLM المحتوى المدمج). +- **delete** -- السجل الحالي قديم أو تم استبداله أو تناقضه. +- **insert_new** -- ما إذا كان يجب إدراج المحتوى الجديد أيضًا كسجل منفصل. + +هذا يمنع تراكم النسخ المكررة. على سبيل المثال، إذا حفظت "CrewAI ensures reliable operation" ثلاث مرات، يتعرف التوحيد على النسخ المكررة ويحتفظ بسجل واحد فقط. + +### إزالة التكرار داخل الدفعة + +عند استخدام `remember_many()`، تتم مقارنة العناصر داخل نفس الدفعة مع بعضها البعض قبل الوصول إلى التخزين. إذا كان تشابه جيب التمام >= `batch_dedup_threshold` (الافتراضي 0.98)، يتم إسقاط العنصر الأحدث بصمت. هذا يلتقط النسخ المكررة الدقيقة أو شبه الدقيقة داخل دفعة واحدة دون أي استدعاءات LLM (رياضيات متجهات خالصة). + +```python +# Only 2 records are stored (the third is a near-duplicate of the first) +memory.remember_many([ + "CrewAI supports complex workflows.", + "Python is a great language.", + "CrewAI supports complex workflows.", # dropped by intra-batch dedup +]) +``` + + +## الحفظ غير الحاجب + +`remember_many()` **غير حاجب** -- يقدم خط أنابيب الترميز إلى خيط خلفي ويعود فورًا. هذا يعني أن الوكيل يمكنه المتابعة إلى المهمة التالية بينما يتم حفظ الذكريات. + +```python +# Returns immediately -- save happens in background +memory.remember_many(["Fact A.", "Fact B.", "Fact C."]) + +# recall() automatically waits for pending saves before searching +matches = memory.recall("facts") # sees all 3 records +``` + +### حاجز القراءة + +كل استدعاء `recall()` يستدعي تلقائيًا `drain_writes()` قبل البحث، مما يضمن أن الاستعلام يرى دائمًا أحدث السجلات المستمرة. هذا شفاف -- لا تحتاج أبدًا إلى التفكير فيه. + +### إيقاف الفريق + +عند انتهاء الفريق، يستنزف `kickoff()` جميع عمليات حفظ الذاكرة المعلقة في كتلة `finally` الخاصة به، لذا لا تُفقد أي عمليات حفظ حتى لو اكتمل الفريق بينما عمليات الحفظ الخلفية قيد التنفيذ. + +### الاستخدام المستقل + +للسكربتات أو دفاتر الملاحظات حيث لا توجد دورة حياة فريق، استدعِ `drain_writes()` أو `close()` صراحة: + +```python +memory = Memory() +memory.remember_many(["Fact A.", "Fact B."]) + +# Option 1: Wait for pending saves +memory.drain_writes() + +# Option 2: Drain and shut down the background pool +memory.close() +``` + + +## المصدر والخصوصية + +يمكن لكل سجل ذاكرة أن يحمل علامة `source` لتتبع المصدر وعلامة `private` للتحكم في الوصول. + +### تتبع المصدر + +يحدد معامل `source` من أين جاءت الذاكرة: + +```python +# Tag memories with their origin +memory.remember("User prefers dark mode", source="user:alice") +memory.remember("System config updated", source="admin") +memory.remember("Agent found a bug", source="agent:debugger") + +# Recall only memories from a specific source +matches = memory.recall("user preferences", source="user:alice") +``` + +### الذكريات الخاصة + +الذكريات الخاصة مرئية فقط للاسترجاع عندما يتطابق `source`: + +```python +# Store a private memory +memory.remember("Alice's API key is sk-...", source="user:alice", private=True) + +# This recall sees the private memory (source matches) +matches = memory.recall("API key", source="user:alice") + +# This recall does NOT see it (different source) +matches = memory.recall("API key", source="user:bob") + +# Admin access: see all private records regardless of source +matches = memory.recall("API key", include_private=True) +``` + +هذا مفيد بشكل خاص في النشرات متعددة المستخدمين أو المؤسسية حيث يجب عزل ذكريات المستخدمين المختلفين. + + +## RecallFlow (الاسترجاع العميق) + +يدعم `recall()` عمقين: + +- **`depth="shallow"`** -- بحث متجهي مباشر مع تسجيل مركب. سريع (~200 مللي ثانية)، بدون استدعاءات LLM. +- **`depth="deep"` (افتراضي)** -- يشغل RecallFlow متعدد الخطوات: تحليل الاستعلام، اختيار النطاق، بحث متجهي متوازٍ، توجيه قائم على الثقة، واستكشاف متكرر اختياري عندما تكون الثقة منخفضة. + +**تخطي LLM الذكي**: الاستعلامات الأقصر من `query_analysis_threshold` (الافتراضي 200 حرف) تتخطى تحليل LLM للاستعلام بالكامل، حتى في الوضع العميق. الاستعلامات القصيرة مثل "ما قاعدة البيانات التي نستخدمها؟" هي بالفعل عبارات بحث جيدة -- تحليل LLM يضيف قيمة قليلة. هذا يوفر ~1-3 ثوانٍ لكل استرجاع للاستعلامات القصيرة النموذجية. فقط الاستعلامات الأطول (مثل أوصاف المهام الكاملة) تمر عبر تقطير LLM إلى استعلامات فرعية مستهدفة. + +```python +# Shallow: pure vector search, no LLM +matches = memory.recall("What did we decide?", limit=10, depth="shallow") + +# Deep (default): intelligent retrieval with LLM analysis for long queries +matches = memory.recall( + "Summarize all architecture decisions from this quarter", + limit=10, + depth="deep", +) +``` + +عتبات الثقة التي تتحكم في موجّه RecallFlow قابلة للإعداد: + +```python +memory = Memory( + confidence_threshold_high=0.9, # Only synthesize when very confident + confidence_threshold_low=0.4, # Explore deeper more aggressively + exploration_budget=2, # Allow up to 2 exploration rounds + query_analysis_threshold=200, # Skip LLM for queries shorter than this +) +``` + + +## إعداد المُضمِّن + +تحتاج الذاكرة إلى نموذج تضمين لتحويل النص إلى متجهات للبحث الدلالي. يمكنك إعداده بثلاث طرق. + +### التمرير إلى Memory مباشرة + +```python +from crewai import Memory + +# As a config dict +memory = Memory(embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-small"}}) + +# As a pre-built callable +from crewai.rag.embeddings.factory import build_embedder +embedder = build_embedder({"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}) +memory = Memory(embedder=embedder) +``` + +### عبر إعداد مُضمِّن Crew + +عند استخدام `memory=True`، يتم تمرير إعداد `embedder` الخاص بالفريق: + +```python +from crewai import Crew + +crew = Crew( + agents=[...], + tasks=[...], + memory=True, + embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-small"}}, +) +``` + +### أمثلة المزودين + + + +```python +memory = Memory(embedder={ + "provider": "openai", + "config": { + "model_name": "text-embedding-3-small", + # "api_key": "sk-...", # or set OPENAI_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "ollama", + "config": { + "model_name": "mxbai-embed-large", + "url": "http://localhost:11434/api/embeddings", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "azure", + "config": { + "deployment_id": "your-embedding-deployment", + "api_key": "your-azure-api-key", + "api_base": "https://your-resource.openai.azure.com", + "api_version": "2024-02-01", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "google-generativeai", + "config": { + "model_name": "gemini-embedding-001", + # "api_key": "...", # or set GOOGLE_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "google-vertex", + "config": { + "model_name": "gemini-embedding-001", + "project_id": "your-gcp-project-id", + "location": "us-central1", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "cohere", + "config": { + "model_name": "embed-english-v3.0", + # "api_key": "...", # or set COHERE_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "voyageai", + "config": { + "model": "voyage-3", + # "api_key": "...", # or set VOYAGE_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "amazon-bedrock", + "config": { + "model_name": "amazon.titan-embed-text-v1", + # Uses default AWS credentials (boto3 session) + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "huggingface", + "config": { + "model_name": "sentence-transformers/all-MiniLM-L6-v2", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "jina", + "config": { + "model_name": "jina-embeddings-v2-base-en", + # "api_key": "...", # or set JINA_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "watsonx", + "config": { + "model_id": "ibm/slate-30m-english-rtrvr", + "api_key": "your-watsonx-api-key", + "project_id": "your-project-id", + "url": "https://us-south.ml.cloud.ibm.com", + }, +}) +``` + + + +```python +# Pass any callable that takes a list of strings and returns a list of vectors +def my_embedder(texts: list[str]) -> list[list[float]]: + # Your embedding logic here + return [[0.1, 0.2, ...] for _ in texts] + +memory = Memory(embedder=my_embedder) +``` + + + +### مرجع المزودين + +| المزود | المفتاح | النموذج النموذجي | ملاحظات | +| :--- | :--- | :--- | :--- | +| OpenAI | `openai` | `text-embedding-3-small` | افتراضي. عيّن `OPENAI_API_KEY`. | +| Ollama | `ollama` | `mxbai-embed-large` | محلي، لا حاجة لمفتاح API. | +| Azure OpenAI | `azure` | `text-embedding-ada-002` | يتطلب `deployment_id`. | +| Google AI | `google-generativeai` | `gemini-embedding-001` | عيّن `GOOGLE_API_KEY`. | +| Google Vertex | `google-vertex` | `gemini-embedding-001` | يتطلب `project_id`. | +| Cohere | `cohere` | `embed-english-v3.0` | دعم قوي متعدد اللغات. | +| VoyageAI | `voyageai` | `voyage-3` | محسّن للاسترجاع. | +| AWS Bedrock | `amazon-bedrock` | `amazon.titan-embed-text-v1` | يستخدم بيانات اعتماد boto3. | +| Hugging Face | `huggingface` | `all-MiniLM-L6-v2` | sentence-transformers محلي. | +| Jina | `jina` | `jina-embeddings-v2-base-en` | عيّن `JINA_API_KEY`. | +| IBM WatsonX | `watsonx` | `ibm/slate-30m-english-rtrvr` | يتطلب `project_id`. | +| Sentence Transformer | `sentence-transformer` | `all-MiniLM-L6-v2` | محلي، لا حاجة لمفتاح API. | +| مخصص | `custom` | -- | يتطلب `embedding_callable`. | + + +## إعداد LLM + +تستخدم الذاكرة LLM لتحليل الحفظ (استنتاج النطاق والفئات والأهمية)، وقرارات التوحيد، وتحليل استعلام الاسترجاع العميق. يمكنك إعداد النموذج المُستخدم. + +```python +from crewai import Memory, LLM + +# Default: gpt-4o-mini +memory = Memory() + +# Use a different OpenAI model +memory = Memory(llm="gpt-4o") + +# Use Anthropic +memory = Memory(llm="anthropic/claude-3-haiku-20240307") + +# Use Ollama for fully local/private analysis +memory = Memory(llm="ollama/llama3.2") + +# Use Google Gemini +memory = Memory(llm="gemini/gemini-2.0-flash") + +# Pass a pre-configured LLM instance with custom settings +llm = LLM(model="gpt-4o", temperature=0) +memory = Memory(llm=llm) +``` + +يتم تهيئة LLM **بشكل كسول** -- يتم إنشاؤه فقط عند الحاجة لأول مرة. هذا يعني أن `Memory()` لا يفشل أبدًا في وقت الإنشاء، حتى لو لم تكن مفاتيح API مُعيّنة. تظهر الأخطاء فقط عند استدعاء LLM فعليًا (مثلاً عند الحفظ بدون نطاق/فئات صريحة، أو أثناء الاسترجاع العميق). + +للتشغيل المحلي/الخاص بالكامل، استخدم نموذجًا محليًا لكل من LLM والمُضمِّن: + +```python +memory = Memory( + llm="ollama/llama3.2", + embedder={"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}, +) +``` + + +## واجهة التخزين + +- **الافتراضي**: LanceDB، مخزّن تحت `./.crewai/memory` (أو `$CREWAI_STORAGE_DIR/memory` إذا تم تعيين متغير البيئة، أو المسار الذي تمرره كـ `storage="path/to/dir"`). +- **واجهة مخصصة**: نفّذ بروتوكول `StorageBackend` (انظر `crewai.memory.storage.backend`) ومرّر مثيلًا إلى `Memory(storage=your_backend)`. + + +## الاستكشاف + +فحص التسلسل الهرمي للنطاقات والفئات والسجلات: + +```python +memory.tree() # Formatted tree of scopes and record counts +memory.tree("/project", max_depth=2) # Subtree view +memory.info("/project") # ScopeInfo: record_count, categories, oldest/newest +memory.list_scopes("/") # Immediate child scopes +memory.list_categories() # Category names and counts +memory.list_records(scope="/project/alpha", limit=20) # Records in a scope, newest first +``` + + +## سلوك الفشل + +إذا فشل LLM أثناء التحليل (خطأ شبكة، حد معدل، استجابة غير صالحة)، تتدهور الذاكرة بسلاسة: + +- **تحليل الحفظ** -- يتم تسجيل تحذير ولا يزال يتم تخزين الذاكرة مع النطاق الافتراضي `/`، فئات فارغة، وأهمية `0.5`. +- **استخراج الذكريات** -- يتم تخزين المحتوى الكامل كذاكرة واحدة حتى لا يُفقد شيء. +- **تحليل الاستعلام** -- يتراجع الاسترجاع إلى اختيار نطاق بسيط وبحث متجهي حتى تستمر في الحصول على نتائج. + +لا يتم رفع أي استثناء لفشل التحليل هذه؛ فقط فشل التخزين أو المُضمِّن سيرفع استثناءً. + + +## ملاحظة حول الخصوصية + +يتم إرسال محتوى الذاكرة إلى LLM المُعدّ للتحليل (النطاق/الفئات/الأهمية عند الحفظ، تحليل الاستعلام والاسترجاع العميق الاختياري). للبيانات الحساسة، استخدم LLM محليًا (مثل Ollama) أو تأكد من أن مزودك يلبي متطلبات الامتثال الخاصة بك. + + +## أحداث الذاكرة + +جميع عمليات الذاكرة تُصدر أحداثًا مع `source_type="unified_memory"`. يمكنك الاستماع للتوقيت والأخطاء والمحتوى. + +| الحدث | الوصف | الخصائص الرئيسية | +| :---- | :---------- | :------------- | +| **MemoryQueryStartedEvent** | بداية الاستعلام | `query`, `limit` | +| **MemoryQueryCompletedEvent** | نجاح الاستعلام | `query`, `results`, `query_time_ms` | +| **MemoryQueryFailedEvent** | فشل الاستعلام | `query`, `error` | +| **MemorySaveStartedEvent** | بداية الحفظ | `value`, `metadata` | +| **MemorySaveCompletedEvent** | نجاح الحفظ | `value`, `save_time_ms` | +| **MemorySaveFailedEvent** | فشل الحفظ | `value`, `error` | +| **MemoryRetrievalStartedEvent** | بداية استرجاع الوكيل | `task_id` | +| **MemoryRetrievalCompletedEvent** | اكتمال استرجاع الوكيل | `task_id`, `memory_content`, `retrieval_time_ms` | + +مثال: مراقبة وقت الاستعلام: + +```python +from crewai.events import BaseEventListener, MemoryQueryCompletedEvent + +class MemoryMonitor(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(MemoryQueryCompletedEvent) + def on_done(source, event): + if getattr(event, "source_type", None) == "unified_memory": + print(f"Query '{event.query}' completed in {event.query_time_ms:.0f}ms") +``` + + +## استكشاف المشاكل + +**الذاكرة لا تستمر؟** +- تأكد من أن مسار التخزين قابل للكتابة (الافتراضي `./.crewai/memory`). مرّر `storage="./your_path"` لاستخدام مجلد مختلف، أو عيّن متغير البيئة `CREWAI_STORAGE_DIR`. +- عند استخدام فريق، تأكد من تعيين `memory=True` أو `memory=Memory(...)`. + +**الاسترجاع بطيء؟** +- استخدم `depth="shallow"` لسياق الوكيل الروتيني. احتفظ بـ `depth="deep"` للاستعلامات المعقدة. +- زد `query_analysis_threshold` لتخطي تحليل LLM لمزيد من الاستعلامات. + +**أخطاء تحليل LLM في السجلات؟** +- لا تزال الذاكرة تحفظ/تسترجع بإعدادات افتراضية آمنة. تحقق من مفاتيح API وحدود المعدل وتوفر النموذج إذا كنت تريد تحليل LLM كاملاً. + +**أخطاء حفظ خلفية في السجلات؟** +- عمليات حفظ الذاكرة تعمل في خيط خلفي. تُصدر الأخطاء كـ `MemorySaveFailedEvent` لكنها لا تعطل الوكيل. تحقق من السجلات للسبب الجذري (عادة مشاكل اتصال LLM أو المُضمِّن). + +**تعارضات الكتابة المتزامنة؟** +- عمليات LanceDB مُتسلسلة بقفل مشترك وتُعاد تلقائيًا عند التعارض. هذا يتعامل مع مثيلات `Memory` المتعددة التي تشير إلى نفس قاعدة البيانات (مثل ذاكرة وكيل + ذاكرة فريق). لا حاجة لإجراء. + +**تصفح الذاكرة من الطرفية:** +```bash +crewai memory # Opens the TUI browser +crewai memory --storage-path ./my_memory # Point to a specific directory +``` + +**إعادة تعيين الذاكرة (مثلاً للاختبارات):** +```python +crew.reset_memories(command_type="memory") # Resets unified memory +# Or on a Memory instance: +memory.reset() # All scopes +memory.reset(scope="/project/old") # Only that subtree +``` + + +## مرجع الإعداد + +جميع الإعدادات تُمرر كمعاملات كلمة مفتاحية إلى `Memory(...)`. كل معامل له قيمة افتراضية معقولة. + +| المعامل | الافتراضي | الوصف | +| :--- | :--- | :--- | +| `llm` | `"gpt-4o-mini"` | LLM للتحليل (اسم نموذج أو مثيل `BaseLLM`). | +| `storage` | `"lancedb"` | واجهة التخزين (`"lancedb"`، سلسلة مسار، أو مثيل `StorageBackend`). | +| `embedder` | `None` (افتراضي OpenAI) | المُضمِّن (قاموس إعداد، دالة قابلة للاستدعاء، أو `None` لافتراضي OpenAI). | +| `recency_weight` | `0.3` | وزن الحداثة في الدرجة المركبة. | +| `semantic_weight` | `0.5` | وزن التشابه الدلالي في الدرجة المركبة. | +| `importance_weight` | `0.2` | وزن الأهمية في الدرجة المركبة. | +| `recency_half_life_days` | `30` | أيام لتنصيف درجة الحداثة (اضمحلال أُسي). | +| `consolidation_threshold` | `0.85` | التشابه الذي يُشغّل فوقه التوحيد عند الحفظ. عيّن إلى `1.0` للتعطيل. | +| `consolidation_limit` | `5` | أقصى عدد سجلات حالية للمقارنة أثناء التوحيد. | +| `default_importance` | `0.5` | الأهمية المُعيّنة عندما لا تُوفَّر ويتم تخطي تحليل LLM. | +| `batch_dedup_threshold` | `0.98` | تشابه جيب التمام لإسقاط النسخ شبه المكررة داخل دفعة `remember_many()`. | +| `confidence_threshold_high` | `0.8` | ثقة الاسترجاع التي تُعاد فوقها النتائج مباشرة. | +| `confidence_threshold_low` | `0.5` | ثقة الاسترجاع التي يُشغّل تحتها استكشاف أعمق. | +| `complex_query_threshold` | `0.7` | للاستعلامات المعقدة، استكشف أعمق تحت هذه الثقة. | +| `exploration_budget` | `1` | عدد جولات الاستكشاف المدفوعة بـ LLM أثناء الاسترجاع العميق. | +| `query_analysis_threshold` | `200` | الاستعلامات الأقصر من هذا (بالأحرف) تتخطى تحليل LLM أثناء الاسترجاع العميق. | diff --git a/docs/v1.15.13/ar/concepts/planning.mdx b/docs/v1.15.13/ar/concepts/planning.mdx new file mode 100644 index 0000000000..12f5ef1172 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/planning.mdx @@ -0,0 +1,155 @@ +--- +title: التخطيط +description: تعرّف على كيفية إضافة التخطيط إلى طاقم CrewAI وتحسين أدائه. +icon: ruler-combined +mode: "wide" +--- + +## نظرة عامة + +تتيح لك ميزة التخطيط في CrewAI إضافة قدرة التخطيط إلى طاقمك. عند تفعيلها، قبل كل تكرار للطاقم، +يتم إرسال جميع معلومات الطاقم إلى AgentPlanner الذي يخطط للمهام خطوة بخطوة، ويُضاف هذا المخطط إلى وصف كل مهمة. + +### استخدام ميزة التخطيط + +البدء بميزة التخطيط سهل جدًا، الخطوة الوحيدة المطلوبة هي إضافة `planning=True` إلى طاقمك: + + +```python Code +from crewai import Crew, Agent, Task, Process + +# تجميع طاقمك مع قدرات التخطيط +my_crew = Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + planning=True, +) +``` + + +من هذه النقطة فصاعدًا، سيكون التخطيط مفعّلًا في طاقمك، وسيتم تخطيط المهام قبل كل تكرار. + + +عند تفعيل التخطيط، سيستخدم CrewAI `gpt-4o-mini` كنموذج LLM افتراضي للتخطيط، مما يتطلب مفتاح API صالحًا من OpenAI. نظرًا لأن وكلاءك قد يستخدمون نماذج LLM مختلفة، فقد يسبب ذلك ارتباكًا إذا لم يكن لديك مفتاح OpenAI API مهيأ أو إذا كنت تواجه سلوكًا غير متوقع متعلقًا باستدعاءات LLM API. + + +#### LLM التخطيط + +يمكنك الآن تحديد نموذج LLM الذي سيُستخدم لتخطيط المهام. + +عند تشغيل مثال الحالة الأساسية، سترى شيئًا مشابهًا للمخرجات أدناه، والتي تمثل مخرجات `AgentPlanner` +المسؤول عن إنشاء المنطق التدريجي لإضافته إلى مهام الوكلاء. + + +```python Code +from crewai import Crew, Agent, Task, Process + +# تجميع طاقمك مع قدرات التخطيط ونموذج LLM مخصص +my_crew = Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + planning=True, + planning_llm="gpt-4o" +) + +# تشغيل الطاقم +my_crew.kickoff() +``` + +```markdown Result +[2024-07-15 16:49:11][INFO]: Planning the crew execution +**Step-by-Step Plan for Task Execution** + +**Task Number 1: Conduct a thorough research about AI LLMs** + +**Agent:** AI LLMs Senior Data Researcher + +**Agent Goal:** Uncover cutting-edge developments in AI LLMs + +**Task Expected Output:** A list with 10 bullet points of the most relevant information about AI LLMs + +**Task Tools:** None specified + +**Agent Tools:** None specified + +**Step-by-Step Plan:** + +1. **Define Research Scope:** + + - Determine the specific areas of AI LLMs to focus on, such as advancements in architecture, use cases, ethical considerations, and performance metrics. + +2. **Identify Reliable Sources:** + + - List reputable sources for AI research, including academic journals, industry reports, conferences (e.g., NeurIPS, ACL), AI research labs (e.g., OpenAI, Google AI), and online databases (e.g., IEEE Xplore, arXiv). + +3. **Collect Data:** + + - Search for the latest papers, articles, and reports published in 2024 and early 2025. + - Use keywords like "Large Language Models 2025", "AI LLM advancements", "AI ethics 2025", etc. + +4. **Analyze Findings:** + + - Read and summarize the key points from each source. + - Highlight new techniques, models, and applications introduced in the past year. + +5. **Organize Information:** + + - Categorize the information into relevant topics (e.g., new architectures, ethical implications, real-world applications). + - Ensure each bullet point is concise but informative. + +6. **Create the List:** + + - Compile the 10 most relevant pieces of information into a bullet point list. + - Review the list to ensure clarity and relevance. + +**Expected Output:** + +A list with 10 bullet points of the most relevant information about AI LLMs. + +--- + +**Task Number 2: Review the context you got and expand each topic into a full section for a report** + +**Agent:** AI LLMs Reporting Analyst + +**Agent Goal:** Create detailed reports based on AI LLMs data analysis and research findings + +**Task Expected Output:** A fully fledged report with the main topics, each with a full section of information. Formatted as markdown without '```' + +**Task Tools:** None specified + +**Agent Tools:** None specified + +**Step-by-Step Plan:** + +1. **Review the Bullet Points:** + - Carefully read through the list of 10 bullet points provided by the AI LLMs Senior Data Researcher. + +2. **Outline the Report:** + - Create an outline with each bullet point as a main section heading. + - Plan sub-sections under each main heading to cover different aspects of the topic. + +3. **Research Further Details:** + - For each bullet point, conduct additional research if necessary to gather more detailed information. + - Look for case studies, examples, and statistical data to support each section. + +4. **Write Detailed Sections:** + - Expand each bullet point into a comprehensive section. + - Ensure each section includes an introduction, detailed explanation, examples, and a conclusion. + - Use markdown formatting for headings, subheadings, lists, and emphasis. + +5. **Review and Edit:** + - Proofread the report for clarity, coherence, and correctness. + - Make sure the report flows logically from one section to the next. + - Format the report according to markdown standards. + +6. **Finalize the Report:** + - Ensure the report is complete with all sections expanded and detailed. + - Double-check formatting and make any necessary adjustments. + +**Expected Output:** +A fully fledged report with the main topics, each with a full section of information. Formatted as markdown without '```'. +``` + diff --git a/docs/v1.15.13/ar/concepts/processes.mdx b/docs/v1.15.13/ar/concepts/processes.mdx new file mode 100644 index 0000000000..a49ecc2272 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/processes.mdx @@ -0,0 +1,66 @@ +--- +title: العمليات +description: دليل تفصيلي حول إدارة سير العمل من خلال العمليات في CrewAI، مع تفاصيل التنفيذ المحدّثة. +icon: bars-staggered +mode: "wide" +--- + +## نظرة عامة + + + تنسّق العمليات تنفيذ المهام بواسطة الوكلاء، على غرار إدارة المشاريع في الفرق البشرية. + تضمن هذه العمليات توزيع المهام وتنفيذها بكفاءة، وفقًا لاستراتيجية محددة مسبقًا. + + +## تنفيذات العمليات + +- **تسلسلي**: ينفذ المهام بالتتابع، مما يضمن إكمال المهام بتقدم منظم. +- **هرمي**: ينظم المهام في تسلسل إداري هرمي، حيث يتم تفويض المهام وتنفيذها بناءً على سلسلة أوامر منظمة. يجب تحديد نموذج لغة المدير (`manager_llm`) أو وكيل مدير مخصص (`manager_agent`) في الطاقم لتفعيل العملية الهرمية، مما يسهّل إنشاء وإدارة المهام من قبل المدير. + +## دور العمليات في العمل الجماعي +تُمكّن العمليات الوكلاء الأفراد من العمل كوحدة متماسكة، مما يبسّط جهودهم لتحقيق أهداف مشتركة بكفاءة وتناسق. + +## تعيين العمليات للطاقم +لتعيين عملية لطاقم، حدد نوع العملية عند إنشاء الطاقم لتعيين استراتيجية التنفيذ. للعملية الهرمية، تأكد من تحديد `manager_llm` أو `manager_agent` لوكيل المدير. + +```python +from crewai import Crew, Process + +# مثال: إنشاء طاقم بعملية تسلسلية +crew = Crew( + agents=my_agents, + tasks=my_tasks, + process=Process.sequential +) + +# مثال: إنشاء طاقم بعملية هرمية +# تأكد من توفير manager_llm أو manager_agent +crew = Crew( + agents=my_agents, + tasks=my_tasks, + process=Process.hierarchical, + manager_llm="gpt-4o" + # أو + # manager_agent=my_manager_agent +) +``` +**ملاحظة:** تأكد من تعريف `my_agents` و `my_tasks` قبل إنشاء كائن `Crew`، وللعملية الهرمية، يُعد `manager_llm` أو `manager_agent` مطلوبًا أيضًا. + +## العملية التسلسلية + +تعكس هذه الطريقة سير عمل الفريق الديناميكي، وتتقدم عبر المهام بطريقة مدروسة ومنهجية. يتبع تنفيذ المهام الترتيب المحدد مسبقًا في قائمة المهام، حيث يعمل ناتج مهمة واحدة كسياق للمهمة التالية. + +لتخصيص سياق المهمة، استخدم معامل `context` في فئة `Task` لتحديد المخرجات التي يجب استخدامها كسياق للمهام اللاحقة. + +## العملية الهرمية + +تحاكي التسلسل الهرمي المؤسسي، حيث يسمح CrewAI بتحديد وكيل مدير مخصص أو إنشاء واحد تلقائيًا، مما يتطلب تحديد نموذج لغة المدير (`manager_llm`). يشرف هذا الوكيل على تنفيذ المهام، بما في ذلك التخطيط والتفويض والتحقق. لا يتم تعيين المهام مسبقًا؛ يخصص المدير المهام للوكلاء بناءً على قدراتهم، ويراجع المخرجات، ويقيّم اكتمال المهام. + +## فئة Process: نظرة عامة مفصلة + +تم تنفيذ فئة `Process` كتعداد (`Enum`)، مما يضمن أمان الأنواع ويقيّد قيم العملية على الأنواع المحددة (`sequential`، `hierarchical`). + +## الخلاصة + +التعاون المنظم الذي تسهّله العمليات داخل CrewAI ضروري لتمكين العمل الجماعي المنهجي بين الوكلاء. +تم تحديث هذه الوثائق لتعكس أحدث الميزات والتحسينات، مما يضمن وصول المستخدمين إلى أحدث المعلومات وأكثرها شمولاً. diff --git a/docs/v1.15.13/ar/concepts/production-architecture.mdx b/docs/v1.15.13/ar/concepts/production-architecture.mdx new file mode 100644 index 0000000000..11c902c95a --- /dev/null +++ b/docs/v1.15.13/ar/concepts/production-architecture.mdx @@ -0,0 +1,162 @@ +--- +title: بنية الإنتاج +description: أفضل الممارسات لبناء تطبيقات ذكاء اصطناعي جاهزة للإنتاج مع CrewAI +icon: server +mode: "wide" +--- + +# عقلية التدفق أولاً + +عند بناء تطبيقات ذكاء اصطناعي إنتاجية مع CrewAI، **نوصي بالبدء بتدفق (Flow)**. + +بينما يمكن تشغيل أطقم أو وكلاء فرديين، فإن تغليفهم في تدفق يوفر الهيكل اللازم لتطبيق متين وقابل للتوسع. + +## لماذا التدفقات؟ + +1. **إدارة الحالة**: توفر التدفقات طريقة مدمجة لإدارة الحالة عبر مراحل مختلفة من تطبيقك. هذا ضروري لتمرير البيانات بين الأطقم والحفاظ على السياق ومعالجة مدخلات المستخدم. +2. **التحكم**: تتيح لك التدفقات تحديد مسارات تنفيذ دقيقة، بما في ذلك الحلقات والشرطيات ومنطق التفريع. هذا أساسي لمعالجة الحالات الاستثنائية وضمان سلوك تطبيقك بشكل متوقع. +3. **المراقبة**: توفر التدفقات هيكلًا واضحًا يسهّل تتبع التنفيذ وتصحيح الأخطاء ومراقبة الأداء. نوصي باستخدام [تتبع CrewAI](/ar/observability/tracing) للحصول على رؤى تفصيلية. ما عليك سوى تشغيل `crewai login` لتفعيل ميزات المراقبة المجانية. + +## البنية + +يبدو تطبيق CrewAI الإنتاجي النموذجي هكذا: + +```mermaid +graph TD + Start((Start)) --> Flow[Flow Orchestrator] + Flow --> State{State Management} + State --> Step1[Step 1: Data Gathering] + Step1 --> Crew1[Research Crew] + Crew1 --> State + State --> Step2{Condition Check} + Step2 -- "Valid" --> Step3[Step 3: Execution] + Step3 --> Crew2[Action Crew] + Step2 -- "Invalid" --> End((End)) + Crew2 --> End +``` + +### 1. فئة التدفق +فئة `Flow` هي نقطة الدخول. تحدد مخطط الحالة والطرق التي تنفذ منطقك. + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class AppState(BaseModel): + user_input: str = "" + research_results: str = "" + final_report: str = "" + +class ProductionFlow(Flow[AppState]): + @start() + def gather_input(self): + # ... منطق الحصول على المدخلات ... + pass + + @listen(gather_input) + def run_research_crew(self): + # ... تشغيل طاقم ... + pass +``` + +### 2. إدارة الحالة +استخدم نماذج Pydantic لتعريف حالتك. يضمن هذا أمان الأنواع ويوضح البيانات المتاحة في كل مرحلة. + +- **اجعلها بسيطة**: خزّن فقط ما تحتاجه للاستمرار بين المراحل. +- **استخدم بيانات منظمة**: تجنب القواميس غير المنظمة قدر الإمكان. + +### 3. الأطقم كوحدات عمل +فوّض المهام المعقدة إلى الأطقم. يجب أن يكون الطاقم مركّزًا على هدف محدد (مثل "البحث في موضوع"، "كتابة مقال مدونة"). + +- **لا تبالغ في هندسة الأطقم**: اجعلها مركّزة. +- **مرر الحالة بشكل صريح**: مرر البيانات الضرورية من حالة التدفق إلى مدخلات الطاقم. + +```python + @listen(gather_input) + def run_research_crew(self): + crew = ResearchCrew() + result = crew.kickoff(inputs={"topic": self.state.user_input}) + self.state.research_results = result.raw +``` + +## عناصر التحكم الأولية + +استفد من عناصر التحكم الأولية في CrewAI لإضافة المتانة والتحكم إلى أطقمك. + +### 1. حواجز المهام +استخدم [حواجز المهام](/ar/concepts/tasks#task-guardrails) للتحقق من مخرجات المهام قبل قبولها. يضمن هذا أن وكلاءك ينتجون نتائج عالية الجودة. + +```python +def validate_content(result: TaskOutput) -> Tuple[bool, Any]: + if len(result.raw) < 100: + return (False, "Content is too short. Please expand.") + return (True, result.raw) + +task = Task( + ..., + guardrail=validate_content +) +``` + +### 2. المخرجات المنظمة +استخدم دائمًا المخرجات المنظمة (`output_pydantic` أو `output_json`) عند تمرير البيانات بين المهام أو إلى تطبيقك. يمنع هذا أخطاء التحليل ويضمن أمان الأنواع. + +```python +class ResearchResult(BaseModel): + summary: str + sources: List[str] + +task = Task( + ..., + output_pydantic=ResearchResult +) +``` + +### 3. خطافات LLM +استخدم [خطافات LLM](/ar/learn/llm-hooks) لفحص أو تعديل الرسائل قبل إرسالها إلى LLM، أو لتنقية الاستجابات. + +```python +@before_llm_call +def log_request(context): + print(f"Agent {context.agent.role} is calling the LLM...") +``` + +## أنماط النشر + +عند نشر تدفقك، ضع في اعتبارك ما يلي: + +### CrewAI Enterprise +أسهل طريقة لنشر تدفقك هي استخدام CrewAI Enterprise. تتعامل مع البنية التحتية والمصادقة والمراقبة نيابة عنك. + +راجع [دليل النشر](https://docs-platform.crewai.com/platform/ar/guides/deploy-to-amp) للبدء. + +```bash +crewai deploy create +``` + +### التنفيذ غير المتزامن +للمهام طويلة التشغيل، استخدم `kickoff_async` لتجنب حظر واجهتك البرمجية. + +### الاستمرارية +استخدم مزيّن `@persist` لحفظ حالة تدفقك في قاعدة بيانات. يتيح لك هذا استئناف التنفيذ إذا تعطلت العملية أو إذا كنت بحاجة لانتظار مدخلات بشرية. + +```python +@persist +class ProductionFlow(Flow[AppState]): + # ... +``` + +افتراضيًا، يستأنف `@persist` تدفقًا عند توفير `kickoff(inputs={"id": })`، مما يمدّ نفس تاريخ `flow_uuid`. لـ **تفرع** تدفق مستمر إلى نسبٍ جديد — ترطيب الحالة من تشغيل سابق ولكن الكتابة تحت `state.id` جديد — مرّر `restore_from_state_id`: + +```python +flow.kickoff(restore_from_state_id="") +``` + +يحصل التشغيل الجديد على `state.id` جديد (مولّد تلقائيًا، أو `inputs["id"]` إذا تم تثبيته) لذا لا تمتد كتابات `@persist` الخاصة به إلى تاريخ المصدر. الجمع مع `from_checkpoint` يطلق `ValueError`؛ اختر مصدر ترطيب واحدًا. + +## الخلاصة + +- **ابدأ بتدفق.** +- **حدد حالة واضحة.** +- **استخدم الأطقم للمهام المعقدة.** +- **انشر مع API واستمرارية.** diff --git a/docs/v1.15.13/ar/concepts/reasoning.mdx b/docs/v1.15.13/ar/concepts/reasoning.mdx new file mode 100644 index 0000000000..33ec1d6e7b --- /dev/null +++ b/docs/v1.15.13/ar/concepts/reasoning.mdx @@ -0,0 +1,148 @@ +--- +title: الاستدلال +description: "تعرّف على كيفية تفعيل واستخدام استدلال الوكيل لتحسين تنفيذ المهام." +icon: brain +mode: "wide" +--- + +## نظرة عامة + +استدلال الوكيل هو ميزة تتيح للوكلاء التأمل في المهمة وإنشاء خطة قبل التنفيذ. يساعد هذا الوكلاء على التعامل مع المهام بشكل أكثر منهجية ويضمن استعدادهم لأداء العمل المطلوب. + +## الاستخدام + +لتفعيل الاستدلال لوكيل، ما عليك سوى تعيين `reasoning=True` عند إنشاء الوكيل: + +```python +from crewai import Agent + +agent = Agent( + role="Data Analyst", + goal="Analyze complex datasets and provide insights", + backstory="You are an experienced data analyst with expertise in finding patterns in complex data.", + reasoning=True, # تفعيل الاستدلال + max_reasoning_attempts=3 # اختياري: تعيين حد أقصى لمحاولات الاستدلال +) +``` + +## كيف يعمل + +عند تفعيل الاستدلال، قبل تنفيذ المهمة، سيقوم الوكيل بما يلي: + +1. التأمل في المهمة وإنشاء خطة مفصلة +2. تقييم ما إذا كان مستعدًا لتنفيذ المهمة +3. تحسين الخطة حسب الحاجة حتى يصبح مستعدًا أو يصل إلى max_reasoning_attempts +4. حقن خطة الاستدلال في وصف المهمة قبل التنفيذ + +تساعد هذه العملية الوكيل على تقسيم المهام المعقدة إلى خطوات يمكن إدارتها وتحديد التحديات المحتملة قبل البدء. + +## خيارات التهيئة + + + تفعيل أو تعطيل الاستدلال + + + + الحد الأقصى لعدد المحاولات لتحسين الخطة قبل المتابعة بالتنفيذ. إذا كانت القيمة None (الافتراضي)، سيستمر الوكيل في التحسين حتى يصبح مستعدًا. + + +## مثال + +إليك مثالًا كاملًا: + +```python +from crewai import Agent, Task, Crew + +# إنشاء وكيل مع تفعيل الاستدلال +analyst = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + backstory="You are an expert data analyst.", + reasoning=True, + max_reasoning_attempts=3 # اختياري: تعيين حد لمحاولات الاستدلال +) + +# إنشاء مهمة +analysis_task = Task( + description="Analyze the provided sales data and identify key trends.", + expected_output="A report highlighting the top 3 sales trends.", + agent=analyst +) + +# إنشاء طاقم وتشغيل المهمة +crew = Crew(agents=[analyst], tasks=[analysis_task]) +result = crew.kickoff() + +print(result) +``` + +## معالجة الأخطاء + +صُممت عملية الاستدلال لتكون متينة، مع معالجة أخطاء مدمجة. إذا حدث خطأ أثناء الاستدلال، سيتابع الوكيل تنفيذ المهمة بدون خطة الاستدلال. يضمن هذا إمكانية تنفيذ المهام حتى في حالة فشل عملية الاستدلال. + +إليك كيفية التعامل مع الأخطاء المحتملة في الكود الخاص بك: + +```python +from crewai import Agent, Task +import logging + +# إعداد التسجيل لالتقاط أي أخطاء في الاستدلال +logging.basicConfig(level=logging.INFO) + +# إنشاء وكيل مع تفعيل الاستدلال +agent = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + reasoning=True, + max_reasoning_attempts=3 +) + +# إنشاء مهمة +task = Task( + description="Analyze the provided sales data and identify key trends.", + expected_output="A report highlighting the top 3 sales trends.", + agent=agent +) + +# تنفيذ المهمة +# إذا حدث خطأ أثناء الاستدلال، سيتم تسجيله وسيستمر التنفيذ +result = agent.execute_task(task) +``` + +## مثال على مخرجات الاستدلال + +إليك مثالًا على شكل خطة الاستدلال لمهمة تحليل البيانات: + +``` +Task: Analyze the provided sales data and identify key trends. + +Reasoning Plan: +I'll analyze the sales data to identify the top 3 trends. + +1. Understanding of the task: + I need to analyze sales data to identify key trends that would be valuable for business decision-making. + +2. Key steps I'll take: + - First, I'll examine the data structure to understand what fields are available + - Then I'll perform exploratory data analysis to identify patterns + - Next, I'll analyze sales by time periods to identify temporal trends + - I'll also analyze sales by product categories and customer segments + - Finally, I'll identify the top 3 most significant trends + +3. Approach to challenges: + - If the data has missing values, I'll decide whether to fill or filter them + - If the data has outliers, I'll investigate whether they're valid data points or errors + - If trends aren't immediately obvious, I'll apply statistical methods to uncover patterns + +4. Use of available tools: + - I'll use data analysis tools to explore and visualize the data + - I'll use statistical tools to identify significant patterns + - I'll use knowledge retrieval to access relevant information about sales analysis + +5. Expected outcome: + A concise report highlighting the top 3 sales trends with supporting evidence from the data. + +READY: I am ready to execute the task. +``` + +تساعد خطة الاستدلال هذه الوكيل على تنظيم نهجه تجاه المهمة، والنظر في التحديات المحتملة، وضمان تقديم المخرجات المتوقعة. diff --git a/docs/v1.15.13/ar/concepts/skills.mdx b/docs/v1.15.13/ar/concepts/skills.mdx new file mode 100644 index 0000000000..faef071d3d --- /dev/null +++ b/docs/v1.15.13/ar/concepts/skills.mdx @@ -0,0 +1,373 @@ +--- +title: المهارات +description: حزم المهارات المبنية على نظام الملفات التي تحقن خبرة المجال والتعليمات في إرشادات الوكلاء. +icon: bolt +mode: "wide" +--- + +## نظرة عامة + +المهارات هي مجلدات مستقلة توفر للوكلاء **تعليمات وإرشادات ومواد مرجعية خاصة بالمجال**. تُعرّف كل مهارة بملف `SKILL.md` يحتوي على بيانات وصفية YAML ومحتوى Markdown. + +عند التفعيل، يتم حقن تعليمات المهارة مباشرة في إرشادات مهمة الوكيل — مما يمنح الوكيل خبرة دون الحاجة لأي تغييرات في الكود. + + +**المهارات ليست أدوات.** هذه هي نقطة الارتباك الأكثر شيوعًا. + +- **المهارات** تحقن *تعليمات وسياق* في إرشادات الوكيل. تخبر الوكيل *كيف يفكر* في مشكلة ما. +- **الأدوات** تمنح الوكيل *دوال قابلة للاستدعاء* لاتخاذ إجراءات (البحث، قراءة الملفات، استدعاء APIs). + +غالبًا ما تحتاج **كليهما**: مهارات للخبرة، وأدوات للإجراء. يتم تكوينهما بشكل مستقل ويُكمّلان بعضهما. + + +--- + +## البداية السريعة + +### 1. إنشاء مهارة باستخدام سطر الأوامر (CLI) + +واجهة سطر الأوامر هي الطريقة المدعومة لإنشاء مهارة — فهي تُنشئ لك هيكل المجلد وملف `SKILL.md` صالحًا: + +```shell Terminal +crewai skill create code-review +``` + +داخل مشروع طاقم (حيث يوجد `pyproject.toml`) يُنشئ هذا الأمر `./skills/code-review/`؛ وخارج المشروع يُنشئ `./code-review/` في المجلد الحالي (يمكنك فرض هذا السلوك باستخدام `--no-project`): + +``` +skills/ +└── code-review/ + ├── SKILL.md # Required — instructions (pre-filled template) + ├── references/ # Optional — reference docs + ├── scripts/ # Optional — executable scripts + └── assets/ # Optional — static files +``` + +### 2. كتابة SKILL.md الخاص بك + +```markdown +--- +name: code-review +description: Guidelines for conducting thorough code reviews with focus on security and performance. +metadata: + author: your-team + version: "1.0" +--- + +## إرشادات مراجعة الكود + +عند مراجعة الكود، اتبع قائمة التحقق هذه: + +1. **الأمان**: تحقق من ثغرات الحقن وتجاوز المصادقة وكشف البيانات +2. **الأداء**: ابحث عن استعلامات N+1 والتخصيصات غير الضرورية والاستدعاءات المحظورة +3. **القابلية للقراءة**: تأكد من وضوح التسمية والتعليقات المناسبة والأسلوب المتسق +4. **الاختبارات**: تحقق من تغطية اختبار كافية للوظائف الجديدة + +### مستويات الخطورة +- **حرج**: ثغرات أمنية، مخاطر فقدان البيانات → حظر الدمج +- **رئيسي**: مشاكل أداء، أخطاء منطقية → طلب تغييرات +- **ثانوي**: مسائل أسلوبية، اقتراحات تسمية → الموافقة مع تعليقات +``` + +### 3. ربطها بوكيل + +```python +from crewai import Agent +from crewai_tools import GithubSearchTool, FileReadTool + +reviewer = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["./skills"], # يحقن إرشادات المراجعة + tools=[GithubSearchTool(), FileReadTool()], # يسمح للوكيل بقراءة الكود +) +``` + +الوكيل الآن لديه **خبرة** (من المهارة) و**قدرات** (من الأدوات) معًا. + +--- + +## المهارات + الأدوات: العمل معًا + +إليك أنماط شائعة توضح كيف تُكمّل المهارات والأدوات بعضهما: + +### النمط 1: مهارات فقط (خبرة المجال، بدون إجراءات مطلوبة) + +استخدم عندما يحتاج الوكيل لتعليمات محددة لكن لا يحتاج لاستدعاء خدمات خارجية: + +```python +agent = Agent( + role="Technical Writer", + goal="Write clear API documentation", + backstory="Expert technical writer", + skills=["./skills/api-docs-style"], # إرشادات وقوالب الكتابة + # لا حاجة لأدوات — الوكيل يكتب بناءً على السياق المقدم +) +``` + +### النمط 2: أدوات فقط (إجراءات، بدون خبرة خاصة) + +استخدم عندما يحتاج الوكيل لاتخاذ إجراءات لكن لا يحتاج لتعليمات مجال محددة: + +```python +from crewai_tools import SerperDevTool, ScrapeWebsiteTool + +agent = Agent( + role="Web Researcher", + goal="Find information about a topic", + backstory="Skilled at finding information online", + tools=[SerperDevTool(), ScrapeWebsiteTool()], # يمكنه البحث والاستخراج + # لا حاجة لمهارات — البحث العام لا يحتاج إرشادات خاصة +) +``` + +### النمط 3: مهارات + أدوات (خبرة وإجراءات) + +النمط الأكثر شيوعًا في العالم الحقيقي. المهارة توفر *كيف* تقترب من العمل؛ الأدوات توفر *ما* يمكن للوكيل فعله: + +```python +from crewai_tools import SerperDevTool, FileReadTool, CodeInterpreterTool + +analyst = Agent( + role="Security Analyst", + goal="Audit infrastructure for vulnerabilities", + backstory="Expert in cloud security and compliance", + skills=["./skills/security-audit"], # منهجية وقوائم تحقق التدقيق + tools=[ + SerperDevTool(), # البحث عن ثغرات معروفة + FileReadTool(), # قراءة ملفات التكوين + CodeInterpreterTool(), # تشغيل سكربتات التحليل + ], +) +``` + +### النمط 4: مهارات + MCP + +المهارات تعمل مع خوادم MCP بنفس الطريقة التي تعمل بها مع الأدوات: + +```python +agent = Agent( + role="Data Analyst", + goal="Analyze customer data and generate reports", + backstory="Expert data analyst with strong statistical background", + skills=["./skills/data-analysis"], # منهجية التحليل + mcps=["https://data-warehouse.example.com/sse"], # وصول بيانات عن بُعد +) +``` + +### النمط 5: مهارات + تطبيقات + +المهارات يمكن أن توجّه كيف يستخدم الوكيل تكاملات المنصة: + +```python +agent = Agent( + role="Customer Support Agent", + goal="Respond to customer inquiries professionally", + backstory="Experienced support representative", + skills=["./skills/support-playbook"], # قوالب الردود وقواعد التصعيد + apps=["gmail", "zendesk"], # يمكنه إرسال رسائل بريد وتحديث التذاكر +) +``` + +--- + +## إنشاء المهارات ونشرها وتثبيتها + +للمهارات دورة حياة كاملة تُدار عبر واجهة سطر الأوامر: **أنشئها باستخدام `crewai skill create`، وانشرها باستخدام `crewai skill publish`** — إنشاء المجلدات يدويًا يصلح للتجارب المحلية، لكن واجهة سطر الأوامر هي سير العمل المقصود، وهي تحافظ على صحة هيكل المهارة وبياناتها الوصفية. + +### الإنشاء + +```shell Terminal +crewai skill create my-skill +``` + +يُنشئ هذا الأمر المجلد (داخل `./skills/` في مشروع الطاقم) مع قالب `SKILL.md`، بالإضافة إلى مجلدات فارغة `scripts/` و `references/` و `assets/`. عدّل `SKILL.md` لتعريف التعليمات. + +### النشر + +نفّذ الأمر من داخل مجلد المهارة (حيث يوجد `SKILL.md`): + +```shell Terminal +cd skills/my-skill +crewai skill publish +``` + +يقرأ النشر الحقول `name` و `description` و `metadata.version` من البيانات الوصفية في مقدمة `SKILL.md` ويدفع المهارة إلى سجل CrewAI. **المهارات المنشورة تكون دائمًا مقيّدة بنطاق مؤسستك** — مثل الأدوات، لا يستطيع رؤيتها وتثبيتها إلا أعضاء المؤسسة الناشرة؛ ولا توجد رؤية عامة. أعلام مفيدة: + +| العلم | التأثير | +| :--- | :--- | +| `--org ` | النشر تحت مؤسسة محددة (يتجاوز الإعدادات). | +| `--force` | تخطي التحقق من حالة git (تغييرات غير مُثبتة، إلخ). | + +### التثبيت + +ثبّت مهارة منشورة عبر مرجعها `@org/name`: + +```shell Terminal +crewai skill install @acme/code-review +``` + +داخل مشروع الطاقم تُثبَّت المهارة في `./skills/{name}/`؛ وخارج المشروع تذهب إلى ذاكرة التخزين المؤقتة المشتركة في `~/.crewai/skills/{org}/{name}/`. + +يمكن للوكلاء أيضًا الإشارة إلى مهارات السجل مباشرة — يتم حلّها من ذاكرة التخزين المؤقتة المحلية (أو من مجلد `skills/` في المشروع) وقت التشغيل: + +```python +agent = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["@acme/code-review"], # registry ref, resolved locally +) +``` + +### عرض القائمة + +```shell Terminal +crewai skill list +``` + +يعرض المهارات المثبّتة من مجلد المشروع `./skills/` ومن ذاكرة التخزين المؤقتة العامة معًا، مع إصداراتها ومساراتها. + +--- + +## المهارات على مستوى الطاقم + +يمكن تعيين المهارات على الطاقم لتُطبّق على **جميع الوكلاء**: + +```python +from crewai import Crew + +crew = Crew( + agents=[researcher, writer, reviewer], + tasks=[research_task, write_task, review_task], + skills=["./skills"], # جميع الوكلاء يحصلون على هذه المهارات +) +``` + +المهارات على مستوى الوكيل لها الأولوية — إذا تم اكتشاف نفس المهارة في كلا المستويين، يتم استخدام نسخة الوكيل. + +--- + +## تنسيق SKILL.md + +```markdown +--- +name: my-skill +description: وصف قصير لما تفعله هذه المهارة ومتى تُستخدم. +license: Apache-2.0 # اختياري +compatibility: crewai>=0.1.0 # اختياري +metadata: # اختياري + author: your-name + version: "1.0" +allowed-tools: web-search file-read # اختياري، تجريبي +--- + +التعليمات للوكيل تُكتب هنا. يتم حقن محتوى Markdown هذا +في إرشادات الوكيل عند تفعيل المهارة. +``` + +### حقول البيانات الوصفية + +| الحقل | مطلوب | الوصف | +| :-------------- | :------- | :----------------------------------------------------------------------- | +| `name` | نعم | 1-64 حرف. أحرف صغيرة أبجدية رقمية وشرطات. يجب أن يطابق اسم المجلد. | +| `description` | نعم | 1-1024 حرف. يصف ما تفعله المهارة ومتى تُستخدم. | +| `license` | لا | اسم الترخيص أو مرجع لملف ترخيص مضمّن. | +| `compatibility` | لا | حد أقصى 500 حرف. متطلبات البيئة (منتجات، حزم، شبكة). | +| `metadata` | لا | تعيين مفتاح-قيمة نصي عشوائي. | +| `allowed-tools` | لا | قائمة أدوات معتمدة مسبقًا مفصولة بمسافات. تجريبي. | + +--- + +## هيكل المجلد + +``` +my-skill/ +├── SKILL.md # مطلوب — البيانات الوصفية + التعليمات +├── scripts/ # اختياري — سكربتات قابلة للتنفيذ +├── references/ # اختياري — مستندات مرجعية +└── assets/ # اختياري — ملفات ثابتة (إعدادات، بيانات) +``` + +يجب أن يتطابق اسم المجلد مع حقل `name` في `SKILL.md`. مجلدات `scripts/` و `references/` و `assets/` متاحة في مسار المهارة `path` للوكلاء الذين يحتاجون للإشارة إلى الملفات مباشرة. + +--- + +## المهارات المحمّلة مسبقًا + +للمزيد من التحكم، يمكنك اكتشاف المهارات وتفعيلها برمجيًا: + +```python +from pathlib import Path +from crewai.skills import discover_skills, activate_skill + +# اكتشاف جميع المهارات في مجلد +skills = discover_skills(Path("./skills")) + +# تفعيلها (تحميل محتوى SKILL.md الكامل) +activated = [activate_skill(s) for s in skills] + +# تمرير إلى وكيل +agent = Agent( + role="Researcher", + goal="Find relevant information", + backstory="An expert researcher.", + skills=activated, +) +``` + +--- + +## كيف يتم تحميل المهارات + +تستخدم المهارات **الكشف التدريجي** — تحمّل فقط ما هو مطلوب في كل مرحلة: + +| المرحلة | ما يتم تحميله | متى | +| :--------- | :------------------------------------ | :------------------ | +| الاكتشاف | الاسم، الوصف، حقول البيانات الوصفية | `discover_skills()` | +| التفعيل | نص محتوى SKILL.md الكامل | `activate_skill()` | + +أثناء التنفيذ العادي للوكيل (تمرير مسارات المجلدات عبر `skills=["./skills"]`)، يتم اكتشاف المهارات وتفعيلها تلقائيًا. التحميل التدريجي مهم فقط عند استخدام الواجهة البرمجية. + +--- + +## المهارات مقابل المعرفة + +كلا المهارات والمعرفة تُعدّل إرشادات الوكيل، لكنهما يخدمان أغراضًا مختلفة: + +| الجانب | المهارات | المعرفة | +| :--- | :--- | :--- | +| **ما توفره** | تعليمات، إجراءات، إرشادات | حقائق، بيانات، معلومات | +| **كيف تُخزّن** | ملفات Markdown (SKILL.md) | مُضمّنة في مخزن متجهي (ChromaDB) | +| **كيف تُسترجع** | يتم حقن المحتوى الكامل في الإرشادات | البحث الدلالي يجد الأجزاء ذات الصلة | +| **الأفضل لـ** | المنهجيات، قوائم التحقق، أدلة الأسلوب | مستندات الشركة، معلومات المنتج، بيانات مرجعية | +| **يُعيّن عبر** | `skills=["./skills"]` | `knowledge_sources=[source]` | + +**القاعدة العامة:** إذا كان الوكيل يحتاج لاتباع *عملية*، استخدم مهارة. إذا كان يحتاج للرجوع إلى *بيانات*، استخدم المعرفة. + +--- + +## الأسئلة الشائعة + + + + يعتمد على حالة الاستخدام. المهارات والأدوات **مستقلتان** — يمكنك استخدام أيّ منهما أو كليهما أو لا شيء. + + - **مهارات فقط**: عندما يحتاج الوكيل خبرة لكن لا يحتاج إجراءات خارجية (مثال: الكتابة بإرشادات أسلوبية) + - **أدوات فقط**: عندما يحتاج الوكيل إجراءات لكن لا يحتاج منهجية خاصة (مثال: بحث بسيط على الويب) + - **كليهما**: عندما يحتاج الوكيل خبرة وإجراءات (مثال: تدقيق أمني بقوائم تحقق محددة وقدرة على فحص الكود) + + + + **لا.** حقل `allowed-tools` في SKILL.md هو بيانات وصفية تجريبية فقط — لا يُنشئ أو يحقن أي أدوات. يجب عليك دائمًا تعيين الأدوات بشكل منفصل عبر `tools=[]` أو `mcps=[]` أو `apps=[]`. + + + + المهارة على مستوى الوكيل لها الأولوية. يتم إزالة التكرار حسب الاسم — مهارات الوكيل تُعالج أولاً، لذا إذا ظهر نفس اسم المهارة في كلا المستويين، تُستخدم نسخة الوكيل. + + + + هناك تحذير ناعم عند 50,000 حرف، لكن بدون حد صارم. حافظ على تركيز المهارات وإيجازها للحصول على أفضل النتائج — الحقن الكبيرة في الإرشادات قد تُشتت انتباه الوكيل. + + diff --git a/docs/v1.15.13/ar/concepts/tasks.mdx b/docs/v1.15.13/ar/concepts/tasks.mdx new file mode 100644 index 0000000000..e1fa1027c9 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/tasks.mdx @@ -0,0 +1,1120 @@ +--- +title: المهام +description: دليل مفصل حول إدارة وإنشاء المهام ضمن إطار عمل CrewAI. +icon: list-check +mode: "wide" +--- + +## نظرة عامة + +في إطار عمل CrewAI، المهمة (`Task`) هي تكليف محدد يُنجزه وكيل (`Agent`). + +توفر المهام جميع التفاصيل اللازمة للتنفيذ، مثل الوصف والوكيل المسؤول والأدوات المطلوبة والمزيد، مما يسهّل مجموعة واسعة من تعقيدات الإجراءات. + +يمكن أن تكون المهام في CrewAI تعاونية، تتطلب عمل وكلاء متعددين معًا. تتم إدارة ذلك من خلال خصائص المهمة ويتم تنسيقه بواسطة عملية Crew، مما يعزز العمل الجماعي والكفاءة. + + +يتضمن CrewAI AMP منشئ مهام مرئي في Crew Studio يبسّط إنشاء المهام المعقدة وربطها. صمم تدفقات مهامك بصريًا واختبرها في الوقت الفعلي دون كتابة كود. + +![Task Builder Screenshot](/images/enterprise/crew-studio-interface.png) + +يتيح منشئ المهام المرئي: + +- إنشاء المهام بالسحب والإفلات +- تبعيات المهام المرئية والتدفق +- الاختبار والتحقق في الوقت الفعلي +- المشاركة والتعاون بسهولة + + +### تدفق تنفيذ المهام + +يمكن تنفيذ المهام بطريقتين: + +- **تسلسلي**: تُنفَّذ المهام بالترتيب الذي تم تعريفها به +- **هرمي**: تُعيَّن المهام للوكلاء بناءً على أدوارهم وخبراتهم + +يتم تحديد تدفق التنفيذ عند إنشاء الفريق: + +```python Code +crew = Crew( + agents=[agent1, agent2], + tasks=[task1, task2], + process=Process.sequential # or Process.hierarchical +) +``` + +## خصائص المهمة + +| الخاصية | المعاملات | النوع | الوصف | +| :------------------------------------- | :---------------------- | :-------------------------- | :-------------------------------------------------------------------------------------------------------------- | +| **الوصف** | `description` | `str` | بيان واضح وموجز لما تستلزمه المهمة. | +| **المخرجات المتوقعة** | `expected_output` | `str` | وصف مفصل لما يبدو عليه إتمام المهمة. | +| **الاسم** _(اختياري)_ | `name` | `Optional[str]` | معرّف اسمي للمهمة. | +| **الوكيل** _(اختياري)_ | `agent` | `Optional[BaseAgent]` | الوكيل المسؤول عن تنفيذ المهمة. | +| **الأدوات** _(اختياري)_ | `tools` | `List[BaseTool]` | الأدوات/الموارد التي يقتصر الوكيل على استخدامها لهذه المهمة. | +| **السياق** _(اختياري)_ | `context` | `Optional[List["Task"]]` | مهام أخرى ستُستخدم مخرجاتها كسياق لهذه المهمة. | +| **التنفيذ غير المتزامن** _(اختياري)_ | `async_execution` | `Optional[bool]` | ما إذا كان يجب تنفيذ المهمة بشكل غير متزامن. الافتراضي False. | +| **المدخلات البشرية** _(اختياري)_ | `human_input` | `Optional[bool]` | ما إذا كان يجب أن يراجع إنسان الإجابة النهائية للوكيل. الافتراضي False. | +| **Markdown** _(اختياري)_ | `markdown` | `Optional[bool]` | ما إذا كان يجب أن توجّه المهمة الوكيل لإعادة الإجابة النهائية بتنسيق Markdown. الافتراضي False. | +| **الإعداد** _(اختياري)_ | `config` | `Optional[Dict[str, Any]]` | معاملات إعداد خاصة بالمهمة. | +| **ملف المخرجات** _(اختياري)_ | `output_file` | `Optional[str]` | مسار الملف لتخزين مخرجات المهمة. | +| **إنشاء المجلد** _(اختياري)_ | `create_directory` | `Optional[bool]` | ما إذا كان يجب إنشاء المجلد لـ output_file إذا لم يكن موجودًا. الافتراضي True. | +| **مخرجات JSON** _(اختياري)_ | `output_json` | `Optional[Type[BaseModel]]` | نموذج Pydantic لهيكلة مخرجات JSON. | +| **مخرجات Pydantic** _(اختياري)_ | `output_pydantic` | `Optional[Type[BaseModel]]` | نموذج Pydantic لمخرجات المهمة. | +| **دالة الاسترجاع** _(اختياري)_ | `callback` | `Optional[Any]` | دالة/كائن يُنفَّذ بعد اكتمال المهمة. | +| **حارس** _(اختياري)_ | `guardrail` | `Optional[Callable]` | دالة للتحقق من مخرجات المهمة قبل الانتقال إلى المهمة التالية. | +| **حراس** _(اختياري)_ | `guardrails` | `Optional[List[Callable]]` | قائمة حراس للتحقق من مخرجات المهمة قبل الانتقال إلى المهمة التالية. | +| **أقصى محاولات الحارس** _(اختياري)_ | `guardrail_max_retries` | `Optional[int]` | الحد الأقصى لعدد المحاولات عند فشل التحقق من الحارس. الافتراضي 3. | + + + خاصية المهمة `max_retries` مهملة وستتم إزالتها في v1.0.0. + استخدم `guardrail_max_retries` بدلاً منها للتحكم في محاولات الإعادة عند فشل الحارس. + + +## إنشاء المهام + +هناك طريقتان شائعتان لإنشاء المهام في CrewAI: باستخدام **تهيئة JSONC (الموصى بها للـ crews الجديدة)** أو تعريفها **مباشرة في الكود**. + +### تهيئة JSONC (موصى بها) + +المشاريع الجديدة التي تُنشأ عبر `crewai create crew ` تعرّف المهام في `crew.jsonc`. + +````jsonc crew.jsonc +{ + "name": "Research Crew", + "agents": ["researcher", "reporting_analyst"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research about {topic}.", + "expected_output": "A list of the most relevant information about {topic}.", + "agent": "researcher" + }, + { + "name": "reporting_task", + "description": "Review the research and expand it into a detailed report.", + "expected_output": "A polished markdown report.", + "agent": "reporting_analyst", + "context": ["research_task"], + "markdown": true, + "output_file": "report.md" + } + ], + "inputs": { + "topic": "AI Agents" + } +} +```` + +كل مهمة تحتاج إلى `description` و `expected_output`. يجب أن يطابق `agent` اسم Agent مذكورًا في `agents`. يشير `context` إلى أسماء مهام سابقة فقط؛ وترفض الإشارات إلى مهام لاحقة. + +### إعداد YAML الكلاسيكي + +المشاريع الكلاسيكية التي تُنشأ عبر `crewai create crew --classic` تستخدم `config/tasks.yaml` وفئة `@CrewBase` في `crew.py`. + +يظل إعداد YAML مدعومًا للمشاريع الحالية المبنية بـ Python/YAML وللفِرق التي تفضل تعريف المهام من خلال فئة `@CrewBase`. + +بعد إنشاء مشروع كلاسيكي، انتقل إلى ملف `src//config/tasks.yaml` وعدّل القالب ليتوافق مع متطلبات مهامك المحددة. + + +المتغيرات في ملفات YAML (مثل `{topic}`) سيتم استبدالها بالقيم من مدخلاتك عند تشغيل الفريق: +```python Code +crew.kickoff(inputs={'topic': 'AI Agents'}) +``` + + +إليك مثال على كيفية إعداد المهام باستخدام YAML: + +````yaml tasks.yaml +research_task: + description: > + Conduct a thorough research about {topic} + Make sure you find any interesting and relevant information given + the current year is 2025. + expected_output: > + A list with 10 bullet points of the most relevant information about {topic} + agent: researcher + +reporting_task: + description: > + Review the context you got and expand each topic into a full section for a report. + Make sure the report is detailed and contains any and all relevant information. + expected_output: > + A fully fledge reports with the mains topics, each with a full section of information. + Formatted as markdown without '```' + agent: reporting_analyst + markdown: true + output_file: report.md +```` + +لاستخدام إعداد YAML هذا في كودك، أنشئ فئة فريق ترث من `CrewBase`: + +```python crew.py +# src//crew.py + +from crewai import Agent, Crew, Process, Task +from crewai.project import CrewBase, agent, crew, task +from crewai_tools import SerperDevTool + +@CrewBase +class LatestAiDevelopmentCrew(): + """LatestAiDevelopment crew""" + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], # type: ignore[index] + verbose=True, + tools=[SerperDevTool()] + ) + + @agent + def reporting_analyst(self) -> Agent: + return Agent( + config=self.agents_config['reporting_analyst'], # type: ignore[index] + verbose=True + ) + + @task + def research_task(self) -> Task: + return Task( + config=self.tasks_config['research_task'] # type: ignore[index] + ) + + @task + def reporting_task(self) -> Task: + return Task( + config=self.tasks_config['reporting_task'] # type: ignore[index] + ) + + @crew + def crew(self) -> Crew: + return Crew( + agents=[ + self.researcher(), + self.reporting_analyst() + ], + tasks=[ + self.research_task(), + self.reporting_task() + ], + process=Process.sequential + ) +``` + + + يجب أن تتطابق الأسماء المستخدمة في ملفات YAML (`agents.yaml` و `tasks.yaml`) + مع أسماء الدوال في كود Python الخاص بك. + + +### تعريف مباشر في الكود (بديل) + +بدلاً من ذلك، يمكنك تعريف المهام مباشرة في كودك دون استخدام إعداد YAML: + +```python task.py +from crewai import Task + +research_task = Task( + description=""" + Conduct a thorough research about AI Agents. + Make sure you find any interesting and relevant information given + the current year is 2025. + """, + expected_output=""" + A list with 10 bullet points of the most relevant information about AI Agents + """, + agent=researcher +) + +reporting_task = Task( + description=""" + Review the context you got and expand each topic into a full section for a report. + Make sure the report is detailed and contains any and all relevant information. + """, + expected_output=""" + A fully fledge reports with the mains topics, each with a full section of information. + """, + agent=reporting_analyst, + markdown=True, # Enable markdown formatting for the final output + output_file="report.md" +) +``` + + + حدد وكيلًا (`agent`) مباشرة للتعيين أو دع عملية CrewAI `hierarchical` + تقرر بناءً على الأدوار والتوفر وغيرها. + + +## مخرجات المهمة + +فهم مخرجات المهام أمر بالغ الأهمية لبناء سير عمل ذكاء اصطناعي فعال. يوفر CrewAI طريقة منظمة للتعامل مع نتائج المهام من خلال فئة `TaskOutput`، التي تدعم تنسيقات مخرجات متعددة ويمكن تمريرها بسهولة بين المهام. + +يتم تغليف مخرجات المهمة في إطار عمل CrewAI داخل فئة `TaskOutput`. توفر هذه الفئة طريقة منظمة للوصول إلى نتائج المهمة، بما في ذلك تنسيقات متنوعة مثل المخرجات الخام و JSON ونماذج Pydantic. + +بشكل افتراضي، سيتضمن `TaskOutput` المخرجات `raw` فقط. سيتضمن `TaskOutput` مخرجات `pydantic` أو `json_dict` فقط إذا تم إعداد كائن `Task` الأصلي مع `output_pydantic` أو `output_json` على التوالي. + +### خصائص مخرجات المهمة + +| الخاصية | المعاملات | النوع | الوصف | +| :---------------- | :-------------- | :------------------------- | :------------------------------------------------------------------------------------------------- | +| **الوصف** | `description` | `str` | وصف المهمة. | +| **الملخص** | `summary` | `Optional[str]` | ملخص المهمة، يُنشأ تلقائيًا من أول 10 كلمات من الوصف. | +| **الخام** | `raw` | `str` | المخرجات الخام للمهمة. هذا هو التنسيق الافتراضي للمخرجات. | +| **Pydantic** | `pydantic` | `Optional[BaseModel]` | كائن نموذج Pydantic يمثل المخرجات المنظمة للمهمة. | +| **قاموس JSON** | `json_dict` | `Optional[Dict[str, Any]]` | قاموس يمثل مخرجات JSON للمهمة. | +| **الوكيل** | `agent` | `str` | الوكيل الذي نفذ المهمة. | +| **تنسيق المخرجات**| `output_format` | `OutputFormat` | تنسيق مخرجات المهمة، مع خيارات تشمل RAW و JSON و Pydantic. الافتراضي هو RAW. | +| **الرسائل** | `messages` | `list[LLMMessage]` | الرسائل من آخر تنفيذ للمهمة. | + +### دوال وخصائص المهمة + +| الدالة/الخاصية | الوصف | +| :-------------- | :------------------------------------------------------------------------------------------------ | +| **json** | تُعيد تمثيل سلسلة JSON لمخرجات المهمة إذا كان تنسيق المخرجات JSON. | +| **to_dict** | تحوّل مخرجات JSON و Pydantic إلى قاموس. | +| **str** | تُعيد التمثيل النصي لمخرجات المهمة، مع أولوية Pydantic ثم JSON ثم الخام. | + +### الوصول إلى مخرجات المهمة + +بمجرد تنفيذ المهمة، يمكن الوصول إلى مخرجاتها من خلال خاصية `output` لكائن `Task`. توفر فئة `TaskOutput` طرقًا متنوعة للتفاعل مع هذه المخرجات وعرضها. + +#### مثال + +```python Code +# Example task +task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +# Execute the crew +crew = Crew( + agents=[research_agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() + +# Accessing the task output +task_output = task.output + +print(f"Task Description: {task_output.description}") +print(f"Task Summary: {task_output.summary}") +print(f"Raw Output: {task_output.raw}") +if task_output.json_dict: + print(f"JSON Output: {json.dumps(task_output.json_dict, indent=2)}") +if task_output.pydantic: + print(f"Pydantic Output: {task_output.pydantic}") +``` + +## تنسيق مخرجات Markdown + +يتيح معامل `markdown` تنسيق Markdown تلقائي لمخرجات المهام. عند تعيينه إلى `True`، ستوجّه المهمة الوكيل لتنسيق الإجابة النهائية باستخدام صيغة Markdown الصحيحة. + +### استخدام تنسيق Markdown + +```python Code +# Example task with markdown formatting enabled +formatted_task = Task( + description="Create a comprehensive report on AI trends", + expected_output="A well-structured report with headers, sections, and bullet points", + agent=reporter_agent, + markdown=True # Enable automatic markdown formatting +) +``` + +عند تعيين `markdown=True`، سيتلقى الوكيل تعليمات إضافية لتنسيق المخرجات باستخدام: + +- `#` للعناوين +- `**text**` للنص العريض +- `*text*` للنص المائل +- `-` أو `*` للقوائم النقطية +- `` `code` `` للكود المضمّن +- ` `language ``` لكتل الكود + +### إعداد YAML مع Markdown + +```yaml tasks.yaml +analysis_task: + description: > + Analyze the market data and create a detailed report + expected_output: > + A comprehensive analysis with charts and key findings + agent: analyst + markdown: true # Enable markdown formatting + output_file: analysis.md +``` + +### فوائد مخرجات Markdown + +- **تنسيق متسق**: يضمن اتباع جميع المخرجات لاتفاقيات Markdown الصحيحة +- **قابلية قراءة أفضل**: محتوى منظم مع عناوين وقوائم وتأكيد +- **جاهز للتوثيق**: يمكن استخدام المخرجات مباشرة في أنظمة التوثيق +- **توافق عبر المنصات**: Markdown مدعوم عالميًا + + + يتم إضافة تعليمات تنسيق Markdown تلقائيًا إلى موجّه المهمة + عند تعيين `markdown=True`، لذا لا تحتاج إلى تحديد متطلبات التنسيق + في وصف المهمة. + + +## تبعيات المهام والسياق + +يمكن للمهام الاعتماد على مخرجات مهام أخرى باستخدام خاصية `context`. على سبيل المثال: + +```python Code +research_task = Task( + description="Research the latest developments in AI", + expected_output="A list of recent AI developments", + agent=researcher +) + +analysis_task = Task( + description="Analyze the research findings and identify key trends", + expected_output="Analysis report of AI trends", + agent=analyst, + context=[research_task] # This task will wait for research_task to complete +) +``` + +## حراس المهام + +توفر حراس المهام طريقة للتحقق من مخرجات المهام وتحويلها قبل +تمريرها إلى المهمة التالية. تساعد هذه الميزة في ضمان جودة البيانات وتوفر +تغذية راجعة للوكلاء عندما لا تستوفي مخرجاتهم معايير محددة. + +يدعم CrewAI نوعين من الحراس: + +1. **حراس قائمون على الدوال**: دوال Python مع منطق تحقق مخصص، تمنحك تحكمًا كاملاً في عملية التحقق وتضمن نتائج موثوقة وحتمية. + +2. **حراس قائمون على LLM**: أوصاف نصية تستخدم LLM الخاص بالوكيل للتحقق من المخرجات بناءً على معايير لغة طبيعية. مثالية لمتطلبات التحقق المعقدة أو الذاتية. + +### الحراس القائمون على الدوال + +لإضافة حارس قائم على الدوال إلى مهمة، قدم دالة تحقق من خلال معامل `guardrail`: + +```python Code +from typing import Tuple, Union, Dict, Any +from crewai import TaskOutput + +def validate_blog_content(result: TaskOutput) -> Tuple[bool, Any]: + """Validate blog content meets requirements.""" + try: + # Check word count + word_count = len(result.raw.split()) + if word_count > 200: + return (False, "Blog content exceeds 200 words") + + # Additional validation logic here + return (True, result.raw.strip()) + except Exception as e: + return (False, "Unexpected error during validation") + +blog_task = Task( + description="Write a blog post about AI", + expected_output="A blog post under 200 words", + agent=blog_agent, + guardrail=validate_blog_content # Add the guardrail function +) +``` + +### الحراس القائمون على LLM (أوصاف نصية) + +بدلاً من كتابة دوال تحقق مخصصة، يمكنك استخدام أوصاف نصية تستفيد من التحقق القائم على LLM. عندما تقدم سلسلة نصية لمعامل `guardrail` أو `guardrails`، ينشئ CrewAI تلقائيًا `LLMGuardrail` يستخدم LLM الخاص بالوكيل للتحقق من المخرجات بناءً على وصفك. + +**المتطلبات**: + +- يجب أن يكون للمهمة وكيل (`agent`) مُعيّن (يستخدم الحارس LLM الخاص بالوكيل) +- قدم سلسلة نصية واضحة ووصفية تشرح معايير التحقق + +```python Code +from crewai import Task + +# Single LLM-based guardrail +blog_task = Task( + description="Write a blog post about AI", + expected_output="A blog post under 200 words", + agent=blog_agent, + guardrail="The blog post must be under 200 words and contain no technical jargon" +) +``` + +الحراس القائمون على LLM مفيدون بشكل خاص لـ: + +- **منطق التحقق المعقد** الذي يصعب التعبير عنه برمجيًا +- **المعايير الذاتية** مثل النبرة والأسلوب أو تقييمات الجودة +- **متطلبات اللغة الطبيعية** التي يسهل وصفها أكثر من برمجتها + +سيقوم حارس LLM بما يلي: + +1. تحليل مخرجات المهمة مقابل وصفك +2. إعادة `(True, output)` إذا امتثلت المخرجات للمعايير +3. إعادة `(False, feedback)` مع تغذية راجعة محددة إذا فشل التحقق + +**مثال مع معايير تحقق مفصلة**: + +```python Code +research_task = Task( + description="Research the latest developments in quantum computing", + expected_output="A comprehensive research report", + agent=researcher_agent, + guardrail=""" + The research report must: + - Be at least 1000 words long + - Include at least 5 credible sources + - Cover both technical and practical applications + - Be written in a professional, academic tone + - Avoid speculation or unverified claims + """ +) +``` + +### حراس متعددون + +يمكنك تطبيق حراس متعددين على مهمة باستخدام معامل `guardrails`. تُنفَّذ الحراس المتعددون بالتسلسل، حيث يتلقى كل حارس المخرجات من السابق. يتيح لك هذا سلسلة خطوات التحقق والتحويل. + +يقبل معامل `guardrails`: + +- قائمة من دوال الحراس أو أوصاف نصية +- حارس واحد (دالة أو سلسلة نصية) (مثل `guardrail`) + +**ملاحظة**: إذا تم تقديم `guardrails`، فإنه يأخذ الأولوية على `guardrail`. سيتم تجاهل معامل `guardrail` عند تعيين `guardrails`. + +```python Code +from typing import Tuple, Any +from crewai import TaskOutput, Task + +def validate_word_count(result: TaskOutput) -> Tuple[bool, Any]: + """Validate word count is within limits.""" + word_count = len(result.raw.split()) + if word_count < 100: + return (False, f"Content too short: {word_count} words. Need at least 100 words.") + if word_count > 500: + return (False, f"Content too long: {word_count} words. Maximum is 500 words.") + return (True, result.raw) + +def validate_no_profanity(result: TaskOutput) -> Tuple[bool, Any]: + """Check for inappropriate language.""" + profanity_words = ["badword1", "badword2"] # Example list + content_lower = result.raw.lower() + for word in profanity_words: + if word in content_lower: + return (False, f"Inappropriate language detected: {word}") + return (True, result.raw) + +def format_output(result: TaskOutput) -> Tuple[bool, Any]: + """Format and clean the output.""" + formatted = result.raw.strip() + # Capitalize first letter + formatted = formatted[0].upper() + formatted[1:] if formatted else formatted + return (True, formatted) + +# Apply multiple guardrails sequentially +blog_task = Task( + description="Write a blog post about AI", + expected_output="A well-formatted blog post between 100-500 words", + agent=blog_agent, + guardrails=[ + validate_word_count, # First: validate length + validate_no_profanity, # Second: check content + format_output # Third: format the result + ], + guardrail_max_retries=3 +) +``` + +في هذا المثال، تُنفَّذ الحراس بالترتيب: + +1. `validate_word_count` يتحقق من عدد الكلمات +2. `validate_no_profanity` يتحقق من اللغة غير الملائمة (باستخدام المخرجات من الخطوة 1) +3. `format_output` ينسّق النتيجة النهائية (باستخدام المخرجات من الخطوة 2) + +إذا فشل أي حارس، يتم إرسال الخطأ إلى الوكيل، وتُعاد المهمة حتى `guardrail_max_retries` مرة. + +**مزج الحراس القائمين على الدوال و LLM**: + +يمكنك الجمع بين الحراس القائمين على الدوال والنصية في نفس القائمة: + +```python Code +from typing import Tuple, Any +from crewai import TaskOutput, Task + +def validate_word_count(result: TaskOutput) -> Tuple[bool, Any]: + """Validate word count is within limits.""" + word_count = len(result.raw.split()) + if word_count < 100: + return (False, f"Content too short: {word_count} words. Need at least 100 words.") + if word_count > 500: + return (False, f"Content too long: {word_count} words. Maximum is 500 words.") + return (True, result.raw) + +# Mix function-based and LLM-based guardrails +blog_task = Task( + description="Write a blog post about AI", + expected_output="A well-formatted blog post between 100-500 words", + agent=blog_agent, + guardrails=[ + validate_word_count, # Function-based: precise word count check + "The content must be engaging and suitable for a general audience", # LLM-based: subjective quality check + "The writing style should be clear, concise, and free of technical jargon" # LLM-based: style validation + ], + guardrail_max_retries=3 +) +``` + +يجمع هذا النهج بين دقة التحقق البرمجي ومرونة التقييم القائم على LLM للمعايير الذاتية. + +### متطلبات دالة الحارس + +1. **توقيع الدالة**: + + - يجب أن تقبل معاملًا واحدًا بالضبط (مخرجات المهمة) + - يجب أن تُعيد tuple من `(bool, Any)` + - يُوصى بتلميحات الأنواع لكنها اختيارية + +2. **قيم الإعادة**: + - عند النجاح: تُعيد tuple من `(bool, Any)`. مثال: `(True, validated_result)` + - عند الفشل: تُعيد tuple من `(bool, str)`. مثال: `(False, "Error message explain the failure")` + +### أفضل ممارسات معالجة الأخطاء + +1. **استجابات أخطاء منظمة**: + +```python Code +from crewai import TaskOutput, LLMGuardrail + +def validate_with_context(result: TaskOutput) -> Tuple[bool, Any]: + try: + # Main validation logic + validated_data = perform_validation(result) + return (True, validated_data) + except ValidationError as e: + return (False, f"VALIDATION_ERROR: {str(e)}") + except Exception as e: + return (False, str(e)) +``` + +2. **فئات الأخطاء**: + + - استخدم رموز خطأ محددة + - ضمّن السياق ذا الصلة + - قدم تغذية راجعة قابلة للتنفيذ + +3. **سلسلة التحقق**: + +```python Code +from typing import Any, Dict, List, Tuple, Union +from crewai import TaskOutput + +def complex_validation(result: TaskOutput) -> Tuple[bool, Any]: + """Chain multiple validation steps.""" + # Step 1: Basic validation + if not result: + return (False, "Empty result") + + # Step 2: Content validation + try: + validated = validate_content(result) + if not validated: + return (False, "Invalid content") + + # Step 3: Format validation + formatted = format_output(validated) + return (True, formatted) + except Exception as e: + return (False, str(e)) +``` + +### التعامل مع نتائج الحارس + +عندما يُعيد حارس `(False, error)`: + +1. يتم إرسال الخطأ إلى الوكيل +2. يحاول الوكيل إصلاح المشكلة +3. تتكرر العملية حتى: + - يُعيد الحارس `(True, result)` + - يتم الوصول إلى الحد الأقصى للمحاولات (`guardrail_max_retries`) + +مثال مع معالجة إعادة المحاولة: + +```python Code +from typing import Optional, Tuple, Union +from crewai import TaskOutput, Task + +def validate_json_output(result: TaskOutput) -> Tuple[bool, Any]: + """Validate and parse JSON output.""" + try: + # Try to parse as JSON + data = json.loads(result) + return (True, data) + except json.JSONDecodeError as e: + return (False, "Invalid JSON format") + +task = Task( + description="Generate a JSON report", + expected_output="A valid JSON object", + agent=analyst, + guardrail=validate_json_output, + guardrail_max_retries=3 # Limit retry attempts +) +``` + +## الحصول على مخرجات منظمة ومتسقة من المهام + + + من المهم أيضًا ملاحظة أن مخرجات المهمة الأخيرة في الفريق + تصبح المخرجات النهائية للفريق نفسه. + + +### استخدام `output_pydantic` + +تتيح لك خاصية `output_pydantic` تحديد نموذج Pydantic يجب أن تتوافق معه مخرجات المهمة. هذا يضمن أن المخرجات ليست منظمة فحسب، بل تم التحقق منها وفقًا لنموذج Pydantic. + +إليك مثال يوضح كيفية استخدام output_pydantic: + +```python Code +import json + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + + +class Blog(BaseModel): + title: str + content: str + + +blog_agent = Agent( + role="Blog Content Generator Agent", + goal="Generate a blog title and content", + backstory="""You are an expert content creator, skilled in crafting engaging and informative blog posts.""", + verbose=False, + allow_delegation=False, + llm="gpt-4o", +) + +task1 = Task( + description="""Create a blog title and content on a given topic. Make sure the content is under 200 words.""", + expected_output="A compelling blog title and well-written content.", + agent=blog_agent, + output_pydantic=Blog, +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[blog_agent], + tasks=[task1], + verbose=True, + process=Process.sequential, +) + +result = crew.kickoff() + +# Option 1: Accessing Properties Using Dictionary-Style Indexing +print("Accessing Properties - Option 1") +title = result["title"] +content = result["content"] +print("Title:", title) +print("Content:", content) + +# Option 2: Accessing Properties Directly from the Pydantic Model +print("Accessing Properties - Option 2") +title = result.pydantic.title +content = result.pydantic.content +print("Title:", title) +print("Content:", content) + +# Option 3: Accessing Properties Using the to_dict() Method +print("Accessing Properties - Option 3") +output_dict = result.to_dict() +title = output_dict["title"] +content = output_dict["content"] +print("Title:", title) +print("Content:", content) + +# Option 4: Printing the Entire Blog Object +print("Accessing Properties - Option 5") +print("Blog:", result) + +``` + +في هذا المثال: + +- يتم تعريف نموذج Pydantic Blog مع حقلي title و content. +- تستخدم المهمة task1 خاصية output_pydantic لتحديد أن مخرجاتها يجب أن تتوافق مع نموذج Blog. +- بعد تنفيذ الفريق، يمكنك الوصول إلى المخرجات المنظمة بعدة طرق كما هو موضح. + +#### شرح الوصول إلى المخرجات + +1. الفهرسة بأسلوب القاموس: يمكنك الوصول مباشرة إلى الحقول باستخدام result["field_name"]. يعمل هذا لأن فئة CrewOutput تنفذ دالة **getitem**. +2. مباشرة من نموذج Pydantic: الوصول إلى الخصائص مباشرة من كائن result.pydantic. +3. باستخدام دالة to_dict(): تحويل المخرجات إلى قاموس والوصول إلى الحقول. +4. طباعة الكائن بالكامل: ببساطة اطبع كائن result لرؤية المخرجات المنظمة. + +### استخدام `output_json` + +تتيح لك خاصية `output_json` تحديد المخرجات المتوقعة بتنسيق JSON. هذا يضمن أن مخرجات المهمة هي هيكل JSON صالح يمكن تحليله واستخدامه بسهولة في تطبيقك. + +إليك مثال يوضح كيفية استخدام `output_json`: + +```python Code +import json + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + + +# Define the Pydantic model for the blog +class Blog(BaseModel): + title: str + content: str + + +# Define the agent +blog_agent = Agent( + role="Blog Content Generator Agent", + goal="Generate a blog title and content", + backstory="""You are an expert content creator, skilled in crafting engaging and informative blog posts.""", + verbose=False, + allow_delegation=False, + llm="gpt-4o", +) + +# Define the task with output_json set to the Blog model +task1 = Task( + description="""Create a blog title and content on a given topic. Make sure the content is under 200 words.""", + expected_output="A JSON object with 'title' and 'content' fields.", + agent=blog_agent, + output_json=Blog, +) + +# Instantiate the crew with a sequential process +crew = Crew( + agents=[blog_agent], + tasks=[task1], + verbose=True, + process=Process.sequential, +) + +# Kickoff the crew to execute the task +result = crew.kickoff() + +# Option 1: Accessing Properties Using Dictionary-Style Indexing +print("Accessing Properties - Option 1") +title = result["title"] +content = result["content"] +print("Title:", title) +print("Content:", content) + +# Option 2: Printing the Entire Blog Object +print("Accessing Properties - Option 2") +print("Blog:", result) +``` + +في هذا المثال: + +- يتم تعريف نموذج Pydantic Blog مع حقلي title و content، الذي يُستخدم لتحديد هيكل مخرجات JSON. +- تستخدم المهمة task1 خاصية output_json للإشارة إلى أنها تتوقع مخرجات JSON متوافقة مع نموذج Blog. +- بعد تنفيذ الفريق، يمكنك الوصول إلى مخرجات JSON المنظمة بطريقتين كما هو موضح. + +#### شرح الوصول إلى المخرجات + +1. الوصول إلى الخصائص باستخدام الفهرسة بأسلوب القاموس: يمكنك الوصول إلى الحقول مباشرة باستخدام result["field_name"]. هذا ممكن لأن فئة CrewOutput تنفذ دالة **getitem**، مما يتيح لك معاملة المخرجات كقاموس. في هذا الخيار، نسترد title و content من النتيجة. +2. طباعة كائن Blog بالكامل: بطباعة result، تحصل على التمثيل النصي لكائن CrewOutput. نظرًا لأن دالة **str** منفذة لإعادة مخرجات JSON، سيعرض هذا المخرجات الكاملة كسلسلة منسقة تمثل كائن Blog. + +--- + +باستخدام output_pydantic أو output_json، تضمن أن مهامك تنتج مخرجات بتنسيق متسق ومنظم، مما يسهّل معالجة البيانات واستخدامها داخل تطبيقك أو عبر مهام متعددة. + +## دمج الأدوات مع المهام + +استفد من أدوات [CrewAI Toolkit](https://github.com/joaomdmoura/crewai-tools) و [LangChain Tools](https://python.langchain.com/docs/integrations/tools) لتحسين أداء المهام وتفاعل الوكلاء. + +## إنشاء مهمة بأدوات + +```python Code +import os +os.environ["OPENAI_API_KEY"] = "Your Key" +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key + +from crewai import Agent, Task, Crew +from crewai_tools import SerperDevTool + +research_agent = Agent( + role='Researcher', + goal='Find and summarize the latest AI news', + backstory="""You're a researcher at a large company. + You're responsible for analyzing data and providing insights + to the business.""", + verbose=True +) + +# to perform a semantic search for a specified query from a text's content across the internet +search_tool = SerperDevTool() + +task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +crew = Crew( + agents=[research_agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() +print(result) +``` + +يوضح هذا كيف يمكن للمهام ذات الأدوات المحددة تجاوز المجموعة الافتراضية للوكيل لتنفيذ مهام مخصصة. + +## الإشارة إلى مهام أخرى + +في CrewAI، يتم تمرير مخرجات مهمة واحدة تلقائيًا إلى المهمة التالية، لكن يمكنك تحديد مخرجات مهام بعينها، بما في ذلك عدة مهام، لاستخدامها كسياق لمهمة أخرى. + +هذا مفيد عندما تكون لديك مهمة تعتمد على مخرجات مهمة أخرى لا يتم تنفيذها مباشرة بعدها. يتم ذلك من خلال خاصية `context` للمهمة: + +```python Code +# ... + +research_ai_task = Task( + description="Research the latest developments in AI", + expected_output="A list of recent AI developments", + async_execution=True, + agent=research_agent, + tools=[search_tool] +) + +research_ops_task = Task( + description="Research the latest developments in AI Ops", + expected_output="A list of recent AI Ops developments", + async_execution=True, + agent=research_agent, + tools=[search_tool] +) + +write_blog_task = Task( + description="Write a full blog post about the importance of AI and its latest news", + expected_output="Full blog post that is 4 paragraphs long", + agent=writer_agent, + context=[research_ai_task, research_ops_task] +) + +#... +``` + +## التنفيذ غير المتزامن + +يمكنك تعريف مهمة ليتم تنفيذها بشكل غير متزامن. هذا يعني أن الفريق لن ينتظر اكتمالها للمتابعة مع المهمة التالية. هذا مفيد للمهام التي تستغرق وقتًا طويلاً، أو التي ليست حاسمة لتنفيذ المهام التالية. + +يمكنك بعد ذلك استخدام خاصية `context` لتحديد في مهمة مستقبلية أنها يجب أن تنتظر اكتمال مخرجات المهمة غير المتزامنة. + +```python Code +#... + +list_ideas = Task( + description="List of 5 interesting ideas to explore for an article about AI.", + expected_output="Bullet point list of 5 ideas for an article.", + agent=researcher, + async_execution=True # Will be executed asynchronously +) + +list_important_history = Task( + description="Research the history of AI and give me the 5 most important events.", + expected_output="Bullet point list of 5 important events.", + agent=researcher, + async_execution=True # Will be executed asynchronously +) + +write_article = Task( + description="Write an article about AI, its history, and interesting ideas.", + expected_output="A 4 paragraph article about AI.", + agent=writer, + context=[list_ideas, list_important_history] # Will wait for the output of the two tasks to be completed +) + +#... +``` + +## آلية دالة الاسترجاع + +يتم تنفيذ دالة الاسترجاع بعد اكتمال المهمة، مما يتيح تشغيل إجراءات أو إشعارات بناءً على نتيجة المهمة. + +```python Code +# ... + +def callback_function(output: TaskOutput): + # Do something after the task is completed + # Example: Send an email to the manager + print(f""" + Task completed! + Task: {output.description} + Output: {output.raw} + """) + +research_task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool], + callback=callback_function +) + +#... +``` + +## الوصول إلى مخرجات مهمة محددة + +بمجرد انتهاء الفريق من التشغيل، يمكنك الوصول إلى مخرجات مهمة محددة باستخدام خاصية `output` لكائن المهمة: + +```python Code +# ... +task1 = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +#... + +crew = Crew( + agents=[research_agent], + tasks=[task1, task2, task3], + verbose=True +) + +result = crew.kickoff() + +# Returns a TaskOutput object with the description and results of the task +print(f""" + Task completed! + Task: {task1.output.description} + Output: {task1.output.raw} +""") +``` + +## آلية تجاوز الأدوات + +تحديد الأدوات في مهمة يتيح التكيف الديناميكي لقدرات الوكيل، مما يؤكد مرونة CrewAI. + +## آليات معالجة الأخطاء والتحقق + +أثناء إنشاء المهام وتنفيذها، توجد آليات تحقق معينة لضمان متانة وموثوقية خصائص المهمة. تشمل على سبيل المثال لا الحصر: + +- ضمان تعيين نوع مخرجات واحد فقط لكل مهمة للحفاظ على توقعات مخرجات واضحة. +- منع التعيين اليدوي لخاصية `id` للحفاظ على سلامة نظام المعرّفات الفريدة. + +تساعد عمليات التحقق هذه في الحفاظ على اتساق وموثوقية تنفيذ المهام ضمن إطار عمل crewAI. + +## إنشاء المجلدات عند حفظ الملفات + +يتحكم معامل `create_directory` فيما إذا كان يجب على CrewAI إنشاء المجلدات تلقائيًا عند حفظ مخرجات المهام في ملفات. هذه الميزة مفيدة بشكل خاص لتنظيم المخرجات وضمان هيكلة مسارات الملفات بشكل صحيح، خاصة عند العمل مع تسلسلات مشاريع معقدة. + +### السلوك الافتراضي + +بشكل افتراضي، `create_directory=True`، مما يعني أن CrewAI سينشئ تلقائيًا أي مجلدات مفقودة في مسار ملف المخرجات: + +```python Code +# Default behavior - directories are created automatically +report_task = Task( + description='Generate a comprehensive market analysis report', + expected_output='A detailed market analysis with charts and insights', + agent=analyst_agent, + output_file='reports/2025/market_analysis.md', # Creates 'reports/2025/' if it doesn't exist + markdown=True +) +``` + +### تعطيل إنشاء المجلدات + +إذا كنت تريد منع الإنشاء التلقائي للمجلدات والتأكد من وجود المجلد مسبقًا، عيّن `create_directory=False`: + +```python Code +# Strict mode - directory must already exist +strict_output_task = Task( + description='Save critical data that requires existing infrastructure', + expected_output='Data saved to pre-configured location', + agent=data_agent, + output_file='secure/vault/critical_data.json', + create_directory=False # Will raise RuntimeError if 'secure/vault/' doesn't exist +) +``` + +### إعداد YAML + +يمكنك أيضًا إعداد هذا السلوك في تعريفات مهام YAML: + +```yaml tasks.yaml +analysis_task: + description: > + Generate quarterly financial analysis + expected_output: > + A comprehensive financial report with quarterly insights + agent: financial_analyst + output_file: reports/quarterly/q4_2024_analysis.pdf + create_directory: true # Automatically create 'reports/quarterly/' directory + +audit_task: + description: > + Perform compliance audit and save to existing audit directory + expected_output: > + A compliance audit report + agent: auditor + output_file: audit/compliance_report.md + create_directory: false # Directory must already exist +``` + +### حالات الاستخدام + +**إنشاء المجلدات تلقائيًا (`create_directory=True`):** + +- بيئات التطوير والنماذج الأولية +- إنشاء تقارير ديناميكية مع مجلدات قائمة على التاريخ +- سير عمل آلي حيث قد يختلف هيكل المجلدات +- تطبيقات متعددة المستأجرين مع مجلدات خاصة بالمستخدمين + +**إدارة المجلدات يدويًا (`create_directory=False`):** + +- بيئات الإنتاج مع ضوابط نظام ملفات صارمة +- التطبيقات الحساسة أمنيًا حيث يجب إعداد المجلدات مسبقًا +- الأنظمة ذات متطلبات أذونات محددة +- بيئات الامتثال حيث يتم مراقبة إنشاء المجلدات + +### معالجة الأخطاء + +عندما يكون `create_directory=False` والمجلد غير موجود، سيرفع CrewAI خطأ `RuntimeError`: + +```python Code +try: + result = crew.kickoff() +except RuntimeError as e: + # Handle missing directory error + print(f"Directory creation failed: {e}") + # Create directory manually or use fallback location +``` + +شاهد الفيديو أدناه لمعرفة كيفية استخدام المخرجات المنظمة في CrewAI: + + + +## الخلاصة + +المهام هي القوة الدافعة وراء إجراءات الوكلاء في CrewAI. +من خلال تعريف المهام ونتائجها بشكل صحيح، تمهّد الطريق لعمل وكلاء الذكاء الاصطناعي بفعالية، سواء بشكل مستقل أو كوحدة تعاونية. +تجهيز المهام بالأدوات المناسبة وفهم عملية التنفيذ واتباع ممارسات التحقق المتينة أمور حاسمة لتعظيم إمكانات CrewAI، +وضمان إعداد الوكلاء بفعالية لتكليفاتهم وتنفيذ المهام كما هو مقصود. diff --git a/docs/v1.15.13/ar/concepts/testing.mdx b/docs/v1.15.13/ar/concepts/testing.mdx new file mode 100644 index 0000000000..061dc7fb37 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/testing.mdx @@ -0,0 +1,49 @@ +--- +title: الاختبار +description: تعرّف على كيفية اختبار طاقم CrewAI وتقييم أدائه. +icon: vial +mode: "wide" +--- + +## نظرة عامة + +يُعد الاختبار جزءًا حيويًا من عملية التطوير، ومن الضروري التأكد من أن طاقمك يعمل كما هو متوقع. مع CrewAI، يمكنك اختبار طاقمك وتقييم أدائه بسهولة باستخدام إمكانيات الاختبار المدمجة. + +### استخدام ميزة الاختبار + +أضفنا أمر CLI `crewai test` لتسهيل اختبار طاقمك. سيقوم هذا الأمر بتشغيل طاقمك لعدد محدد من التكرارات وتوفير مقاييس أداء مفصلة. المعاملات هي `n_iterations` و `model`، وهي اختيارية وتكون قيمها الافتراضية 2 و `gpt-4o-mini` على التوالي. حاليًا، المزود الوحيد المتاح هو OpenAI. + +```bash +crewai test +``` + +إذا أردت تشغيل المزيد من التكرارات أو استخدام نموذج مختلف، يمكنك تحديد المعاملات هكذا: + +```bash +crewai test --n_iterations 5 --model gpt-4o +``` + +أو باستخدام الصيغة المختصرة: + +```bash +crewai test -n 5 -m gpt-4o +``` + +عند تشغيل أمر `crewai test`، سيتم تنفيذ الطاقم للعدد المحدد من التكرارات، وستُعرض مقاييس الأداء في نهاية التشغيل. + +سيظهر جدول الدرجات في النهاية لعرض أداء الطاقم من حيث المقاييس التالية: + +
**درجات المهام (1-10 الأعلى أفضل)**
+ +| المهام/الطاقم/الوكلاء | التشغيل 1 | التشغيل 2 | المجموع المتوسط | الوكلاء | معلومات إضافية | +|:------------------|:-----:|:-----:|:----------:|:------------------------------:|:---------------------------------| +| المهمة 1 | 9.0 | 9.5 | **9.2** | Professional Insights | | +| | | | | Researcher | | +| المهمة 2 | 9.0 | 10.0 | **9.5** | Company Profile Investigator | | +| المهمة 3 | 9.0 | 9.0 | **9.0** | Automation Insights | | +| | | | | Specialist | | +| المهمة 4 | 9.0 | 9.0 | **9.0** | Final Report Compiler | Automation Insights Specialist | +| الطاقم | 9.00 | 9.38 | **9.2** | | | +| زمن التنفيذ (ثانية) | 126 | 145 | **135** | | | + +يوضح المثال أعلاه نتائج الاختبار لتشغيلين للطاقم مع مهمتين، مع الدرجة الإجمالية المتوسطة لكل مهمة والطاقم ككل. diff --git a/docs/v1.15.13/ar/concepts/tools.mdx b/docs/v1.15.13/ar/concepts/tools.mdx new file mode 100644 index 0000000000..2740f723d1 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/tools.mdx @@ -0,0 +1,290 @@ +--- +title: الأدوات +description: فهم واستخدام الأدوات ضمن إطار عمل CrewAI لتعاون الوكلاء وتنفيذ المهام. +icon: screwdriver-wrench +mode: "wide" +--- + +## نظرة عامة + +تُمكّن أدوات CrewAI الوكلاء بقدرات تتراوح من البحث على الويب وتحليل البيانات إلى التعاون وتفويض المهام بين الزملاء. +توضح هذه الوثائق كيفية إنشاء هذه الأدوات ودمجها والاستفادة منها ضمن إطار عمل CrewAI، بما في ذلك التركيز على أدوات التعاون. + + + الأدوات تمنح الوكلاء **دوال قابلة للاستدعاء** لاتخاذ إجراءات. تعمل جنبًا إلى جنب مع [MCP](/ar/mcp/overview) (خوادم أدوات عن بُعد) و[التطبيقات](/ar/concepts/agent-capabilities) (تكاملات المنصة) و[المهارات](/ar/concepts/skills) (خبرة المجال) و[المعرفة](/ar/concepts/knowledge) (حقائق مُسترجعة). راجع نظرة عامة على [قدرات الوكيل](/ar/concepts/agent-capabilities) لفهم متى تستخدم كل نوع. + + +## ما هي الأداة؟ + +الأداة في CrewAI هي مهارة أو وظيفة يمكن للوكلاء استخدامها لأداء إجراءات مختلفة. +يشمل ذلك أدوات من [مجموعة أدوات CrewAI](https://github.com/joaomdmoura/crewai-tools) و[أدوات LangChain](https://python.langchain.com/docs/integrations/tools)، +مما يُمكّن كل شيء من عمليات البحث البسيطة إلى التفاعلات المعقدة والعمل الجماعي الفعال بين الوكلاء. + + +يوفر CrewAI AMP مستودع أدوات شامل مع تكاملات جاهزة لأنظمة الأعمال الشائعة وواجهات API. انشر الوكلاء مع أدوات المؤسسة في دقائق بدلاً من أيام. + +يتضمن مستودع أدوات المؤسسة: + +- موصلات جاهزة لأنظمة المؤسسة الشائعة +- واجهة إنشاء أدوات مخصصة +- إمكانيات التحكم في الإصدارات والمشاركة +- ميزات الأمان والامتثال + + +## الخصائص الرئيسية للأدوات + +- **المنفعة**: مصممة لمهام مثل البحث على الويب وتحليل البيانات وإنشاء المحتوى وتعاون الوكلاء. +- **التكامل**: تعزز قدرات الوكلاء من خلال دمج الأدوات بسلاسة في سير عملهم. +- **القابلية للتخصيص**: توفر المرونة لتطوير أدوات مخصصة أو استخدام الأدوات الموجودة، لتلبية الاحتياجات المحددة للوكلاء. +- **معالجة الأخطاء**: تتضمن آليات معالجة أخطاء قوية لضمان التشغيل السلس. +- **آلية التخزين المؤقت**: تتميز بتخزين مؤقت ذكي لتحسين الأداء وتقليل العمليات المتكررة. +- **الدعم غير المتزامن**: تتعامل مع الأدوات المتزامنة وغير المتزامنة، مما يُمكّن العمليات غير الحاجبة. + +## استخدام أدوات CrewAI + +لتعزيز قدرات وكلائك بأدوات CrewAI، ابدأ بتثبيت حزمة الأدوات الإضافية: + +```bash +pip install 'crewai[tools]' +``` + +إليك مثالًا يوضح استخدامها: + +```python Code +import os +from crewai import Agent, Task, Crew +# استيراد أدوات crewAI +from crewai_tools import ( + DirectoryReadTool, + FileReadTool, + SerperDevTool, + WebsiteSearchTool +) + +# إعداد مفاتيح API +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key +os.environ["OPENAI_API_KEY"] = "Your Key" + +# إنشاء الأدوات +docs_tool = DirectoryReadTool(directory='./blog-posts') +file_tool = FileReadTool() +search_tool = SerperDevTool() +web_rag_tool = WebsiteSearchTool() + +# إنشاء الوكلاء +researcher = Agent( + role='Market Research Analyst', + goal='Provide up-to-date market analysis of the AI industry', + backstory='An expert analyst with a keen eye for market trends.', + tools=[search_tool, web_rag_tool], + verbose=True +) + +writer = Agent( + role='Content Writer', + goal='Craft engaging blog posts about the AI industry', + backstory='A skilled writer with a passion for technology.', + tools=[docs_tool, file_tool], + verbose=True +) + +# تعريف المهام +research = Task( + description='Research the latest trends in the AI industry and provide a summary.', + expected_output='A summary of the top 3 trending developments in the AI industry with a unique perspective on their significance.', + agent=researcher +) + +write = Task( + description='Write an engaging blog post about the AI industry, based on the research analyst\'s summary. Draw inspiration from the latest blog posts in the directory.', + expected_output='A 4-paragraph blog post formatted in markdown with engaging, informative, and accessible content, avoiding complex jargon.', + agent=writer, + output_file='blog-posts/new_post.md' +) + +# تجميع طاقم مع تفعيل التخطيط +crew = Crew( + agents=[researcher, writer], + tasks=[research, write], + verbose=True, + planning=True, +) + +# تنفيذ المهام +crew.kickoff() +``` + +## أدوات CrewAI المتاحة + +- **معالجة الأخطاء**: جميع الأدوات مبنية بقدرات معالجة الأخطاء، مما يسمح للوكلاء بإدارة الاستثناءات بسلاسة ومتابعة مهامهم. +- **آلية التخزين المؤقت**: جميع الأدوات تدعم التخزين المؤقت، مما يُمكّن الوكلاء من إعادة استخدام النتائج المحصلة سابقًا بكفاءة، مما يقلل الحمل على الموارد الخارجية ويسرّع وقت التنفيذ. يمكنك أيضًا تحديد تحكم أدق في آلية التخزين المؤقت باستخدام خاصية `cache_function` على الأداة. + +إليك قائمة بالأدوات المتاحة وأوصافها: + +| الأداة | الوصف | +| :------------------------------- | :--------------------------------------------------------------------------------------------- | +| **ApifyActorsTool** | أداة تدمج Apify Actors مع سير عملك لمهام استخراج البيانات من الويب والأتمتة. | +| **BrowserbaseLoadTool** | أداة للتفاعل مع المتصفحات واستخراج البيانات منها. | +| **CodeDocsSearchTool** | أداة RAG محسّنة للبحث في وثائق الكود والمستندات التقنية ذات الصلة. | +| **CodeInterpreterTool** | أداة لتفسير كود Python. | +| **ComposioTool** | تُمكّن استخدام أدوات Composio. | +| **CSVSearchTool** | أداة RAG مصممة للبحث في ملفات CSV، مخصصة للتعامل مع البيانات المنظمة. | +| **DALL-E Tool** | أداة لإنشاء الصور باستخدام DALL-E API. | +| **DirectorySearchTool** | أداة RAG للبحث في المجلدات، مفيدة للتنقل في أنظمة الملفات. | +| **DOCXSearchTool** | أداة RAG للبحث في مستندات DOCX، مثالية لمعالجة ملفات Word. | +| **DirectoryReadTool** | تسهّل قراءة ومعالجة هياكل المجلدات ومحتوياتها. | +| **ExaSearchTool** | أداة مصممة لإجراء عمليات بحث شاملة عبر مصادر بيانات متنوعة. | +| **FileReadTool** | تُمكّن قراءة واستخراج البيانات من الملفات، مع دعم تنسيقات ملفات متنوعة. | +| **FirecrawlSearchTool** | أداة للبحث في صفحات الويب باستخدام Firecrawl وإرجاع النتائج. | +| **FirecrawlCrawlWebsiteTool** | أداة لزحف صفحات الويب باستخدام Firecrawl. | +| **FirecrawlScrapeWebsiteTool** | أداة لاستخراج محتوى عناوين URL لصفحات الويب باستخدام Firecrawl. | +| **GithubSearchTool** | أداة RAG للبحث في مستودعات GitHub، مفيدة لبحث الكود والوثائق. | +| **SerperDevTool** | أداة متخصصة لأغراض التطوير، مع وظائف محددة قيد التطوير. | +| **TXTSearchTool** | أداة RAG مركّزة على البحث في ملفات النص (.txt)، مناسبة للبيانات غير المنظمة. | +| **JSONSearchTool** | أداة RAG مصممة للبحث في ملفات JSON، تخدم التعامل مع البيانات المنظمة. | +| **LlamaIndexTool** | تُمكّن استخدام أدوات LlamaIndex. | +| **MDXSearchTool** | أداة RAG مخصصة للبحث في ملفات Markdown (MDX)، مفيدة للوثائق. | +| **PDFSearchTool** | أداة RAG للبحث في مستندات PDF، مثالية لمعالجة المستندات الممسوحة ضوئيًا. | +| **PGSearchTool** | أداة RAG محسّنة للبحث في قواعد بيانات PostgreSQL، مناسبة لاستعلامات قواعد البيانات. | +| **Vision Tool** | أداة لإنشاء الصور باستخدام DALL-E API. | +| **RagTool** | أداة RAG للأغراض العامة قادرة على التعامل مع مصادر وأنواع بيانات متنوعة. | +| **ScrapeElementFromWebsiteTool** | تُمكّن استخراج عناصر محددة من المواقع، مفيدة لاستخراج البيانات المستهدف. | +| **ScrapeWebsiteTool** | تسهّل استخراج المواقع بالكامل، مثالية لجمع البيانات الشامل. | +| **WebsiteSearchTool** | أداة RAG للبحث في محتوى المواقع، محسّنة لاستخراج بيانات الويب. | +| **XMLSearchTool** | أداة RAG مصممة للبحث في ملفات XML، مناسبة لتنسيقات البيانات المنظمة. | +| **YoutubeChannelSearchTool** | أداة RAG للبحث في قنوات YouTube، مفيدة لتحليل محتوى الفيديو. | +| **YoutubeVideoSearchTool** | أداة RAG للبحث في مقاطع فيديو YouTube، مثالية لاستخراج بيانات الفيديو. | + +## إنشاء أدواتك الخاصة + + + يمكن للمطورين إنشاء `أدوات مخصصة` مصممة خصيصًا لاحتياجات وكلائهم أو + استخدام الخيارات الجاهزة. + + +هناك طريقتان رئيسيتان لإنشاء أداة CrewAI: + +### الوراثة من `BaseTool` + +```python Code +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class MyToolInput(BaseModel): + """Input schema for MyCustomTool.""" + argument: str = Field(..., description="Description of the argument.") + +class MyCustomTool(BaseTool): + name: str = "Name of my tool" + description: str = "What this tool does. It's vital for effective utilization." + args_schema: Type[BaseModel] = MyToolInput + + def _run(self, argument: str) -> str: + # منطق أداتك هنا + return "Tool's result" +``` + +## دعم الأدوات غير المتزامنة + +يدعم CrewAI الأدوات غير المتزامنة، مما يتيح لك تنفيذ أدوات تجري عمليات غير حاجبة مثل طلبات الشبكة وعمليات الإدخال/الإخراج على الملفات أو عمليات async أخرى بدون حجب مسار التنفيذ الرئيسي. + +### إنشاء أدوات غير متزامنة + +يمكنك إنشاء أدوات غير متزامنة بطريقتين: + +#### 1. استخدام مزيّن `tool` مع دوال Async + +```python Code +from crewai.tools import tool + +@tool("fetch_data_async") +async def fetch_data_async(query: str) -> str: + """Asynchronously fetch data based on the query.""" + # محاكاة عملية غير متزامنة + await asyncio.sleep(1) + return f"Data retrieved for {query}" +``` + +#### 2. تنفيذ طرق Async في فئات الأدوات المخصصة + +```python Code +from crewai.tools import BaseTool + +class AsyncCustomTool(BaseTool): + name: str = "async_custom_tool" + description: str = "An asynchronous custom tool" + + async def _run(self, query: str = "") -> str: + """Asynchronously run the tool""" + # تنفيذك غير المتزامن هنا + await asyncio.sleep(1) + return f"Processed {query} asynchronously" +``` + +### استخدام الأدوات غير المتزامنة + +تعمل الأدوات غير المتزامنة بسلاسة في كل من سير عمل الطاقم القياسي وسير عمل التدفق: + +```python Code +# في طاقم قياسي +agent = Agent(role="researcher", tools=[async_custom_tool]) + +# في تدفق +class MyFlow(Flow): + @start() + async def begin(self): + crew = Crew(agents=[agent]) + result = await crew.kickoff_async() + return result +``` + +يتعامل إطار عمل CrewAI تلقائيًا مع تنفيذ الأدوات المتزامنة وغير المتزامنة، لذا لا تحتاج للقلق بشأن كيفية استدعائها بشكل مختلف. + +### استخدام مزيّن `tool` + +```python Code +from crewai.tools import tool +@tool("Name of my tool") +def my_tool(question: str) -> str: + """Clear description for what this tool is useful for, your agent will need this information to use it.""" + # منطق الدالة هنا + return "Result from your custom tool" +``` + +### آلية التخزين المؤقت المخصصة + + + يمكن للأدوات اختياريًا تنفيذ `cache_function` لضبط سلوك + التخزين المؤقت. تحدد هذه الدالة متى يتم تخزين النتائج مؤقتًا بناءً على شروط + محددة، مما يوفر تحكمًا دقيقًا في منطق التخزين المؤقت. + + +```python Code +from crewai.tools import tool + +@tool +def multiplication_tool(first_number: int, second_number: int) -> str: + """Useful for when you need to multiply two numbers together.""" + return first_number * second_number + +def cache_func(args, result): + # في هذه الحالة، نخزّن النتيجة مؤقتًا فقط إذا كانت من مضاعفات 2 + cache = result % 2 == 0 + return cache + +multiplication_tool.cache_function = cache_func + +writer1 = Agent( + role="Writer", + goal="You write lessons of math for kids.", + backstory="You're an expert in writing and you love to teach kids but you know nothing of math.", + tools=[multiplication_tool], + allow_delegation=False, + ) + #... +``` + +## الخلاصة + +الأدوات محورية في توسيع قدرات وكلاء CrewAI، مما يمكّنهم من تنفيذ مجموعة واسعة من المهام والتعاون بفعالية. +عند بناء حلول مع CrewAI، استفد من كل من الأدوات المخصصة والموجودة لتمكين وكلائك وتعزيز نظام الذكاء الاصطناعي البيئي. فكّر في استخدام معالجة الأخطاء وآليات التخزين المؤقت ومرونة معاملات الأدوات لتحسين أداء وقدرات وكلائك. diff --git a/docs/v1.15.13/ar/concepts/training.mdx b/docs/v1.15.13/ar/concepts/training.mdx new file mode 100644 index 0000000000..0195323481 --- /dev/null +++ b/docs/v1.15.13/ar/concepts/training.mdx @@ -0,0 +1,197 @@ +--- +title: التدريب +description: تعرّف على كيفية تدريب وكلاء CrewAI من خلال تقديم ملاحظات مبكرة والحصول على نتائج متسقة. +icon: dumbbell +mode: "wide" +--- + +## نظرة عامة + +تتيح لك ميزة التدريب في CrewAI تدريب وكلاء الذكاء الاصطناعي باستخدام واجهة سطر الأوامر (CLI). +بتشغيل الأمر `crewai train -n `، يمكنك تحديد عدد التكرارات لعملية التدريب. + +أثناء التدريب، يستخدم CrewAI تقنيات لتحسين أداء وكلائك مع التغذية الراجعة البشرية. +يساعد هذا الوكلاء على تحسين فهمهم واتخاذ القرارات وحل المشكلات. + +### تدريب طاقمك باستخدام CLI + +لاستخدام ميزة التدريب، اتبع الخطوات التالية: + +1. افتح الطرفية أو موجه الأوامر. +2. انتقل إلى المجلد حيث يقع مشروع CrewAI. +3. شغّل الأمر التالي: + +```shell +crewai train -n -f +``` + + استبدل `` بعدد تكرارات التدريب المرغوب و`` باسم الملف المناسب المنتهي بـ `.pkl`. + + + + إذا حذفت `-f`، فإن المخرجات تُحفظ افتراضيًا في `trained_agents_data.pkl` في مجلد العمل الحالي. يمكنك تمرير مسار مطلق للتحكم في مكان كتابة الملف. + + +### تدريب طاقمك برمجيًا + +لتدريب طاقمك برمجيًا، استخدم الخطوات التالية: + +1. حدد عدد التكرارات للتدريب. +2. حدد معاملات الإدخال لعملية التدريب. +3. نفّذ أمر التدريب داخل كتلة try-except للتعامل مع الأخطاء المحتملة. + +```python Code +n_iterations = 2 +inputs = {"topic": "CrewAI Training"} +filename = "your_model.pkl" + +try: + YourCrewName_Crew().crew().train( + n_iterations=n_iterations, + inputs=inputs, + filename=filename + ) + +except Exception as e: + raise Exception(f"An error occurred while training the crew: {e}") +``` + +## كيف تُستخدم بيانات التدريب من قبل الوكلاء + +يستخدم CrewAI مخرجات التدريب بطريقتين: أثناء التدريب لدمج ملاحظاتك البشرية، وبعد التدريب لتوجيه الوكلاء باقتراحات موحدة. + +### تدفق بيانات التدريب + +```mermaid +flowchart TD + A["Start training
CLI: crewai train -n -f
or Python: crew.train(...)"] --> B["Setup training mode
- task.human_input = true
- disable delegation
- init training_data.pkl + trained file"] + + subgraph "Iterations" + direction LR + C["Iteration i
initial_output"] --> D["User human_feedback"] + D --> E["improved_output"] + E --> F["Append to training_data.pkl
by agent_id and iteration"] + end + + B --> C + F --> G{"More iterations?"} + G -- "Yes" --> C + G -- "No" --> H["Evaluate per agent
aggregate iterations"] + + H --> I["Consolidate
suggestions[] + quality + final_summary"] + I --> J["Save by agent role to trained file
(default: trained_agents_data.pkl)"] + + J --> K["Normal (non-training) runs"] + K --> L["Auto-load suggestions
from trained_agents_data.pkl"] + L --> M["Append to prompt
for consistent improvements"] +``` + +### أثناء تشغيلات التدريب + +- في كل تكرار، يسجل النظام لكل وكيل: + - `initial_output`: الإجابة الأولى للوكيل + - `human_feedback`: ملاحظاتك المضمّنة عند الطلب + - `improved_output`: إجابة المتابعة للوكيل بعد الملاحظات +- تُخزن هذه البيانات في ملف عمل باسم `training_data.pkl` مفهرس بمعرّف الوكيل الداخلي والتكرار. +- أثناء نشاط التدريب، يُلحق الوكيل تلقائيًا ملاحظاتك البشرية السابقة بأمره لتطبيق تلك التعليمات في المحاولات اللاحقة ضمن جلسة التدريب. + التدريب تفاعلي: تُعيّن المهام `human_input = true`، لذا سيتوقف التشغيل في بيئة غير تفاعلية بانتظار مدخلات المستخدم. + +### بعد اكتمال التدريب + +- عند انتهاء `train(...)`، يقيّم CrewAI بيانات التدريب المجمعة لكل وكيل وينتج نتيجة موحدة تحتوي على: + - `suggestions`: تعليمات واضحة وقابلة للتنفيذ مستخلصة من ملاحظاتك والفرق بين المخرجات الأولية/المحسنة + - `quality`: درجة من 0-10 تعكس التحسن + - `final_summary`: مجموعة خطوات عمل تفصيلية للمهام المستقبلية +- تُحفظ هذه النتائج الموحدة في اسم الملف الذي تمرره إلى `train(...)` (الافتراضي عبر CLI هو `trained_agents_data.pkl`). تُفهرس الإدخالات بدور الوكيل `role` لتطبيقها عبر الجلسات. +- أثناء التنفيذ العادي (غير التدريب)، يحمّل كل وكيل تلقائيًا `suggestions` الموحدة ويلحقها بأمر المهمة كتعليمات إلزامية. يمنحك هذا تحسينات متسقة بدون تغيير تعريفات الوكلاء. + +### ملخص الملفات + +- `training_data.pkl` (مؤقت، لكل جلسة): + - الهيكل: `agent_id -> { iteration_number: { initial_output, human_feedback, improved_output } }` + - الغرض: التقاط البيانات الخام والملاحظات البشرية أثناء التدريب + - الموقع: يُحفظ في مجلد العمل الحالي (CWD) +- `trained_agents_data.pkl` (أو اسم ملفك المخصص): + - الهيكل: `agent_role -> { suggestions: string[], quality: number, final_summary: string }` + - الغرض: استمرار التوجيه الموحد للتشغيلات المستقبلية + - الموقع: يُكتب في CWD افتراضيًا؛ استخدم `-f` لتعيين مسار مخصص (بما في ذلك المطلق) + +## اعتبارات نماذج اللغة الصغيرة + + + عند استخدام نماذج لغة أصغر (≤7 مليار معامل) لتقييم بيانات التدريب، كن على علم أنها قد تواجه تحديات في إنتاج مخرجات منظمة واتباع التعليمات المعقدة. + + +### قيود النماذج الصغيرة في تقييم التدريب + + + + غالبًا ما تواجه النماذج الأصغر صعوبة في إنتاج استجابات JSON صالحة مطلوبة لتقييمات التدريب المنظمة، مما يؤدي إلى أخطاء تحليل وبيانات غير مكتملة. + + + قد توفر النماذج تحت 7 مليار معامل تقييمات أقل دقة مع عمق استدلال محدود مقارنة بالنماذج الأكبر. + + + قد لا تُتبع معايير تقييم التدريب المعقدة بالكامل أو تُراعى من قبل النماذج الأصغر. + + + قد تفتقر التقييمات عبر تكرارات تدريب متعددة إلى الاتساق مع النماذج الأصغر. + + + +### توصيات للتدريب + + + + لجودة تدريب مثالية وتقييمات موثوقة، نوصي بشدة باستخدام نماذج بحد أدنى 7 مليار معامل أو أكبر: + + ```python + from crewai import Agent, Crew, Task, LLM + + # الحد الأدنى الموصى به لتقييم التدريب + llm = LLM(model="mistral/open-mistral-7b") + + # خيارات أفضل لتقييم تدريب موثوق + llm = LLM(model="anthropic/claude-3-sonnet-20240229-v1:0") + llm = LLM(model="gpt-4o") + + # استخدم هذا LLM مع وكلائك + agent = Agent( + role="Training Evaluator", + goal="Provide accurate training feedback", + llm=llm + ) + ``` + + + توفر النماذج الأكثر قوة ملاحظات أعلى جودة مع استدلال أفضل، مما يؤدي إلى تكرارات تدريب أكثر فعالية. + + + + إذا كان يجب عليك استخدام نماذج أصغر لتقييم التدريب، كن على علم بهذه القيود: + + ```python + # استخدام نموذج أصغر (توقع بعض القيود) + llm = LLM(model="huggingface/microsoft/Phi-3-mini-4k-instruct") + ``` + + + بينما يتضمن CrewAI تحسينات للنماذج الصغيرة، توقع نتائج تقييم أقل موثوقية ودقة قد تتطلب تدخلاً بشريًا أكبر أثناء التدريب. + + + + +### نقاط مهمة يجب ملاحظتها + +- **متطلب العدد الصحيح الموجب:** تأكد من أن عدد التكرارات (`n_iterations`) هو عدد صحيح موجب. سيرمي الكود `ValueError` إذا لم يتحقق هذا الشرط. +- **متطلب اسم الملف:** تأكد من أن اسم الملف ينتهي بـ `.pkl`. سيرمي الكود `ValueError` إذا لم يتحقق هذا الشرط. +- **معالجة الأخطاء:** يتعامل الكود مع أخطاء العمليات الفرعية والاستثناءات غير المتوقعة، ويوفر رسائل خطأ للمستخدم. +- يُطبق التوجيه المدرّب في وقت الأمر؛ لا يعدّل تهيئة وكيل Python/YAML. +- يحمّل الوكلاء تلقائيًا الاقتراحات المدربة من ملف باسم `trained_agents_data.pkl` الموجود في مجلد العمل الحالي. إذا درّبت إلى اسم ملف مختلف، أعد تسميته إلى `trained_agents_data.pkl` قبل التشغيل، أو اضبط المحمّل في الكود. +- يمكنك تغيير اسم ملف المخرجات عند استدعاء `crewai train` بـ `-f/--filename`. المسارات المطلقة مدعومة إذا أردت الحفظ خارج CWD. + +من المهم ملاحظة أن عملية التدريب قد تستغرق بعض الوقت، اعتمادًا على تعقيد وكلائك وستتطلب أيضًا ملاحظاتك في كل تكرار. + +بمجرد اكتمال التدريب، سيكون وكلاؤك مجهزين بقدرات ومعرفة محسّنة، وجاهزين لمعالجة المهام المعقدة وتقديم رؤى أكثر اتساقًا وقيمة. + +تذكر تحديث وإعادة تدريب وكلائك بانتظام لضمان بقائهم على اطلاع بأحدث المعلومات والتطورات في المجال. diff --git a/docs/v1.15.13/ar/examples/cookbooks.mdx b/docs/v1.15.13/ar/examples/cookbooks.mdx new file mode 100644 index 0000000000..49280d73c9 --- /dev/null +++ b/docs/v1.15.13/ar/examples/cookbooks.mdx @@ -0,0 +1,49 @@ +--- +title: كتب وصفات CrewAI +description: بدايات سريعة ودفاتر ملاحظات مركّزة على الميزات لتعلم الأنماط بسرعة. +icon: book +mode: "wide" +--- + +## بدايات سريعة وعروض توضيحية + + + + تنسيق عدة Agents على مهام مشتركة. يتضمن دفتر ملاحظات بنمط تعاون شامل. + + + + تعليم الـ Agents التفكير في خطط متعددة المراحل قبل التنفيذ باستخدام أدوات التخطيط. + + + + استكشاف حلقات التأمل الذاتي، ومطالبات النقد، وأنماط التفكير المنظم. + + + + + + تطبيق حواجز حماية على مستوى المهام مع إعادة المحاولة ودوال التحقق والبدائل الآمنة. + + + + ربط CrewAI بـ Gemini مع تأريض البحث للحصول على مخرجات واقعية غنية بالاستشهادات. + + + + إنشاء ملخصات فيديو باستخدام نموذج Gemini متعدد الوسائط وتنسيق CrewAI. + + + + + + عرض جميع دفاتر الملاحظات والعروض التوضيحية التي تستعرض إمكانيات CrewAI المحددة. + + + هل يفتقد نمط معين؟ أرسل طلبًا في منتدى المجتمع وسنوسّع المكتبة. + + + + +استخدم كتب الوصفات لتعلم نمط بسرعة، ثم انتقل إلى الأمثلة الكاملة للتطبيقات الجاهزة للإنتاج. + diff --git a/docs/v1.15.13/ar/examples/example.mdx b/docs/v1.15.13/ar/examples/example.mdx new file mode 100644 index 0000000000..0987e8dff5 --- /dev/null +++ b/docs/v1.15.13/ar/examples/example.mdx @@ -0,0 +1,86 @@ +--- +title: أمثلة CrewAI +description: استكشف أمثلة منسّقة مرتبة حسب Crews وFlows والتكاملات ودفاتر الملاحظات. +icon: rocket-launch +mode: "wide" +--- + +## Crews + + + + تخطيط حملات تسويقية متعددة الـ Agents. + + + تخطيط رحلات مفاجئة مخصصة. + + + مطابقة السيرة الذاتية بالوظائف باستخدام البحث المتجهي. + + + إنشاء أوصاف وظيفية آلية. + + + فريق متعدد الـ Agents يصمم ويبني ألعاب Python. + + + استقطاب المرشحين وتقييمهم. + + + عرض القائمة الكاملة لأمثلة الـ Crews. + + + +## Flows + + + + إنشاء محتوى متعدد الـ Crews مع التوجيه. + + + مراقبة البريد الإلكتروني والرد الآلي. + + + تأهيل العملاء المحتملين مع تدخل بشري. + + + معالجة الملاحظات مع التكاملات. + + + سير عمل التحسين الذاتي التكراري. + + + إنشاء الفصول بالتوازي. + + + عرض القائمة الكاملة لأمثلة الـ Flows. + + + +## التكاملات + + + + التكامل مع إطار عمل LangGraph. + + + استخدام CrewAI مع Azure OpenAI. + + + تكاملات منظومة NVIDIA. + + + عرض جميع أمثلة التكاملات. + + + +## دفاتر الملاحظات + + + + Simple QA Crew + Flow. + + + أمثلة تفاعلية للتعلم والتجريب. + + diff --git a/docs/v1.15.13/ar/guides/advanced/customizing-prompts.mdx b/docs/v1.15.13/ar/guides/advanced/customizing-prompts.mdx new file mode 100644 index 0000000000..b16c3b0b04 --- /dev/null +++ b/docs/v1.15.13/ar/guides/advanced/customizing-prompts.mdx @@ -0,0 +1,331 @@ +--- +title: تخصيص المطالبات +description: تعمّق في تخصيص المطالبات على المستوى المنخفض في CrewAI، مما يتيح حالات استخدام مخصصة ومعقدة لنماذج ولغات مختلفة. +icon: message-pen +mode: "wide" +--- + +## لماذا نخصص المطالبات؟ + +على الرغم من أن مطالبات CrewAI الافتراضية تعمل بشكل جيد في كثير من السيناريوهات، إلا أن التخصيص على المستوى المنخفض يفتح الباب أمام سلوك أكثر مرونة وقوة للـ Agent. إليك لماذا قد ترغب في الاستفادة من هذا التحكم العميق: + +1. **التحسين لنماذج LLM محددة** – تزدهر النماذج المختلفة (مثل GPT-4 وClaude وLlama) مع تنسيقات مطالبات مصممة لبنيتها الفريدة. +2. **تغيير اللغة** – بناء Agents تعمل حصريًا بلغات غير الإنجليزية مع التعامل مع الفروق الدقيقة بدقة. +3. **التخصص في مجالات معقدة** – تكييف المطالبات لصناعات متخصصة للغاية مثل الرعاية الصحية والمالية والقانون. +4. **ضبط النبرة والأسلوب** – جعل الـ Agents أكثر رسمية أو عفوية أو إبداعية أو تحليلية. +5. **دعم حالات استخدام مخصصة للغاية** – استخدام هياكل وتنسيقات مطالبات متقدمة لتلبية متطلبات معقدة خاصة بالمشروع. + +يستكشف هذا الدليل كيفية الوصول إلى مطالبات CrewAI على مستوى أعمق، مما يمنحك تحكمًا دقيقًا في كيفية تفكير الـ Agents وتفاعلها. + +## فهم نظام المطالبات في CrewAI + +تحت الغطاء، يستخدم CrewAI نظام مطالبات معياري يمكنك تخصيصه على نطاق واسع: + +- **قوالب الـ Agent** – تحكم في نهج كل Agent تجاه دوره المعيّن. +- **شرائح المطالبات** – تتحكم في السلوكيات المتخصصة مثل المهام واستخدام الأدوات وهيكل المخرجات. +- **معالجة الأخطاء** – توجيه كيفية استجابة الـ Agents للإخفاقات والاستثناءات وحالات انتهاء المهلة. +- **مطالبات خاصة بالأدوات** – تعريف تعليمات مفصلة لكيفية استدعاء الأدوات أو استخدامها. + +اطلع على [قوالب المطالبات الأصلية في مستودع CrewAI](https://github.com/crewAIInc/crewAI/blob/main/src/crewai/translations/en.json) لمعرفة كيفية تنظيم هذه العناصر. من هناك، يمكنك تجاوزها أو تكييفها حسب الحاجة لفتح سلوكيات متقدمة. + +## فهم تعليمات النظام الافتراضية + + +**مشكلة شفافية الإنتاج**: يحقن CrewAI تلقائيًا تعليمات افتراضية في مطالباتك قد لا تكون على علم بها. يشرح هذا القسم ما يحدث تحت الغطاء وكيفية الحصول على تحكم كامل. + + +عندما تعرّف Agent بـ `role` و`goal` و`backstory`، يضيف CrewAI تلقائيًا تعليمات نظام إضافية تتحكم في التنسيق والسلوك. فهم هذه الحقن الافتراضية أمر بالغ الأهمية لأنظمة الإنتاج التي تحتاج شفافية كاملة في المطالبات. + +### ما يحقنه CrewAI تلقائيًا + +بناءً على تهيئة الـ Agent، يضيف CrewAI تعليمات افتراضية مختلفة: + +#### للـ Agents بدون أدوات +```text +"I MUST use these formats, my job depends on it!" +``` + +#### للـ Agents مع أدوات +```text +"IMPORTANT: Use the following format in your response: + +Thought: you should always think about what to do +Action: the action to take, only one name of [tool_names] +Action Input: the input to the action, just a simple JSON object... +``` + +#### للمخرجات المنظمة (JSON/Pydantic) +```text +"Ensure your final answer contains only the content in the following format: {output_format} +Ensure the final output does not include any code block markers like ```json or ```python." +``` + +### عرض مطالبة النظام الكاملة + +لمعرفة المطالبة المرسلة بالضبط إلى LLM، يمكنك فحص المطالبة المولّدة: + +```python +from crewai import Agent, Crew, Task +from crewai.utilities.prompts import Prompts + +# Create your agent +agent = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + backstory="You are an expert data analyst with 10 years of experience.", + verbose=True +) + +# Create a sample task +task = Task( + description="Analyze the sales data and identify trends", + expected_output="A detailed analysis with key insights and trends", + agent=agent +) + +# Create the prompt generator +prompt_generator = Prompts( + agent=agent, + has_tools=len(agent.tools) > 0, + use_system_prompt=agent.use_system_prompt +) + +# Generate and inspect the actual prompt +generated_prompt = prompt_generator.task_execution() + +# Print the complete system prompt that will be sent to the LLM +if "system" in generated_prompt: + print("=== SYSTEM PROMPT ===") + print(generated_prompt["system"]) + print("\n=== USER PROMPT ===") + print(generated_prompt["user"]) +else: + print("=== COMPLETE PROMPT ===") + print(generated_prompt["prompt"]) + +# You can also see how the task description gets formatted +print("\n=== TASK CONTEXT ===") +print(f"Task Description: {task.description}") +print(f"Expected Output: {task.expected_output}") +``` + +### تجاوز التعليمات الافتراضية + +لديك عدة خيارات للحصول على تحكم كامل في المطالبات: + +#### الخيار 1: القوالب المخصصة (مُوصى به) +```python +from crewai import Agent + +# Define your own system template without default instructions +custom_system_template = """You are {role}. {backstory} +Your goal is: {goal} + +Respond naturally and conversationally. Focus on providing helpful, accurate information.""" + +custom_prompt_template = """Task: {input} + +Please complete this task thoughtfully.""" + +agent = Agent( + role="Research Assistant", + goal="Help users find accurate information", + backstory="You are a helpful research assistant.", + system_template=custom_system_template, + prompt_template=custom_prompt_template, + use_system_prompt=True # Use separate system/user messages +) +``` + +#### الخيار 2: ملف مطالبات مخصص +أنشئ ملف `custom_prompts.json` لتجاوز شرائح مطالبات محددة: + +```json +{ + "slices": { + "no_tools": "\nProvide your best answer in a natural, conversational way.", + "tools": "\nYou have access to these tools: {tools}\n\nUse them when helpful, but respond naturally.", + "formatted_task_instructions": "Format your response as: {output_format}" + } +} +``` + +ثم استخدمه في Crew: + +```python +crew = Crew( + agents=[agent], + tasks=[task], + prompt_file="custom_prompts.json", + verbose=True +) +``` + + +يُحتفظ بـ `agent.i18n` للتوافق مع الإصدارات السابقة فقط، وقد تم إهماله. لتخصيص المطالبات أثناء التشغيل، مرّر `prompt_file` إلى `Crew`. وللوصول البرمجي المباشر إلى شرائح المطالبات، استخدم أداة i18n مباشرة: + + +```python +from crewai.utilities.i18n import get_i18n + +i18n = get_i18n("custom_prompts.json") +format_slice = i18n.slice("format") +tool_prompt = i18n.tools("ask_question") +``` + +#### الخيار 3: تعطيل مطالبات النظام لنماذج o1 +```python +agent = Agent( + role="Analyst", + goal="Analyze data", + backstory="Expert analyst", + use_system_prompt=False # Disables system prompt separation +) +``` + +### التصحيح باستخدام أدوات المراقبة + +لشفافية الإنتاج، استخدم منصات المراقبة لمتابعة جميع المطالبات وتفاعلات LLM. يتيح لك ذلك رؤية المطالبات المرسلة بالضبط (بما في ذلك التعليمات الافتراضية) إلى نماذج LLM. + +راجع [توثيق المراقبة](/ar/observability/overview) للحصول على أدلة تكامل مفصلة مع منصات متعددة بما في ذلك Langfuse وMLflow وWeights & Biases وحلول التسجيل المخصصة. + +### أفضل الممارسات للإنتاج + +1. **افحص المطالبات المولّدة دائمًا** قبل النشر في الإنتاج +2. **استخدم قوالب مخصصة** عندما تحتاج تحكمًا كاملاً في محتوى المطالبات +3. **دمج أدوات المراقبة** للمتابعة المستمرة للمطالبات (راجع [توثيق المراقبة](/ar/observability/overview)) +4. **اختبر مع نماذج LLM مختلفة** حيث قد تعمل التعليمات الافتراضية بشكل مختلف عبر النماذج +5. **وثّق تخصيصات المطالبات** لشفافية الفريق + + +التعليمات الافتراضية موجودة لضمان سلوك Agent متسق، لكنها قد تتعارض مع المتطلبات الخاصة بالمجال. استخدم خيارات التخصيص أعلاه للحفاظ على تحكم كامل في سلوك Agent في أنظمة الإنتاج. + + +## أفضل الممارسات لإدارة ملفات المطالبات + +عند الانخراط في تخصيص المطالبات على المستوى المنخفض، اتبع هذه الإرشادات للحفاظ على التنظيم وسهولة الصيانة: + +1. **احتفظ بالملفات منفصلة** – خزّن المطالبات المخصصة في ملفات JSON مخصصة خارج قاعدة الكود الرئيسية. +2. **التحكم في الإصدارات** – تتبع التغييرات داخل المستودع مع ضمان توثيق واضح لتعديلات المطالبات بمرور الوقت. +3. **التنظيم حسب النموذج أو اللغة** – استخدم تسميات مثل `prompts_llama.json` أو `prompts_es.json` لتحديد التهيئات المتخصصة بسرعة. +4. **توثيق التغييرات** – قدم تعليقات أو حافظ على ملف يوضح غرض ونطاق تخصيصاتك. +5. **قلل التعديلات** – تجاوز فقط الشرائح المحددة التي تحتاج حقًا لتعديلها مع الحفاظ على الوظائف الافتراضية لكل شيء آخر. + +## أبسط طريقة لتخصيص المطالبات + +إحدى الطرق المباشرة هي إنشاء ملف JSON للمطالبات التي تريد تجاوزها ثم توجيه Crew إلى ذلك الملف: + +1. أنشئ ملف JSON بشرائح المطالبات المحدّثة. +2. أشر إلى ذلك الملف عبر معامل `prompt_file` في Crew. + +يدمج CrewAI بعد ذلك تخصيصاتك مع الإعدادات الافتراضية، فلا تحتاج لإعادة تعريف كل مطالبة. إليك الطريقة: + +بالنسبة للكود الذي يحتاج إلى قراءة شرائح المطالبات مباشرة، استخدم `crewai.utilities.i18n.get_i18n()` مع ملف المطالبات نفسه بدلًا من قراءة `agent.i18n`. + +### مثال: تخصيص أساسي للمطالبات + +أنشئ ملف `custom_prompts.json` بالمطالبات التي تريد تعديلها. تأكد من إدراج جميع المطالبات عالية المستوى التي يجب أن يحتويها، وليس فقط تغييراتك: + +```json +{ + "slices": { + "format": "When responding, follow this structure:\n\nTHOUGHTS: Your step-by-step thinking\nACTION: Any tool you're using\nRESULT: Your final answer or conclusion" + } +} +``` + +ثم ادمجه هكذا: + +```python +from crewai import Agent, Crew, Task, Process + +# Create agents and tasks as normal +researcher = Agent( + role="Research Specialist", + goal="Find information on quantum computing", + backstory="You are a quantum physics expert", + verbose=True +) + +research_task = Task( + description="Research quantum computing applications", + expected_output="A summary of practical applications", + agent=researcher +) + +# Create a crew with your custom prompt file +crew = Crew( + agents=[researcher], + tasks=[research_task], + prompt_file="path/to/custom_prompts.json", + verbose=True +) + +# Run the crew +result = crew.kickoff() +``` + +بهذه التعديلات البسيطة، تحصل على تحكم منخفض المستوى في كيفية تواصل الـ Agents وحل المهام. + +## التحسين لنماذج محددة + +تزدهر النماذج المختلفة مع مطالبات منظمة بطرق مختلفة. إجراء تعديلات أعمق يمكن أن يعزز الأداء بشكل كبير من خلال مواءمة مطالباتك مع خصائص النموذج. + +### مثال: قالب مطالبات Llama 3.3 + +على سبيل المثال، عند التعامل مع Llama 3.3 من Meta، قد يعكس التخصيص على المستوى الأعمق الهيكل الموصى به الموضح في: +https://www.llama.com/docs/model-cards-and-prompt-formats/llama3_1/#prompt-template + +إليك مثالاً يوضح كيف يمكنك ضبط Agent للاستفادة من Llama 3.3 في الكود: + +```python +from crewai import Agent, Crew, Task, Process +from crewai_tools import DirectoryReadTool, FileReadTool + +# Define templates for system, user (prompt), and assistant (response) messages +system_template = """<|begin_of_text|><|start_header_id|>system<|end_header_id|>{{ .System }}<|eot_id|>""" +prompt_template = """<|start_header_id|>user<|end_header_id|>{{ .Prompt }}<|eot_id|>""" +response_template = """<|start_header_id|>assistant<|end_header_id|>{{ .Response }}<|eot_id|>""" + +# Create an Agent using Llama-specific layouts +principal_engineer = Agent( + role="Principal Engineer", + goal="Oversee AI architecture and make high-level decisions", + backstory="You are the lead engineer responsible for critical AI systems", + verbose=True, + llm="groq/llama-3.3-70b-versatile", # Using the Llama 3 model + system_template=system_template, + prompt_template=prompt_template, + response_template=response_template, + tools=[DirectoryReadTool(), FileReadTool()] +) + +# Define a sample task +engineering_task = Task( + description="Review AI implementation files for potential improvements", + expected_output="A summary of key findings and recommendations", + agent=principal_engineer +) + +# Create a Crew for the task +llama_crew = Crew( + agents=[principal_engineer], + tasks=[engineering_task], + process=Process.sequential, + verbose=True +) + +# Execute the crew +result = llama_crew.kickoff() +print(result.raw) +``` + +من خلال هذه التهيئة العميقة، يمكنك ممارسة تحكم شامل منخفض المستوى في سير العمل القائمة على Llama دون الحاجة إلى ملف JSON منفصل. + +## الخلاصة + +يفتح تخصيص المطالبات على المستوى المنخفض في CrewAI الباب أمام حالات استخدام مخصصة ومعقدة للغاية. من خلال إنشاء ملفات مطالبات منظمة (أو قوالب مضمّنة مباشرة)، يمكنك استيعاب نماذج ولغات ومجالات متخصصة متنوعة. يضمن هذا المستوى من المرونة أنك تستطيع صياغة سلوك الذكاء الاصطناعي الذي تحتاجه بالضبط، مع العلم أن CrewAI لا يزال يوفر إعدادات افتراضية موثوقة عندما لا تتجاوزها. + + +لديك الآن الأساس لتخصيصات المطالبات المتقدمة في CrewAI. سواء كنت تتكيف مع هياكل خاصة بالنموذج أو قيود خاصة بالمجال، يتيح لك هذا النهج المنخفض المستوى تشكيل تفاعلات الـ Agent بطرق متخصصة للغاية. + diff --git a/docs/v1.15.13/ar/guides/advanced/fingerprinting.mdx b/docs/v1.15.13/ar/guides/advanced/fingerprinting.mdx new file mode 100644 index 0000000000..12599a88fb --- /dev/null +++ b/docs/v1.15.13/ar/guides/advanced/fingerprinting.mdx @@ -0,0 +1,134 @@ +--- +title: البصمات الرقمية +description: تعلم كيفية استخدام نظام البصمات الرقمية في CrewAI لتحديد وتتبع المكونات بشكل فريد طوال دورة حياتها. +icon: fingerprint +mode: "wide" +--- + +## نظرة عامة + +توفر البصمات الرقمية في CrewAI طريقة لتحديد وتتبع المكونات بشكل فريد طوال دورة حياتها. يتلقى كل `Agent` و`Crew` و`Task` بصمة رقمية فريدة تلقائيًا عند الإنشاء، ولا يمكن تجاوزها يدويًا. + +يمكن استخدام هذه البصمات لـ: +- تدقيق وتتبع استخدام المكونات +- ضمان سلامة هوية المكونات +- إرفاق بيانات وصفية بالمكونات +- إنشاء سلسلة عمليات قابلة للتتبع + +## كيف تعمل البصمات الرقمية + +البصمة الرقمية هي نسخة من فئة `Fingerprint` من وحدة `crewai.security`. تحتوي كل بصمة على: + +- سلسلة UUID: معرّف فريد للمكون يتم إنشاؤه تلقائيًا ولا يمكن تعيينه يدويًا +- طابع زمني للإنشاء: متى تم إنشاء البصمة، يُعيَّن تلقائيًا ولا يمكن تعديله يدويًا +- بيانات وصفية: قاموس معلومات إضافية يمكن تخصيصه + +تُنشأ البصمات الرقمية وتُعيَّن تلقائيًا عند إنشاء المكون. يكشف كل مكون بصمته من خلال خاصية للقراءة فقط. + +## الاستخدام الأساسي + +### الوصول إلى البصمات الرقمية + +```python +from crewai import Agent, Crew, Task + +# Create components - fingerprints are automatically generated +agent = Agent( + role="Data Scientist", + goal="Analyze data", + backstory="Expert in data analysis" +) + +crew = Crew( + agents=[agent], + tasks=[] +) + +task = Task( + description="Analyze customer data", + expected_output="Insights from data analysis", + agent=agent +) + +# Access the fingerprints +agent_fingerprint = agent.fingerprint +crew_fingerprint = crew.fingerprint +task_fingerprint = task.fingerprint + +# Print the UUID strings +print(f"Agent fingerprint: {agent_fingerprint.uuid_str}") +print(f"Crew fingerprint: {crew_fingerprint.uuid_str}") +print(f"Task fingerprint: {task_fingerprint.uuid_str}") +``` + +### العمل مع البيانات الوصفية للبصمة + +يمكنك إضافة بيانات وصفية إلى البصمات لسياق إضافي: + +```python +# Add metadata to the agent's fingerprint +agent.security_config.fingerprint.metadata = { + "version": "1.0", + "department": "Data Science", + "project": "Customer Analysis" +} + +# Access the metadata +print(f"Agent metadata: {agent.fingerprint.metadata}") +``` + +## استمرارية البصمة + +صُممت البصمات لتبقى ثابتة دون تغيير طوال دورة حياة المكون. إذا عدّلت مكونًا، تظل البصمة كما هي: + +```python +original_fingerprint = agent.fingerprint.uuid_str + +# Modify the agent +agent.goal = "New goal for analysis" + +# The fingerprint remains unchanged +assert agent.fingerprint.uuid_str == original_fingerprint +``` + +## البصمات الحتمية + +بينما لا يمكنك تعيين UUID والطابع الزمني مباشرة، يمكنك إنشاء بصمات حتمية باستخدام طريقة `generate` مع بذرة: + +```python +from crewai.security import Fingerprint + +# Create a deterministic fingerprint using a seed string +deterministic_fingerprint = Fingerprint.generate(seed="my-agent-id") + +# The same seed always produces the same fingerprint +same_fingerprint = Fingerprint.generate(seed="my-agent-id") +assert deterministic_fingerprint.uuid_str == same_fingerprint.uuid_str + +# You can also set metadata +custom_fingerprint = Fingerprint.generate( + seed="my-agent-id", + metadata={"version": "1.0"} +) +``` + +## الاستخدام المتقدم + +### هيكل البصمة + +لكل بصمة الهيكل التالي: + +```python +from crewai.security import Fingerprint + +fingerprint = agent.fingerprint + +# UUID string - the unique identifier (auto-generated) +uuid_str = fingerprint.uuid_str # e.g., "123e4567-e89b-12d3-a456-426614174000" + +# Creation timestamp (auto-generated) +created_at = fingerprint.created_at # A datetime object + +# Metadata - for additional information (can be customized) +metadata = fingerprint.metadata # A dictionary, defaults to {} +``` diff --git a/docs/v1.15.13/ar/guides/agents/crafting-effective-agents.mdx b/docs/v1.15.13/ar/guides/agents/crafting-effective-agents.mdx new file mode 100644 index 0000000000..c1c6b1db35 --- /dev/null +++ b/docs/v1.15.13/ar/guides/agents/crafting-effective-agents.mdx @@ -0,0 +1,453 @@ +--- +title: صياغة Agents فعّالة +description: تعلم أفضل الممارسات لتصميم Agents ذكاء اصطناعي قوية ومتخصصة تتعاون بفعالية لحل المشكلات المعقدة. +icon: robot +mode: "wide" +--- + +## فن وعلم تصميم الـ Agent + +في قلب CrewAI يكمن الـ Agent - كيان ذكاء اصطناعي متخصص مصمم لأداء أدوار محددة ضمن إطار تعاوني. بينما إنشاء Agents أساسية أمر بسيط، فإن صياغة Agents فعّالة حقًا تنتج نتائج استثنائية يتطلب فهم مبادئ التصميم الأساسية وأفضل الممارسات. + +سيساعدك هذا الدليل على إتقان فن تصميم الـ Agent، مما يمكّنك من إنشاء شخصيات AI متخصصة تتعاون بفعالية وتفكر بشكل نقدي وتنتج مخرجات عالية الجودة مصممة لاحتياجاتك المحددة. + +### لماذا يهم تصميم الـ Agent + +الطريقة التي تعرّف بها الـ Agents تؤثر بشكل كبير على: + +1. **جودة المخرجات**: الـ Agents المصممة جيدًا تنتج نتائج أكثر صلة وجودة +2. **فعالية التعاون**: الـ Agents ذات المهارات المكملة تعمل معًا بكفاءة أكبر +3. **أداء المهام**: الـ Agents ذات الأدوار والأهداف الواضحة تنفذ المهام بفعالية أكبر +4. **قابلية التوسع**: الـ Agents المصممة بعناية يمكن إعادة استخدامها عبر Crews وسياقات متعددة + +لنستكشف أفضل الممارسات لإنشاء Agents تتفوق في هذه الأبعاد. + +## قاعدة 80/20: ركّز على المهام أكثر من الـ Agents + +عند بناء أنظمة AI فعّالة، تذكر هذا المبدأ الحاسم: **80% من جهدك يجب أن يذهب لتصميم المهام، و20% فقط لتعريف الـ Agents**. + +لماذا؟ لأن حتى أفضل Agent معرّف سيفشل مع مهام مصممة بشكل سيئ، لكن المهام المصممة جيدًا يمكنها رفع مستوى حتى Agent بسيط. هذا يعني: + +- اقضِ معظم وقتك في كتابة تعليمات مهام واضحة +- حدد المدخلات والمخرجات المتوقعة بالتفصيل +- أضف أمثلة وسياقًا لتوجيه التنفيذ +- خصص الوقت المتبقي لدور Agent وهدفه وخلفيته + +هذا لا يعني أن تصميم الـ Agent ليس مهمًا - بل هو مهم بالتأكيد. لكن تصميم المهام هو حيث تحدث معظم إخفاقات التنفيذ، لذا رتّب أولوياتك وفقًا لذلك. + +## المبادئ الأساسية لتصميم Agent فعّال + +### 1. إطار الدور-الهدف-الخلفية + +أقوى الـ Agents في CrewAI مبنية على أساس قوي من ثلاثة عناصر رئيسية: + +#### الدور: الوظيفة المتخصصة للـ Agent + +يحدد الدور ما يفعله الـ Agent ومجال خبرته. عند صياغة الأدوار: + +- **كن محددًا ومتخصصًا**: بدلاً من "كاتب"، استخدم "متخصص في التوثيق التقني" أو "راوي قصص إبداعي" +- **تماشَ مع المهن الواقعية**: ابنِ الأدوار على نماذج مهنية معروفة +- **تضمين خبرة المجال**: حدد مجال معرفة الـ Agent (مثل "محلل مالي متخصص في اتجاهات السوق") + +**أمثلة على أدوار فعّالة:** +```yaml +role: "Senior UX Researcher specializing in user interview analysis" +role: "Full-Stack Software Architect with expertise in distributed systems" +role: "Corporate Communications Director specializing in crisis management" +``` + +#### الهدف: غرض الـ Agent ودافعه + +يوجه الهدف جهود الـ Agent ويشكّل عملية صنع القرار. الأهداف الفعّالة يجب أن: + +- **تكون واضحة ومركّزة على النتائج**: حدد ما يحاول الـ Agent تحقيقه +- **تؤكد على معايير الجودة**: تضمين توقعات حول جودة العمل +- **تتضمن معايير النجاح**: ساعد الـ Agent على فهم ما يعنيه "الجيد" + +**أمثلة على أهداف فعّالة:** +```yaml +goal: "Uncover actionable user insights by analyzing interview data and identifying recurring patterns, unmet needs, and improvement opportunities" +goal: "Design robust, scalable system architectures that balance performance, maintainability, and cost-effectiveness" +goal: "Craft clear, empathetic crisis communications that address stakeholder concerns while protecting organizational reputation" +``` + +#### الخلفية: تجربة الـ Agent ومنظوره + +تمنح الخلفية عمقًا لشخصية الـ Agent، مؤثرة في كيفية تعامله مع المشكلات وتفاعله مع الآخرين. الخلفيات الجيدة: + +- **تؤسس الخبرة والتجربة**: تشرح كيف اكتسب الـ Agent مهاراته +- **تحدد أسلوب العمل والقيم**: تصف كيف يتعامل الـ Agent مع عمله +- **تنشئ شخصية متماسكة**: تضمن أن جميع عناصر الخلفية تتماشى مع الدور والهدف + +**أمثلة على خلفيات فعّالة:** +```yaml +backstory: "You have spent 15 years conducting and analyzing user research for top tech companies. You have a talent for reading between the lines and identifying patterns that others miss. You believe that good UX is invisible and that the best insights come from listening to what users don't say as much as what they do say." + +backstory: "With 20+ years of experience building distributed systems at scale, you've developed a pragmatic approach to software architecture. You've seen both successful and failed systems and have learned valuable lessons from each. You balance theoretical best practices with practical constraints and always consider the maintenance and operational aspects of your designs." + +backstory: "As a seasoned communications professional who has guided multiple organizations through high-profile crises, you understand the importance of transparency, speed, and empathy in crisis response. You have a methodical approach to crafting messages that address concerns while maintaining organizational credibility." +``` + +### 2. المتخصصون أفضل من العموميين + +يؤدي الـ Agents أداءً أفضل بشكل ملحوظ عند منحهم أدوارًا متخصصة بدلاً من عامة. الـ Agent المركّز بشدة ينتج مخرجات أكثر دقة وصلة: + +**عام (أقل فعالية):** +```yaml +role: "Writer" +``` + +**متخصص (أكثر فعالية):** +```yaml +role: "Technical Blog Writer specializing in explaining complex AI concepts to non-technical audiences" +``` + +**فوائد التخصص:** +- فهم أوضح للمخرجات المتوقعة +- أداء أكثر اتساقًا +- توافق أفضل مع المهام المحددة +- قدرة محسّنة على إصدار أحكام خاصة بالمجال + +### 3. التوازن بين التخصص والمرونة + +الـ Agents الفعّالة تحقق التوازن الصحيح بين التخصص (القيام بشيء واحد بشكل ممتاز) والمرونة (التكيف مع مواقف متنوعة): + +- **تخصص في الدور، مرونة في التطبيق**: أنشئ Agents بمهارات متخصصة يمكن تطبيقها عبر سياقات متعددة +- **تجنب التعريفات الضيقة جدًا**: تأكد من أن الـ Agents يمكنها التعامل مع التنوعات ضمن مجال خبرتها +- **ضع في الاعتبار السياق التعاوني**: صمم Agents تكمّل تخصصاتها الـ Agents الأخرى التي ستعمل معها + +### 4. تعيين مستويات الخبرة المناسبة + +مستوى الخبرة الذي تعيّنه للـ Agent يشكّل كيفية تعامله مع المهام: + +- **Agents مبتدئة**: جيدة للمهام المباشرة والعصف الذهني والمسودات الأولية +- **Agents متوسطة**: مناسبة لمعظم المهام القياسية مع تنفيذ موثوق +- **Agents خبيرة**: الأفضل للمهام المعقدة والمتخصصة التي تتطلب عمقًا ودقة +- **Agents على مستوى عالمي**: محجوزة للمهام الحرجة حيث الجودة الاستثنائية مطلوبة + +اختر مستوى الخبرة المناسب بناءً على تعقيد المهمة ومتطلبات الجودة. لمعظم Crews التعاونية، غالبًا ما يعمل مزيج من مستويات الخبرة بشكل أفضل، مع تعيين خبرة أعلى للوظائف المتخصصة الأساسية. + +## أمثلة عملية: قبل وبعد + +لنلقِ نظرة على بعض أمثلة تعريفات الـ Agent قبل وبعد تطبيق أفضل الممارسات: + +### مثال 1: Agent إنشاء المحتوى + +**قبل:** +```yaml +role: "Writer" +goal: "Write good content" +backstory: "You are a writer who creates content for websites." +``` + +**بعد:** +```yaml +role: "B2B Technology Content Strategist" +goal: "Create compelling, technically accurate content that explains complex topics in accessible language while driving reader engagement and supporting business objectives" +backstory: "You have spent a decade creating content for leading technology companies, specializing in translating technical concepts for business audiences. You excel at research, interviewing subject matter experts, and structuring information for maximum clarity and impact. You believe that the best B2B content educates first and sells second, building trust through genuine expertise rather than marketing hype." +``` + +### مثال 2: Agent البحث + +**قبل:** +```yaml +role: "Researcher" +goal: "Find information" +backstory: "You are good at finding information online." +``` + +**بعد:** +```yaml +role: "Academic Research Specialist in Emerging Technologies" +goal: "Discover and synthesize cutting-edge research, identifying key trends, methodologies, and findings while evaluating the quality and reliability of sources" +backstory: "With a background in both computer science and library science, you've mastered the art of digital research. You've worked with research teams at prestigious universities and know how to navigate academic databases, evaluate research quality, and synthesize findings across disciplines. You're methodical in your approach, always cross-referencing information and tracing claims to primary sources before drawing conclusions." +``` + +## صياغة مهام فعّالة للـ Agents + +بينما تصميم الـ Agent مهم، تصميم المهام حاسم للتنفيذ الناجح. إليك أفضل الممارسات لتصميم مهام تهيئ الـ Agents للنجاح: + +### تشريح المهمة الفعّالة + +المهمة المصممة جيدًا لها مكونان رئيسيان يخدمان أغراضًا مختلفة: + +#### وصف المهمة: العملية +يجب أن يركز الوصف على ماذا تفعل وكيف تفعله، بما في ذلك: +- تعليمات مفصلة للتنفيذ +- سياق ومعلومات خلفية +- النطاق والقيود +- خطوات العملية المتبعة + +#### المخرجات المتوقعة: التسليم +يجب أن تحدد المخرجات المتوقعة شكل النتيجة النهائية: +- مواصفات التنسيق (markdown، JSON، إلخ) +- متطلبات الهيكل +- معايير الجودة +- أمثلة على مخرجات جيدة (عند الإمكان) + +### أفضل ممارسات تصميم المهام + +#### 1. غرض واحد، مخرج واحد +تؤدي المهام أفضل أداء عند التركيز على هدف واضح واحد: + +**مثال سيئ (واسع جدًا):** +```yaml +task_description: "Research market trends, analyze the data, and create a visualization." +``` + +**مثال جيد (مركّز):** +```yaml +# Task 1 +research_task: + description: "Research the top 5 market trends in the AI industry for 2024." + expected_output: "A markdown list of the 5 trends with supporting evidence." + +# Task 2 +analysis_task: + description: "Analyze the identified trends to determine potential business impacts." + expected_output: "A structured analysis with impact ratings (High/Medium/Low)." + +# Task 3 +visualization_task: + description: "Create a visual representation of the analyzed trends." + expected_output: "A description of a chart showing trends and their impact ratings." +``` + +#### 2. كن صريحًا بشأن المدخلات والمخرجات +حدد دائمًا بوضوح ما المدخلات التي ستستخدمها المهمة وكيف يجب أن تبدو المخرجات: + +**مثال:** +```yaml +analysis_task: + description: > + Analyze the customer feedback data from the CSV file. + Focus on identifying recurring themes related to product usability. + Consider sentiment and frequency when determining importance. + expected_output: > + A markdown report with the following sections: + 1. Executive summary (3-5 bullet points) + 2. Top 3 usability issues with supporting data + 3. Recommendations for improvement +``` + +#### 3. تضمين الغرض والسياق +اشرح لماذا تهم المهمة وكيف تتناسب مع سير العمل الأكبر: + +**مثال:** +```yaml +competitor_analysis_task: + description: > + Analyze our three main competitors' pricing strategies. + This analysis will inform our upcoming pricing model revision. + Focus on identifying patterns in how they price premium features + and how they structure their tiered offerings. +``` + +#### 4. استخدام أدوات المخرجات المنظمة +للمخرجات القابلة للقراءة آليًا، حدد التنسيق بوضوح: + +**مثال:** +```yaml +data_extraction_task: + description: "Extract key metrics from the quarterly report." + expected_output: "JSON object with the following keys: revenue, growth_rate, customer_acquisition_cost, and retention_rate." +``` + +## أخطاء شائعة يجب تجنبها + +بناءً على الدروس المستفادة من التطبيقات الواقعية، إليك أكثر المزالق شيوعًا في تصميم الـ Agent والمهام: + +### 1. تعليمات مهام غير واضحة + +**المشكلة:** تفتقر المهام لتفاصيل كافية مما يصعّب على الـ Agents تنفيذها بفعالية. + +**مثال تصميم سيئ:** +```yaml +research_task: + description: "Research AI trends." + expected_output: "A report on AI trends." +``` + +**نسخة محسّنة:** +```yaml +research_task: + description: > + Research the top emerging AI trends for 2024 with a focus on: + 1. Enterprise adoption patterns + 2. Technical breakthroughs in the past 6 months + 3. Regulatory developments affecting implementation + + For each trend, identify key companies, technologies, and potential business impacts. + expected_output: > + A comprehensive markdown report with: + - Executive summary (5 bullet points) + - 5-7 major trends with supporting evidence + - For each trend: definition, examples, and business implications + - References to authoritative sources +``` + +### 2. "مهام إلهية" تحاول فعل الكثير + +**المشكلة:** مهام تجمع عمليات معقدة متعددة في مجموعة تعليمات واحدة. + +**مثال تصميم سيئ:** +```yaml +comprehensive_task: + description: "Research market trends, analyze competitor strategies, create a marketing plan, and design a launch timeline." +``` + +**نسخة محسّنة:** +قسّمها إلى مهام متسلسلة ومركّزة: +```yaml +# Task 1: Research +market_research_task: + description: "Research current market trends in the SaaS project management space." + expected_output: "A markdown summary of key market trends." + +# Task 2: Competitive Analysis +competitor_analysis_task: + description: "Analyze strategies of the top 3 competitors based on the market research." + expected_output: "A comparison table of competitor strategies." + context: [market_research_task] + +# Continue with additional focused tasks... +``` + +### 3. عدم توافق الوصف والمخرجات المتوقعة + +**المشكلة:** وصف المهمة يطلب شيئًا بينما المخرجات المتوقعة تحدد شيئًا مختلفًا. + +**مثال تصميم سيئ:** +```yaml +analysis_task: + description: "Analyze customer feedback to find areas of improvement." + expected_output: "A marketing plan for the next quarter." +``` + +**نسخة محسّنة:** +```yaml +analysis_task: + description: "Analyze customer feedback to identify the top 3 areas for product improvement." + expected_output: "A report listing the 3 priority improvement areas with supporting customer quotes and data points." +``` + +### 4. عدم فهم العملية بنفسك + +**المشكلة:** مطالبة الـ Agents بتنفيذ مهام لا تفهمها أنت بالكامل. + +**الحل:** +1. حاول تنفيذ المهمة يدويًا أولاً +2. وثّق عمليتك ونقاط القرار ومصادر المعلومات +3. استخدم هذا التوثيق كأساس لوصف مهمتك + +### 5. الاستخدام المبكر للهياكل الهرمية + +**المشكلة:** إنشاء هرميات Agents معقدة بلا داعٍ حيث تعمل العمليات المتسلسلة بشكل أفضل. + +**الحل:** ابدأ بالعمليات المتسلسلة وانتقل إلى النماذج الهرمية فقط عندما يتطلب تعقيد سير العمل ذلك حقًا. + +### 6. تعريفات Agent غامضة أو عامة + +**المشكلة:** تعريفات Agent العامة تؤدي لمخرجات عامة. + +**مثال تصميم سيئ:** +```yaml +agent: + role: "Business Analyst" + goal: "Analyze business data" + backstory: "You are good at business analysis." +``` + +**نسخة محسّنة:** +```yaml +agent: + role: "SaaS Metrics Specialist focusing on growth-stage startups" + goal: "Identify actionable insights from business data that can directly impact customer retention and revenue growth" + backstory: "With 10+ years analyzing SaaS business models, you've developed a keen eye for the metrics that truly matter for sustainable growth. You've helped numerous companies identify the leverage points that turned around their business trajectory. You believe in connecting data to specific, actionable recommendations rather than general observations." +``` + +## استراتيجيات متقدمة لتصميم الـ Agent + +### التصميم للتعاون + +عند إنشاء Agents ستعمل معًا في Crew، ضع في اعتبارك: + +- **مهارات مكملة**: صمم Agents بقدرات مميزة ومكملة +- **نقاط التسليم**: حدد واجهات واضحة لكيفية انتقال العمل بين الـ Agents +- **توتر بنّاء**: أحيانًا، إنشاء Agents بمنظورات مختلفة قليلاً يمكن أن يؤدي لنتائج أفضل من خلال حوار منتج + +على سبيل المثال، قد يتضمن Crew إنشاء محتوى: + +```yaml +# Research Agent +role: "Research Specialist for technical topics" +goal: "Gather comprehensive, accurate information from authoritative sources" +backstory: "You are a meticulous researcher with a background in library science..." + +# Writer Agent +role: "Technical Content Writer" +goal: "Transform research into engaging, clear content that educates and informs" +backstory: "You are an experienced writer who excels at explaining complex concepts..." + +# Editor Agent +role: "Content Quality Editor" +goal: "Ensure content is accurate, well-structured, and polished while maintaining consistency" +backstory: "With years of experience in publishing, you have a keen eye for detail..." +``` + +### إنشاء مستخدمي أدوات متخصصين + +يمكن تصميم بعض الـ Agents خصيصًا للاستفادة من أدوات معينة بفعالية: + +```yaml +role: "Data Analysis Specialist" +goal: "Derive meaningful insights from complex datasets through statistical analysis" +backstory: "With a background in data science, you excel at working with structured and unstructured data..." +tools: [PythonREPLTool, DataVisualizationTool, CSVAnalysisTool] +``` + +### تكييف الـ Agents مع قدرات LLM + +للنماذج المختلفة نقاط قوة مختلفة. صمم الـ Agents مع وضع هذه القدرات في الاعتبار: + +```yaml +# For complex reasoning tasks +analyst: + role: "Data Insights Analyst" + goal: "..." + backstory: "..." + llm: openai/gpt-4o + +# For creative content +writer: + role: "Creative Content Writer" + goal: "..." + backstory: "..." + llm: anthropic/claude-3-opus +``` + +## اختبار تصميم الـ Agent والتكرار عليه + +تصميم الـ Agent غالبًا عملية تكرارية. إليك نهجًا عمليًا: + +1. **ابدأ بنموذج أولي**: أنشئ تعريف Agent أولي +2. **اختبر مع مهام نموذجية**: قيّم الأداء على مهام تمثيلية +3. **حلل المخرجات**: حدد نقاط القوة والضعف +4. **صقل التعريف**: اضبط الدور والهدف والخلفية بناءً على الملاحظات +5. **اختبر في بيئة تعاونية**: قيّم كيف يعمل الـ Agent في إعداد Crew + +## الخلاصة + +صياغة Agents فعّالة هي فن وعلم في آن واحد. من خلال تعريف الأدوار والأهداف والخلفيات بعناية بما يتماشى مع احتياجاتك المحددة، ودمجها مع مهام مصممة جيدًا، يمكنك إنشاء متعاونين AI متخصصين ينتجون نتائج استثنائية. + +تذكر أن تصميم الـ Agent والمهام عملية تكرارية. ابدأ بأفضل الممارسات هذه، وراقب الـ Agents أثناء العمل، وصقل نهجك بناءً على ما تتعلمه. وتذكر دائمًا قاعدة 80/20 - ركّز معظم جهدك على إنشاء مهام واضحة ومركّزة للحصول على أفضل النتائج من الـ Agents. + + +تهانينا! أنت الآن تفهم مبادئ وممارسات تصميم Agent الفعّال. طبّق هذه التقنيات لإنشاء Agents قوية ومتخصصة تعمل معًا بسلاسة لإنجاز مهام معقدة. + + +## الخطوات التالية + +- جرّب تهيئات Agent مختلفة لحالة استخدامك المحددة +- تعلم عن [بناء أول Crew](/ar/guides/crews/first-crew) لمعرفة كيف تعمل الـ Agents معًا +- استكشف [CrewAI Flows](/ar/guides/flows/first-flow) لتنسيق أكثر تقدمًا diff --git a/docs/v1.15.13/ar/guides/coding-tools/agents-md.mdx b/docs/v1.15.13/ar/guides/coding-tools/agents-md.mdx new file mode 100644 index 0000000000..e118b72eb6 --- /dev/null +++ b/docs/v1.15.13/ar/guides/coding-tools/agents-md.mdx @@ -0,0 +1,61 @@ +--- +title: أدوات البرمجة +description: استخدم AGENTS.md لتوجيه أدوات البرمجة وبيئات التطوير عبر مشاريع CrewAI. +icon: terminal +mode: "wide" +--- + +## لماذا AGENTS.md + +`AGENTS.md` هو ملف تعليمات خفيف محلي للمستودع يمنح أدوات البرمجة توجيهات متسقة خاصة بالمشروع. ضعه في جذر المشروع واعتبره المصدر الموثوق لكيفية عمل المساعدين: الاصطلاحات والأوامر وملاحظات البنية والحدود. + +## إنشاء مشروع باستخدام CLI + +استخدم CLI الخاص بـ CrewAI لإنشاء هيكل مشروع، وسيُضاف `AGENTS.md` تلقائيًا في الجذر. + +```bash +# Crew +crewai create crew my_crew + +# Flow +crewai create flow my_flow + +# Tool repository +crewai tool create my_tool +``` + +## إعداد الأدوات: توجيه المساعدين إلى AGENTS.md + +### Codex + +يمكن توجيه Codex بملفات `AGENTS.md` الموضوعة في مستودعك. استخدمها لتوفير سياق مشروع مستمر مثل الاصطلاحات والأوامر وتوقعات سير العمل. + +### Claude Code + +يخزّن Claude Code ذاكرة المشروع في `CLAUDE.md`. يمكنك تهيئته بـ `/init` وتحريره باستخدام `/memory`. يدعم Claude Code أيضًا الاستيرادات داخل `CLAUDE.md`، فيمكنك إضافة سطر واحد مثل `@AGENTS.md` لسحب التعليمات المشتركة دون تكرارها. + +يمكنك ببساطة استخدام: + +```bash +mv AGENTS.md CLAUDE.md +``` + +### Gemini CLI وGoogle Antigravity + +يقوم Gemini CLI وAntigravity بتحميل ملف سياق المشروع (الافتراضي: `GEMINI.md`) من جذر المستودع والمجلدات الأصلية. يمكنك تهيئته لقراءة `AGENTS.md` بدلاً من ذلك (أو بالإضافة إليه) بتعيين `context.fileName` في إعدادات Gemini CLI. على سبيل المثال، عيّنه إلى `AGENTS.md` فقط، أو أدرج كلاً من `AGENTS.md` و`GEMINI.md` إذا أردت الاحتفاظ بتنسيق كل أداة. + +يمكنك ببساطة استخدام: + +```bash +mv AGENTS.md GEMINI.md +``` + +### Cursor + +يدعم Cursor ملف `AGENTS.md` كملف تعليمات مشروع. ضعه في جذر المشروع لتوفير توجيهات لمساعد البرمجة في Cursor. + +### Windsurf + +يوفر Claude Code تكاملاً رسميًا مع Windsurf. إذا كنت تستخدم Claude Code داخل Windsurf، اتبع توجيهات Claude Code أعلاه واستورد `AGENTS.md` من `CLAUDE.md`. + +إذا كنت تستخدم مساعد Windsurf الأصلي، هيّئ ميزة قواعد أو تعليمات المشروع (إذا كانت متاحة) لقراءة `AGENTS.md` أو الصق المحتويات مباشرة. diff --git a/docs/v1.15.13/ar/guides/coding-tools/build-with-ai.mdx b/docs/v1.15.13/ar/guides/coding-tools/build-with-ai.mdx new file mode 100644 index 0000000000..caaf70c211 --- /dev/null +++ b/docs/v1.15.13/ar/guides/coding-tools/build-with-ai.mdx @@ -0,0 +1,214 @@ +--- +title: "البناء باستخدام الذكاء الاصطناعي" +description: "كل ما يحتاجه وكلاء البرمجة بالذكاء الاصطناعي للبناء والنشر والتوسع مع CrewAI — المهارات، وثائق مقروءة آلياً، النشر، وميزات المؤسسات." +icon: robot +mode: "wide" +--- + +# البناء باستخدام الذكاء الاصطناعي + +CrewAI مُصمَّم أصلاً للعمل مع الذكاء الاصطناعي. تجمع هذه الصفحة ما يحتاجه وكيل البرمجة بالذكاء الاصطناعي للبناء مع CrewAI — سواءً كان Claude Code أو Codex أو Cursor أو Gemini CLI أو أي مساعد آخر يساعد المطوّر على إيصال الـ crews والـ flows. + +### وكلاء البرمجة المدعومون + + + + + + + + + + + صُممت هذه الصفحة للبشر وللمساعدين الذكيين على حدٍّ سواء. إذا كنت وكيل برمجة، ابدأ بـ **Skills** للحصول على سياق CrewAI، ثم استخدم **llms.txt** للوصول الكامل إلى الوثائق. + + +--- + +## 1. Skills — علِّم وكيلك CrewAI + +**Skills** حزم تعليمات تمنح وكلاء البرمجة معرفة عميقة بـ CrewAI — كيفية إنشاء هيكل Flows، وضبط Crews، استخدام الأدوات، واتباع اتفاقيات الإطار. + + + + Anthropic + مهارات CrewAI متاحة في **سوق إضافات Claude Code** — نفس قناة التوزيع التي تستخدمها شركات رائدة في مجال الذكاء الاصطناعي: + ```shell + /plugin marketplace add crewAIInc/skills + /plugin install crewai-skills@crewai-plugins + /reload-plugins + ``` + + تُفعَّل أربع مهارات تلقائياً عند طرح أسئلة متعلقة بـ CrewAI: + + | المهارة | متى تُستخدم | + |---------|-------------| + | `getting-started` | مشاريع جديدة، الاختيار بين `LLM.call()` / `Agent` / `Crew` / `Flow`، ربط `crew.jsonc` / `main.py` | + | `design-agent` | ضبط الوكلاء — الدور، الهدف، الخلفية، الأدوات، نماذج اللغة، الذاكرة، الحدود الآمنة | + | `design-task` | وصف المهام، التبعيات، المخرجات المنظمة (`output_pydantic`، `output_json`)، المراجعة البشرية | + | `ask-docs` | الاستعلام من [خادم CrewAI docs MCP](https://docs.crewai.com/mcp) للحصول على تفاصيل واجهة البرمجة الحالية | + + + يعمل مع Claude Code أو Codex أو Cursor أو Gemini CLI أو أي وكيل برمجة: + ```shell + npx skills add crewaiinc/skills + ``` + يُجلب من [سجل skills.sh](https://skills.sh/crewaiinc/skills). + + + + + + استخدم إحدى الطريقتين أعلاه — سوق إضافات Claude Code أو `npx skills add`. كلاهما يثبّت الحزمة الرسمية [crewAIInc/skills](https://github.com/crewAIInc/skills). + + + تعلّم الحزمة وكيلك: + - **Flows** — تطبيقات ذات حالة، خطوات، وتشغيل crews + - **Crews والوكلاء** — أنماط JSON-first (`crew.jsonc` و `agents/*.jsonc`)، الأدوار، المهام، التفويض + - **الأدوات والتكاملات** — البحث، واجهات API، خوادم MCP، وأدوات CrewAI الشائعة + - **هيكل المشروع** — هياكل CLI واتفاقيات المستودع + - **أنماط محدثة** — يتماشى مع وثائق CrewAI الحالية وأفضل الممارسات + + + يمكن لوكيلك الآن إنشاء هيكل وبناء مشاريع CrewAI دون أن تعيد شرح الإطار في كل جلسة. + + + + + + كيف تعمل المهارات في وكلاء CrewAI — الحقن، التفعيل، والأنماط. + + + نظرة على حزمة crewAIInc/skills وما تتضمنه. + + + إعداد AGENTS.md لـ Claude Code وCodex وCursor وGemini CLI. + + + القائمة الرسمية — المهارات، إحصاءات التثبيت، والتدقيق. + + + +--- + +## 2. llms.txt — وثائق مقروءة آلياً + +ينشر CrewAI ملف `llms.txt` يمنح المساعدين الذكيين وصولاً مباشراً إلى الوثائق الكاملة بصيغة مقروءة آلياً. + +``` +https://docs.crewai.com/llms.txt +``` + + + + [`llms.txt`](https://llmstxt.org/) معيار ناشئ لجعل الوثائق قابلة للاستهلاك من قبل نماذج اللغة الكبيرة. بدلاً من استخراج HTML، يمكن لوكيلك جلب ملف نصي واحد منظم بكل المحتوى المطلوب. + + ملف `llms.txt` الخاص بـ CrewAI **متاح فعلياً** — يمكن لوكيلك استخدامه الآن. + + + وجِّه وكيل البرمجة إلى عنوان URL عندما يحتاج إلى مرجع CrewAI: + + ``` + Fetch https://docs.crewai.com/llms.txt for CrewAI documentation. + ``` + + يمكن للعديد من وكلاء البرمجة (Claude Code، Cursor، وغيرهما) جلب عناوين URL مباشرة. يحتوي الملف على وثائق منظمة تغطي مفاهيم CrewAI وواجهات البرمجة والأدلة. + + + - **دون استخراج ويب** — محتوى نظيف ومنظم في طلب واحد + - **دائماً محدث** — يُقدَّم مباشرة من docs.crewai.com + - **محسّن لنماذج اللغة** — مُنسَّق لنوافذ السياق لا للمتصفحات + - **يُكمّل Skills** — المهارات تعلّم الأنماط، وllms.txt يوفّر المرجع + + + +--- + +## 3. النشر للمؤسسات + +انتقل من crew محلي إلى الإنتاج على **CrewAI AMP** (منصة إدارة الوكلاء) في دقائق. + + + + أنشئ الهيكل واختبر crew أو flow: + ```bash + crewai create crew my_crew + cd my_crew + crewai run + ``` + + + تأكد أن هيكل مشروعك جاهز: + ```bash + crewai deploy --prepare + ``` + راجع [دليل التحضير](https://docs-platform.crewai.com/platform/ar/guides/prepare-for-deployment) لتفاصيل الهيكل والمتطلبات. + + + ادفع إلى منصة CrewAI AMP: + ```bash + crewai deploy + ``` + يمكنك أيضاً النشر عبر [تكامل GitHub](https://docs-platform.crewai.com/platform/ar/guides/deploy-to-amp) أو [Crew Studio](https://docs-platform.crewai.com/platform/ar/guides/enable-crew-studio). + + + يحصل الـ crew المنشور على نقطة نهاية REST. دمجه في أي تطبيق: + ```bash + curl -X POST https://app.crewai.com/api/v1/crews//kickoff \ + -H "Authorization: Bearer $CREWAI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"inputs": {"topic": "AI agents"}}' + ``` + + + + + + دليل النشر الكامل — CLI وGitHub وCrew Studio. + + + نظرة على المنصة — ما يوفّره AMP لـ crews في الإنتاج. + + + +--- + +## 4. ميزات المؤسسات + +CrewAI AMP مُصمَّم لفرق الإنتاج. إليك ما تحصل عليه بعد النشر. + + + + مسارات تنفيذ مفصّلة، وسجلات، ومقاييس أداء لكل تشغيل crew. راقب قرارات الوكلاء، استدعاءات الأدوات، وإكمال المهام في الوقت الفعلي. + + + واجهة منخفضة/بدون كود لإنشاء crews وتخصيصها ونشرها بصرياً — ثم التصدير إلى الشيفرة أو النشر مباشرة. + + + بث أحداث فورية من تنفيذات الـ crews إلى أنظمتك. تكامل مع Slack أو Zapier أو أي مستهلك ويبهوك. + + + SSO وRBAC وضوابط على مستوى المؤسسة. أدر من يمكنه إنشاء crews ونشرها والوصول إليها. + + + انشر وشارك أدواتاً مخصصة عبر مؤسستك. ثبّت أدوات المجتمع من السجل. + + + شغّل CrewAI AMP على بنيتك التحتية. قدرات المنصة كاملة مع ضوابط إقامة البيانات والامتثال. + + + + + + لفرق تحتاج نقل سير عمل وكلاء الذكاء الاصطناعي من النماذج الأولية إلى الإنتاج — مع المراقبة وضوابط الوصول والبنية التحتية القابلة للتوسع. سواءً كنت ناشئاً أو مؤسسة كبيرة، يتولى AMP التعقيد التشغيلي لتتفرغ لبناء الوكلاء. + + + - **السحابة (app.crewai.com)** — تُدار من CrewAI، أسرع طريق إلى الإنتاج + - **Factory (استضافة ذاتية)** — على بنيتك التحتية لسيطرة كاملة على البيانات + - **هجين** — دمج السحابة والاستضافة الذاتية حسب حساسية البيانات + + + + + سجّل وانشر أول crew لك في الإنتاج. + diff --git a/docs/v1.15.13/ar/guides/concepts/evaluating-use-cases.mdx b/docs/v1.15.13/ar/guides/concepts/evaluating-use-cases.mdx new file mode 100644 index 0000000000..a0a3d5f428 --- /dev/null +++ b/docs/v1.15.13/ar/guides/concepts/evaluating-use-cases.mdx @@ -0,0 +1,485 @@ +--- +title: تقييم حالات الاستخدام لـ CrewAI +description: تعلم كيفية تقييم احتياجات تطبيقات الذكاء الاصطناعي واختيار النهج الصحيح بين Crews وFlows بناءً على متطلبات التعقيد والدقة. +icon: scale-balanced +mode: "wide" +--- + +## فهم إطار القرار + +عند بناء تطبيقات ذكاء اصطناعي مع CrewAI، أحد أهم القرارات التي ستتخذها هو اختيار النهج الصحيح لحالة الاستخدام المحددة. هل يجب استخدام Crew؟ أم Flow؟ أم مزيج من كليهما؟ سيساعدك هذا الدليل على تقييم متطلباتك واتخاذ قرارات معمارية مدروسة. + +في جوهر هذا القرار فهم العلاقة بين **التعقيد** و**الدقة** في تطبيقك: + + + مصفوفة التعقيد مقابل الدقة + + +تساعد هذه المصفوفة في تصور كيف تتوافق النهج المختلفة مع متطلبات متفاوتة للتعقيد والدقة. لنستكشف ما يعنيه كل ربع وكيف يوجه خياراتك المعمارية. + +## شرح مصفوفة التعقيد-الدقة + +### ما هو التعقيد؟ + +في سياق تطبيقات CrewAI، يشير **التعقيد** إلى: + +- عدد الخطوات أو العمليات المميزة المطلوبة +- تنوع المهام التي يجب تنفيذها +- التبعيات المتبادلة بين المكونات المختلفة +- الحاجة للمنطق الشرطي والتفرع +- تطور سير العمل الكلي + +### ما هي الدقة؟ + +**الدقة** في هذا السياق تشير إلى: + +- الدقة المطلوبة في المخرجات النهائية +- الحاجة لنتائج منظمة وقابلة للتنبؤ +- أهمية إمكانية التكرار +- مستوى التحكم المطلوب في كل خطوة +- تحمّل التباين في المخرجات + +### الأرباع الأربعة + +#### 1. تعقيد منخفض، دقة منخفضة + +**الخصائص:** +- مهام بسيطة ومباشرة +- تحمّل بعض التباين في المخرجات +- عدد محدود من الخطوات +- تطبيقات إبداعية أو استكشافية + +**النهج الموصى به:** Crews بسيطة مع عدد قليل من الـ Agents + +**أمثلة على حالات الاستخدام:** +- إنشاء محتوى أساسي +- العصف الذهني +- مهام التلخيص البسيطة +- مساعدة الكتابة الإبداعية + +#### 2. تعقيد منخفض، دقة عالية + +**الخصائص:** +- سير عمل بسيطة تتطلب مخرجات دقيقة ومنظمة +- حاجة لنتائج قابلة للتكرار +- خطوات محدودة مع متطلبات دقة عالية +- غالبًا تتضمن معالجة أو تحويل بيانات + +**النهج الموصى به:** Flows مع استدعاءات LLM مباشرة أو Crews بسيطة مع مخرجات منظمة + +**أمثلة على حالات الاستخدام:** +- استخراج البيانات وتحويلها +- ملء النماذج والتحقق منها +- إنشاء محتوى منظم (JSON، XML) +- مهام التصنيف البسيطة + +#### 3. تعقيد عالٍ، دقة منخفضة + +**الخصائص:** +- عمليات متعددة المراحل بخطوات كثيرة +- مخرجات إبداعية أو استكشافية +- تفاعلات معقدة بين المكونات +- تحمّل التباين في النتائج النهائية + +**النهج الموصى به:** Crews معقدة مع عدة Agents متخصصة + +**أمثلة على حالات الاستخدام:** +- البحث والتحليل +- خطوط إنتاج المحتوى +- تحليل البيانات الاستكشافي +- حل المشكلات الإبداعي + +#### 4. تعقيد عالٍ، دقة عالية + +**الخصائص:** +- سير عمل معقدة تتطلب مخرجات منظمة +- خطوات مترابطة متعددة مع متطلبات دقة صارمة +- حاجة لمعالجة متطورة ونتائج دقيقة معًا +- غالبًا تطبيقات حرجة المهمة + +**النهج الموصى به:** Flows تنسّق عدة Crews مع خطوات تحقق + +**أمثلة على حالات الاستخدام:** +- أنظمة دعم القرار المؤسسية +- خطوط معالجة بيانات معقدة +- معالجة مستندات متعددة المراحل +- تطبيقات الصناعات المنظمة + +## الاختيار بين Crews وFlows + +### متى تختار Crews + +الـ Crews مثالية عندما: + +1. **تحتاج ذكاء تعاوني** - عدة Agents بتخصصات مختلفة تحتاج للعمل معًا +2. **المشكلة تتطلب تفكيرًا ناشئًا** - الحل يستفيد من منظورات ونُهج مختلفة +3. **المهمة إبداعية أو تحليلية بالأساس** - العمل يتضمن بحثًا أو إنشاء محتوى أو تحليل +4. **تقدّر القدرة على التكيف على الهيكل الصارم** - سير العمل يمكن أن يستفيد من استقلالية الـ Agent +5. **تنسيق المخرجات يمكن أن يكون مرنًا نوعًا ما** - بعض التباين في هيكل المخرجات مقبول + +```python +# Example: Research Crew for market analysis +from crewai import Agent, Crew, Process, Task + +# Create specialized agents +researcher = Agent( + role="Market Research Specialist", + goal="Find comprehensive market data on emerging technologies", + backstory="You are an expert at discovering market trends and gathering data." +) + +analyst = Agent( + role="Market Analyst", + goal="Analyze market data and identify key opportunities", + backstory="You excel at interpreting market data and spotting valuable insights." +) + +# Define their tasks +research_task = Task( + description="Research the current market landscape for AI-powered healthcare solutions", + expected_output="Comprehensive market data including key players, market size, and growth trends", + agent=researcher +) + +analysis_task = Task( + description="Analyze the market data and identify the top 3 investment opportunities", + expected_output="Analysis report with 3 recommended investment opportunities and rationale", + agent=analyst, + context=[research_task] +) + +# Create the crew +market_analysis_crew = Crew( + agents=[researcher, analyst], + tasks=[research_task, analysis_task], + process=Process.sequential, + verbose=True +) + +# Run the crew +result = market_analysis_crew.kickoff() +``` + +### متى تختار Flows + +الـ Flows مثالية عندما: + +1. **تحتاج تحكمًا دقيقًا في التنفيذ** - سير العمل يتطلب تسلسلًا دقيقًا وإدارة حالة +2. **التطبيق له متطلبات حالة معقدة** - تحتاج لصيانة وتحويل الحالة عبر خطوات متعددة +3. **تحتاج مخرجات منظمة وقابلة للتنبؤ** - التطبيق يتطلب نتائج متسقة ومنسّقة +4. **سير العمل يتضمن منطقًا شرطيًا** - مسارات مختلفة يجب اتخاذها بناءً على نتائج وسيطة +5. **تحتاج الجمع بين AI وكود إجرائي** - الحل يتطلب قدرات AI وبرمجة تقليدية معًا + +```python +# Example: Customer Support Flow with structured processing +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel +from typing import List, Dict + +# Define structured state +class SupportTicketState(BaseModel): + ticket_id: str = "" + customer_name: str = "" + issue_description: str = "" + category: str = "" + priority: str = "medium" + resolution: str = "" + satisfaction_score: int = 0 + +class CustomerSupportFlow(Flow[SupportTicketState]): + @start() + def receive_ticket(self): + self.state.ticket_id = "TKT-12345" + self.state.customer_name = "Alex Johnson" + self.state.issue_description = "Unable to access premium features after payment" + return "Ticket received" + + @listen(receive_ticket) + def categorize_ticket(self, _): + from crewai import LLM + llm = LLM(model="openai/gpt-4o-mini") + + prompt = f""" + Categorize the following customer support issue into one of these categories: + - Billing + - Account Access + - Technical Issue + - Feature Request + - Other + + Issue: {self.state.issue_description} + + Return only the category name. + """ + + self.state.category = llm.call(prompt).strip() + return self.state.category + + @router(categorize_ticket) + def route_by_category(self, category): + return category.lower().replace(" ", "_") + + @listen("billing") + def handle_billing_issue(self): + self.state.priority = "high" + return "Billing issue handled" + + @listen("account_access") + def handle_access_issue(self): + self.state.priority = "high" + return "Access issue handled" + + @listen("billing", "account_access", "technical_issue", "feature_request", "other") + def resolve_ticket(self, resolution_info): + self.state.resolution = f"Issue resolved: {resolution_info}" + return self.state.resolution + +# Run the flow +support_flow = CustomerSupportFlow() +result = support_flow.kickoff() +``` + +### متى تجمع بين Crews وFlows + +أكثر التطبيقات تطورًا غالبًا تستفيد من الجمع بين Crews وFlows: + +1. **عمليات معقدة متعددة المراحل** - استخدم Flows لتنسيق العملية الكلية وCrews للمهام الفرعية المعقدة +2. **تطبيقات تتطلب إبداعًا وهيكلاً معًا** - استخدم Crews للمهام الإبداعية وFlows للمعالجة المنظمة +3. **تطبيقات AI مؤسسية** - استخدم Flows لإدارة الحالة وتدفق العمليات مع الاستفادة من Crews للعمل المتخصص + +```python +# Example: Content Production Pipeline combining Crews and Flows +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel +from typing import List, Dict + +class ContentState(BaseModel): + topic: str = "" + target_audience: str = "" + content_type: str = "" + outline: Dict = {} + draft_content: str = "" + final_content: str = "" + seo_score: int = 0 + +class ContentProductionFlow(Flow[ContentState]): + @start() + def initialize_project(self): + self.state.topic = "Sustainable Investing" + self.state.target_audience = "Millennial Investors" + self.state.content_type = "Blog Post" + return "Project initialized" + + @listen(initialize_project) + def create_outline(self, _): + researcher = Agent( + role="Content Researcher", + goal=f"Research {self.state.topic} for {self.state.target_audience}", + backstory="You are an expert researcher with deep knowledge of content creation." + ) + + outliner = Agent( + role="Content Strategist", + goal=f"Create an engaging outline for a {self.state.content_type}", + backstory="You excel at structuring content for maximum engagement." + ) + + research_task = Task( + description=f"Research {self.state.topic} focusing on what would interest {self.state.target_audience}", + expected_output="Comprehensive research notes with key points and statistics", + agent=researcher + ) + + outline_task = Task( + description=f"Create an outline for a {self.state.content_type} about {self.state.topic}", + expected_output="Detailed content outline with sections and key points", + agent=outliner, + context=[research_task] + ) + + outline_crew = Crew( + agents=[researcher, outliner], + tasks=[research_task, outline_task], + process=Process.sequential, + verbose=True + ) + + result = outline_crew.kickoff() + + import json + try: + self.state.outline = json.loads(result.raw) + except: + self.state.outline = {"sections": result.raw} + + return "Outline created" + + @listen(create_outline) + def write_content(self, _): + writer = Agent( + role="Content Writer", + goal=f"Write engaging content for {self.state.target_audience}", + backstory="You are a skilled writer who creates compelling content." + ) + + editor = Agent( + role="Content Editor", + goal="Ensure content is polished, accurate, and engaging", + backstory="You have a keen eye for detail and a talent for improving content." + ) + + writing_task = Task( + description=f"Write a {self.state.content_type} about {self.state.topic} following this outline: {self.state.outline}", + expected_output="Complete draft content in markdown format", + agent=writer + ) + + editing_task = Task( + description="Edit and improve the draft content for clarity, engagement, and accuracy", + expected_output="Polished final content in markdown format", + agent=editor, + context=[writing_task] + ) + + writing_crew = Crew( + agents=[writer, editor], + tasks=[writing_task, editing_task], + process=Process.sequential, + verbose=True + ) + + result = writing_crew.kickoff() + self.state.final_content = result.raw + + return "Content created" + + @listen(write_content) + def optimize_for_seo(self, _): + from crewai import LLM + llm = LLM(model="openai/gpt-4o-mini") + + prompt = f""" + Analyze this content for SEO effectiveness for the keyword "{self.state.topic}". + Rate it on a scale of 1-100 and provide 3 specific recommendations for improvement. + + Content: {self.state.final_content[:1000]}... (truncated for brevity) + + Format your response as JSON with the following structure: + {{ + "score": 85, + "recommendations": [ + "Recommendation 1", + "Recommendation 2", + "Recommendation 3" + ] + }} + """ + + seo_analysis = llm.call(prompt) + + import json + try: + analysis = json.loads(seo_analysis) + self.state.seo_score = analysis.get("score", 0) + return analysis + except: + self.state.seo_score = 50 + return {"score": 50, "recommendations": ["Unable to parse SEO analysis"]} + +# Run the flow +content_flow = ContentProductionFlow() +result = content_flow.kickoff() +``` + +## إطار التقييم العملي + +لتحديد النهج الصحيح لحالة استخدامك المحددة، اتبع إطار التقييم التدريجي هذا: + +### الخطوة 1: تقييم التعقيد + +قيّم تعقيد تطبيقك على مقياس من 1-10 من خلال النظر في: + +1. **عدد الخطوات**: كم عدد العمليات المميزة المطلوبة؟ + - 1-3 خطوات: تعقيد منخفض (1-3) + - 4-7 خطوات: تعقيد متوسط (4-7) + - 8+ خطوات: تعقيد عالٍ (8-10) + +2. **التبعيات المتبادلة**: ما مدى ترابط الأجزاء المختلفة؟ + - تبعيات قليلة: تعقيد منخفض (1-3) + - بعض التبعيات: تعقيد متوسط (4-7) + - تبعيات معقدة كثيرة: تعقيد عالٍ (8-10) + +3. **المنطق الشرطي**: ما مقدار التفرع وصنع القرار المطلوب؟ + - عملية خطية: تعقيد منخفض (1-3) + - بعض التفرع: تعقيد متوسط (4-7) + - أشجار قرار معقدة: تعقيد عالٍ (8-10) + +4. **المعرفة التخصصية**: ما مدى تخصص المعرفة المطلوبة؟ + - معرفة عامة: تعقيد منخفض (1-3) + - بعض المعرفة المتخصصة: تعقيد متوسط (4-7) + - خبرة عميقة في مجالات متعددة: تعقيد عالٍ (8-10) + +احسب متوسط درجتك لتحديد التعقيد الكلي. + +### الخطوة 2: تقييم متطلبات الدقة + +قيّم متطلبات الدقة على مقياس من 1-10 من خلال النظر في: + +1. **هيكل المخرجات**: ما مدى التنظيم المطلوب في المخرجات؟ + - نص حر: دقة منخفضة (1-3) + - شبه منظم: دقة متوسطة (4-7) + - منسّق بشكل صارم (JSON، XML): دقة عالية (8-10) + +2. **احتياجات الدقة**: ما أهمية الدقة الواقعية؟ + - محتوى إبداعي: دقة منخفضة (1-3) + - محتوى معلوماتي: دقة متوسطة (4-7) + - معلومات حرجة: دقة عالية (8-10) + +3. **إمكانية التكرار**: ما مدى اتساق النتائج عبر التشغيلات؟ + - التباين مقبول: دقة منخفضة (1-3) + - بعض الاتساق مطلوب: دقة متوسطة (4-7) + - تكرار دقيق مطلوب: دقة عالية (8-10) + +4. **تحمّل الأخطاء**: ما تأثير الأخطاء؟ + - تأثير منخفض: دقة منخفضة (1-3) + - تأثير معتدل: دقة متوسطة (4-7) + - تأثير عالٍ: دقة عالية (8-10) + +احسب متوسط درجتك لتحديد متطلبات الدقة الكلية. + +### الخطوة 3: التعيين على المصفوفة + +ارسم درجات التعقيد والدقة على المصفوفة: + +- **تعقيد منخفض (1-4)، دقة منخفضة (1-4)**: Crews بسيطة +- **تعقيد منخفض (1-4)، دقة عالية (5-10)**: Flows مع استدعاءات LLM مباشرة +- **تعقيد عالٍ (5-10)، دقة منخفضة (1-4)**: Crews معقدة +- **تعقيد عالٍ (5-10)، دقة عالية (5-10)**: Flows تنسّق Crews + +### الخطوة 4: مراعاة عوامل إضافية + +بالإضافة إلى التعقيد والدقة، ضع في اعتبارك: + +1. **وقت التطوير**: غالبًا ما تكون Crews أسرع في النماذج الأولية +2. **احتياجات الصيانة**: توفر Flows قابلية صيانة أفضل على المدى الطويل +3. **خبرة الفريق**: ضع في اعتبارك ألفة فريقك مع النُهج المختلفة +4. **متطلبات التوسع**: عادةً ما تتوسع Flows بشكل أفضل للتطبيقات المعقدة +5. **احتياجات التكامل**: ضع في اعتبارك كيف سيتكامل الحل مع الأنظمة الحالية + +## الخلاصة + +الاختيار بين Crews وFlows — أو الجمع بينهما — قرار معماري حاسم يؤثر على فعالية وقابلية صيانة وتوسع تطبيق CrewAI. من خلال تقييم حالة الاستخدام على أبعاد التعقيد والدقة، يمكنك اتخاذ قرارات مدروسة تتماشى مع متطلباتك المحددة. + +تذكر أن أفضل نهج غالبًا يتطور مع نضج تطبيقك. ابدأ بأبسط حل يلبي احتياجاتك، وكن مستعدًا لصقل بنيتك مع اكتساب الخبرة ووضوح المتطلبات. + + +لديك الآن إطار لتقييم حالات استخدام CrewAI واختيار النهج الصحيح بناءً على متطلبات التعقيد والدقة. سيساعدك هذا في بناء تطبيقات AI أكثر فعالية وقابلية للصيانة والتوسع. + + +## الخطوات التالية + +- تعلم المزيد عن [صياغة Agents فعّالة](/ar/guides/agents/crafting-effective-agents) +- استكشف [بناء أول Crew](/ar/guides/crews/first-crew) +- تعمّق في [إتقان إدارة حالة Flow](/ar/guides/flows/mastering-flow-state) +- اطلع على [المفاهيم الأساسية](/ar/concepts/agents) لفهم أعمق diff --git a/docs/v1.15.13/ar/guides/crews/first-crew.mdx b/docs/v1.15.13/ar/guides/crews/first-crew.mdx new file mode 100644 index 0000000000..db07c6ff9b --- /dev/null +++ b/docs/v1.15.13/ar/guides/crews/first-crew.mdx @@ -0,0 +1,140 @@ +--- +title: ابنِ أول Crew +description: دليل خطوة بخطوة لإنشاء فريق AI تعاوني باستخدام تهيئة JSON-first. +icon: users-gear +mode: "wide" +--- + +## بناء Crew للبحث + +في هذا الدليل ستنشئ crew من Agentين: واحد للبحث وآخر لكتابة تقرير markdown. مشاريع الـ crew الجديدة هي JSON-first: تُعرّف الـ Agents في `agents/*.jsonc`، وتُعرّف المهام وإعدادات الـ crew في `crew.jsonc`، ويحمّل `crewai run` هذا التعريف مباشرة. + +### المتطلبات + +1. تثبيت CrewAI من [دليل التثبيت](/ar/installation) +2. إعداد مفتاح LLM من [دليل LLMs](/ar/concepts/llms#setting-up-your-llm) +3. مفتاح [Serper.dev](https://serper.dev/) إذا أردت استخدام البحث على الويب + +## الخطوة 1: إنشاء Crew جديدة + +```bash +crewai create crew research_crew +cd research_crew +``` + +البنية الناتجة: + +```text +research_crew/ +├── .gitignore +├── .env +├── agents/ +│ └── researcher.jsonc +├── crew.jsonc +├── knowledge/ +├── pyproject.toml +├── README.md +├── skills/ +└── tools/ +``` + + +إذا احتجت إلى البنية القديمة التي تحتوي على `crew.py` و `config/agents.yaml` و `config/tasks.yaml`، استخدم `crewai create crew research_crew --classic`. + + +## الخطوة 2: تعريف الـ Agents + +عدّل ملف `agents/researcher.jsonc` الذي أنشأه القالب، ثم أضف `agents/analyst.jsonc`. يجب أن تطابق أسماء الملفات الأسماء المشار إليها في `crew.jsonc`. + +```jsonc agents/researcher.jsonc +{ + "role": "Senior Research Specialist for {topic}", + "goal": "Find comprehensive and accurate information about {topic}, with a focus on recent developments and key insights.", + "backstory": "You are an experienced research specialist who organizes complex information into clear, useful notes.", + // استبدله بالنموذج الذي تستخدمه، مثل "openai/gpt-4o". + "llm": "provider/model-id", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +```jsonc agents/analyst.jsonc +{ + "role": "Report Analyst for {topic}", + "goal": "Turn research findings into a clear, well-structured report.", + "backstory": "You are a careful analyst with strong technical writing skills and a talent for extracting useful insights.", + // استبدله بالنموذج الذي تستخدمه، مثل "openai/gpt-4o". + "llm": "provider/model-id", + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +استبدل `provider/model-id` بالنموذج الذي تستخدمه، مثل `openai/gpt-4o` أو `anthropic/claude-sonnet-4-6` أو `gemini/gemini-2.0-flash-001`. + +## الخطوة 3: تعريف المهام وإعدادات الـ Crew + +استبدل `crew.jsonc` بما يلي: + +```jsonc crew.jsonc +{ + "name": "Research Crew", + "agents": ["researcher", "analyst"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research on {topic}. Focus on key concepts, recent developments, major challenges, notable applications, and future outlook.", + "expected_output": "A comprehensive research document with organized sections, specific facts, and useful examples about {topic}.", + "agent": "researcher" + }, + { + "name": "analysis_task", + "description": "Analyze the research findings and create a polished report on {topic}. Include an executive summary, key insights, trend analysis, and recommendations.", + "expected_output": "A professional markdown report with clear headings, a concise summary, main findings, and recommendations.", + "agent": "analyst", + "context": ["research_task"], + "output_file": "output/report.md", + "markdown": true + } + ], + "process": "sequential", + "verbose": true, + "memory": true, + "inputs": { + "topic": "Artificial Intelligence in Healthcare" + } +} +``` + +يشير `context` إلى أسماء مهام سابقة، لذلك يحصل analyst على مخرجات مهمة البحث. يوفر `inputs` قيمة افتراضية لـ `{topic}`. إذا حذفت القيمة الافتراضية، سيطلبها `crewai run`. + +## الخطوة 4: متغيرات البيئة + +عدّل `.env`: + +```sh +SERPER_API_KEY=your_serper_api_key +# أضف مفتاح مزود النموذج أيضًا. +``` + +## الخطوة 5: التثبيت والتشغيل + +```bash +crewai install +crewai run +``` + +بعد انتهاء التشغيل، افتح `output/report.md`. + + +شغّل مشاريع JSON crew من مصادر تثق بها فقط. أدوات `custom:` ومراجع `{"python": "module.attribute"}` تنفذ Python محليًا عند تحميل الـ crew. + + + +أصبحت لديك crew تعمل بأسلوب JSON-first تبحث في موضوع وتكتب تقريرًا. + diff --git a/docs/v1.15.13/ar/guides/flows/conversational-flows.mdx b/docs/v1.15.13/ar/guides/flows/conversational-flows.mdx new file mode 100644 index 0000000000..371de79bee --- /dev/null +++ b/docs/v1.15.13/ar/guides/flows/conversational-flows.mdx @@ -0,0 +1,473 @@ +--- +title: تدفقات المحادثة +description: أنشئ تطبيقات دردشة متعددة الجولات مع kickoff لكل جولة وسجل الرسائل وتوجيه النية والتتبع وجسور WebSocket. +icon: comments +mode: "wide" +--- + +## نظرة عامة + +تعامل التطبيقات المحادثية مع كل سطر من المستخدم كـ **تشغيل flow جديد** بنفس **معرّف الجلسة**. توفر CrewAI مساعدات لسجل الرسائل وتصنيف النية الاختياري وتأجيل التتبع وجسور الواجهة، إضافة إلى REPL محلي `flow.chat()` للتدفقات المحادثية. + +| المفهوم | التنفيذ | +|---------|---------| +| معرّف الجلسة | `handle_turn(..., session_id=...)` → `kickoff(inputs={"id": ...})` → `state.id` | +| سطر المستخدم | `handle_turn(message)` يضيف الرسالة إلى `state.messages` قبل تشغيل الرسم | +| اكتمال الجولة | `FlowFinished` لهذا **التشغيل** فقط؛ تستمر المحادثة في `handle_turn` التالي | +| تتبع الجلسة | `ConversationConfig(defer_trace_finalization=True)` + `finalize_session_traces()` | + +## واجهات الجولات + +استخدم **`flow.handle_turn(message, session_id=...)`** لكل رسالة مستخدم من REST أو WebSocket أو الاختبارات أو الواجهات المخصصة. استخدم **`flow.chat()`** عندما تريد حلقة دردشة محلية في الطرفية لـ `Flow` محادثي. + +لا يقبل `Flow.kickoff()` الوسيطين `user_message=` أو `session_id=`. في التدفقات المحادثية، يخزن `handle_turn()` الرسالة المعلقة ويستدعي داخلياً `kickoff(inputs={"id": session_id})`. + +| API | الاستخدام | +|-----|-----------| +| `handle_turn(message, session_id=...)` | غلاف مريح لجولة واحدة في `Flow` محادثي | +| `chat()` | REPL محلي في الطرفية لـ `Flow` محادثي | +| `kickoff(inputs={...})` | تشغيل متقدم للـ flow بدون معالجة جولة محادثية | +| `ask()` | مطالبة حاجزة **داخل** خطوة واحدة | +| `@human_feedback` | الموافقة/الرفض على **مخرجات خطوة** — وليس السطر التالي | +| `ChatSession.handle_turn(...)` | طبقة نقل فوق `handle_turn` | + +## بداية سريعة + +```python +from uuid import uuid4 + +from crewai import Flow +from crewai.flow import listen +from crewai.experimental.conversational import ( + ConversationConfig, + ConversationState, +) + + +@ConversationConfig(defer_trace_finalization=True) +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context): + message = (self.state.current_user_message or "").lower() + if "طلب" in message or "order" in message: + return "order" + if "وداع" in message or "goodbye" in message: + return "goodbye" + return "help" + + @listen("order") + def handle_order(self): + reply = "طلبك في الطريق." + self.append_assistant_message(reply) + return reply + + @listen("help") + def handle_help(self): + reply = "كيف يمكنني المساعدة؟" + self.append_assistant_message(reply) + return reply + + @listen("goodbye") + def handle_goodbye(self): + reply = "وداعاً!" + self.append_assistant_message(reply) + return reply + + +session_id = str(uuid4()) +flow = SupportFlow() + +try: + flow.handle_turn("أين طلبي؟", session_id=session_id) + flow.handle_turn("وماذا عن الإرجاع؟", session_id=session_id) +finally: + flow.finalize_session_traces() +``` + +## دورة حياة الجولة + +كل `handle_turn` يشغّل: + +1. **`_configure_conversational_kickoff`** — دمج `session_id` / `user_message` في `inputs` وتطبيق `ConversationalConfig`. +2. **استعادة الحالة** — عند وجود `inputs["id"]` و`@persist`. +3. **`FlowStarted`** — في أول جولة للجلسة المؤجلة فقط. +4. **`prepare_conversational_turn`** — إضافة رسالة المستخدم و`last_user_message` وتصنيف اختياري. +5. **تنفيذ الرسم** — `@start` → `@router` → معالجات `@listen`. +6. **نهاية التشغيل** — يُتخطى `flow_finished` والتتبع لكل جولة عند التأجيل؛ `Agent.kickoff()` / crews لا تغلق دفعة الأب. + +استدعِ **`append_assistant_message(reply)`** في المعالجات. سطر المستخدم محفوظ عبر `handle_turn` — لا تُضفه مرة أخرى. + +## `ConversationalConfig` (افتراضيات على مستوى الصنف) + +عيّن على صنف `Flow` كـ `conversational_config: ClassVar[ConversationalConfig | None]`. + +| الحقل | الافتراضي | الغرض | +|-------|-----------|--------| +| `default_intents` | `None` | تسميات outcome للتصنيف التلقائي قبل kickoff | +| `intent_llm` | `None` | نموذج التصنيف (مطلوب عند وجود intents) | +| `interactive_prompt` | `"You: "` | مطالبة `kickoff(interactive=True)` | +| `interactive_timeout` | `None` | مهلة لكل سطر في الوضع التفاعلي | +| `exit_commands` | `exit`, `quit` | كلمات إنهاء الوضع التفاعلي | +| `defer_trace_finalization` | `True` | إبقاء دفعة trace واحدة مفتوحة بين الجولات | + +يمكن التجاوز لكل kickoff عبر `intents=` و`intent_llm=`. + +## `ChatState` (شكل الحالة الموصى به للحفظ) + +```python +from crewai.flow import ChatState + + +class MyChatState(ChatState): + # موروث: id, messages, last_user_message, last_intent, session_ready + research_turn_count: int = 0 + custom_flag: bool = False +``` + +| الحقل | الدور | +|-------|------| +| `id` | UUID الجلسة (مثل `session_id` / `inputs["id"]`) | +| `messages` | قائمة `{role, content}` لسجل LLM | +| `last_user_message` | آخر سطر مستخدم في هذه الجولة | +| `last_intent` | تسمية المسار بعد التصنيف (إن وُجد) | +| `session_ready` | علم bootstrap لمرة واحدة | + +`ConversationalInputs` هو `TypedDict` لـ `kickoff(inputs={...})`: `id`, `user_message`, `last_intent`. + +## API المحادثة على `Flow` + +### معاملات `kickoff` / `kickoff_async` + +| المعامل | الغرض | +|---------|--------| +| `user_message` | نص هذه الجولة (أو `{"role": "user", "content": "..."}`) | +| `session_id` | UUID المحادثة → `inputs["id"]` / `state.id` | +| `intents` | تسميات outcome لـ `classify_intent` قبل kickoff | +| `intent_llm` | LLM للتصنيف (مطلوب مع `intents`) | +| `interactive` | حلقة CLI عبر `ask()` (للعروض المحلية فقط) | +| `interactive_prompt` | مطالبة الوضع التفاعلي | +| `interactive_timeout` | مهلة `ask()` لكل سطر | +| `exit_commands` | كلمات إنهاء الوضع التفاعلي | +| `inputs` | حقول حالة إضافية | +| `restore_from_state_id` | استنساخ من flow محفوظ آخر | + +### سمات المثيل + +| السمة | الغرض | +|-------|--------| +| `conversational_config` | افتراضيات `ConversationalConfig` على مستوى الصنف | +| `defer_trace_finalization` | علم المثيل؛ يُضبط تلقائياً من config عند kickoff | +| `suppress_flow_events` | يخفي لوحات console؛ **التتبع يُسجّل** | +| `stream` | بث؛ مع `ChatSession.handle_turn(..., stream=True)` | + +### طرق وخصائص + +| الاسم | الوصف | +|------|--------| +| `append_message(role, content, **extra)` | إضافة إلى `state.messages` | +| `conversation_messages` | سجل للقراءة فقط لاستدعاءات LLM | +| `classify_intent(text, outcomes, *, llm, context=None)` | تعيين outcome | +| `receive_user_message(text, *, outcomes=None, llm=None)` | إضافة رسالة مستخدم؛ `last_intent` اختياري | +| `finalize_session_traces()` | إصدار `flow_finished` المؤجل وإنهاء دفعة trace | +| `_should_defer_trace_finalization()` | هل يُؤجل إنهاء trace لكل جولة | +| `input_history` | سجل تدقيق مطالبات وردود `ask()` | + +### مساعدات الوحدة (`crewai.flow.conversation`) + +| الدالة | الوصف | +|--------|--------| +| `normalize_kickoff_inputs(...)` | دمج kwargs المحادثة في `inputs` | +| `get_conversation_messages(flow)` | قراءة الرسائل من الحالة أو المخزن | +| `append_message(flow, ...)` | مثل طريقة المثيل | +| `prepare_conversational_turn(flow, ...)` | تهيئة الجولة (عادةً kickoff يستدعيها) | +| `receive_user_message(flow, ...)` | مثل طريقة المثيل | +| `set_state_field(flow, name, value)` | تعيين حقل dict أو Pydantic | +| `get_conversational_config(flow)` | قراءة `conversational_config` | +| `input_history_to_messages(entries)` | تحويل `input_history` لصيغة رسائل LLM | + +## أنماط توجيه النية + +### أ. تصنيف مسبق عبر `ConversationalConfig` (الأبسط) + +عيّن `default_intents` و`intent_llm`. كل kickoff يصنّف قبل `@router`؛ اقرأ `self.state.last_intent` في `route()`. + +### ب. تصنيف داخل `@router` (مطالبات أغنى) + +عيّن `default_intents=None` ليضيف kickoff الرسالة فقط. في `route()` استدعِ `classify_intent`: + +```python +@router(bootstrap) +def route(self): + intent = self.classify_intent( + self._routing_prompt(self.state.last_user_message), + ("GREETING", "ORDER", "RESEARCH", "GOODBYE"), + llm=self.conversational_config.intent_llm or "gpt-4o-mini", + ) + self.state.last_intent = intent + return intent +``` + +للبحث على الويب أو أدوات متعددة الخطوات استخدم **`@listen("RESEARCH")`** مع `Agent.kickoff()` وأدوات — وليس `LLM.call()` فقط. + +## عندما ينتهي الـ flow ويستمر المستخدم + +`FlowFinished` يعني أن **تنفيذ الرسم هذا** اكتمل. تستمر المحادثة بـ `kickoff` آخر ونفس `session_id`. `@persist` يستعيد `messages` والأعلام والسياق. + +**نمط الحفظ:** يُفضّل `@persist` على **خطوة نهائية واحدة** (مثل `finalize`) وليس على صنف `Flow` بالكامل. الحفظ على مستوى الصنف بعد كل method قد يفقد تحديثات المعالجات في نفس الجولة. + +لا تستخدم `@human_feedback` لأسطر المتابعة في الدردشة إلا عند الحاجة لموافقة بشرية على مخرجات خطوة محددة. + +## `Flow` المحادثاتي (تجريبي) + + + **ميزة تجريبية.** سطح `Flow` المحادثاتي (`conversational = True`، + `handle_turn`، `ConversationConfig`، `RouterConfig`، + `ConversationState`، الرسم البياني المدمج والمساعدات) يقع تحت + `crewai.experimental` وقد يتغير شكله قبل التخرج. ثبّت إصدار CrewAI إذا + كنت تعتمد على سلوك محدد، وراقب changelog للتحديثات الكاسرة. الملاحظات + والمشاكل مرحب بها. + + +فعّل الرسم المحادثاتي بتعيين `conversational = True` على صنف فرعي من `Flow`. عندئذٍ يُظهر `Flow` الأساسي رسم `@start` / `@router` / `converse_turn` / `end_conversation` مدمجاً، ويدير `state.messages`، ويُشغّل LLM التوجيه، ويبقي دفعة trace مفتوحة عبر الجولات. أنت تكتب **المسارات المخصصة** فقط؛ والإطار يتولى الباقي. + +استخدمه عندما تريد دردشة متعددة الجولات مع موجّه قائم على LLM ومعالجات لكل مسار دون توصيل دورة الحياة يدوياً. استخدم `Flow[ChatState]` (النمط الأدنى مستوى في الأعلى) عندما تحتاج تحكماً كاملاً. + +### مثال سريع + +```python +from crewai import LLM, Flow +from crewai.flow import listen +from crewai.experimental.conversational import ( + ConversationConfig, + ConversationState, + RouterConfig, +) + + +ROUTER_LLM = LLM(model="gpt-4o-mini") + + +@ConversationConfig( + system_prompt="A multi-agent assistant for ordinary chat and tool-backed tasks.", + llm=ROUTER_LLM, + router=RouterConfig(), # المسارات + الأوصاف تُكتشف تلقائياً من معالجات @listen +) +class SupportFlow(Flow[ConversationState]): + conversational = True + + @listen("INTERNET_SEARCH") + def handle_internet_search(self) -> str: + """Fresh web research, current news, real-time lookups.""" + ... + self.append_assistant_message(reply) + return reply + + @listen("CREWAI_DOCS") + def handle_crewai_docs(self) -> str: + """Look up the CrewAI documentation for framework/API questions.""" + ... + self.append_assistant_message(reply) + return reply + + +flow = SupportFlow() +try: + flow.handle_turn("ماذا يمكنك أن تفعل؟") # يوجَّه إلى converse (مدمج) + flow.handle_turn("ابحث في الويب عن أخبار الذكاء الاصطناعي.") # يوجَّه إلى INTERNET_SEARCH + flow.handle_turn("لخص النتيجة الأولى.") # يعود إلى converse +finally: + flow.finalize_session_traces() +``` + +للدردشة المحلية في الطرفية، استخدم `chat()`: + +```python +def kickoff() -> None: + SupportFlow().chat() +``` + +يلف `chat()` استدعاءات `handle_turn()` داخل REPL، ويخرج عند `exit` / `quit`، ويتجاهل الأسطر الفارغة افتراضياً، ويستدعي `finalize_session_traces()` عند انتهاء الجلسة. + +### `ConversationConfig` + +مزخرف صنف يُلحق افتراضيات الدردشة على مستوى الصنف. + +| الحقل | الافتراضي | الغرض | +|-------|-----------|-------| +| `system_prompt` | `slices.conversational_system_prompt` من i18n | رسالة system يستخدمها `converse_turn` المدمج. مرر `""` للتعطيل التام. | +| `llm` | `None` | LLM المحادثة (يستخدمه `converse_turn` وكاحتياطي للموجّه). | +| `router` | `None` | `RouterConfig` للتوجيه عبر LLM. بدونه، يسقط الـ flow دائماً إلى `converse`. | +| `answer_from_history_prompt` | افتراضي الإطار | رسالة system للمسار الاختياري `answer_from_history`. | +| `answer_from_history_llm` | `None` | يُفعّل الاختصار `answer_from_history` عند تعيينه. | +| `intent_llm` | `None` | LLM لمسار التصنيف المسبق القديم `intents=`/`default_intents`. | +| `default_intents` | `None` | تسميات النتائج للتصنيف المسبق القديم. | +| `visible_agent_outputs` | `None` | `"all"` أو قائمة بأسماء الـ agents الذين تُرفع مخرجاتهم من `append_agent_result()` إلى رسائل عامة. | +| `defer_trace_finalization` | `True` | يبقي دفعة trace واحدة مفتوحة عبر استدعاءات `handle_turn()`. | + +### `RouterConfig` وفهرس المسارات المُولَّد تلقائياً + +```python +RouterConfig( + prompt="تأطير اختياري للنطاق (سياسة، صوت، شخصية).", + response_format=MyRoute, # اختياري؛ يُولَّد تلقائياً عند الإغفال + llm=ROUTER_LLM, # يسقط إلى ConversationConfig.llm + routes=["INTERNET_SEARCH", "CREWAI_DOCS"], # اختياري؛ يُستنتج من المستمعين + route_descriptions={ + "INTERNET_SEARCH": "تجاوز الـ docstring لهذا المسار فقط.", + }, + default_intent="converse", # يُستخدم عند فشل LLM أو غيابه + fallback_intent="converse", # يُستخدم عندما يعيد LLM مساراً غير صالح + intent_field="intent", +) +``` + +تُبنى رسالة الموجّه إلى LLM تلقائياً. لكل مسار يختار الإطار وصفاً بهذا الترتيب من الأولوية: + +1. `RouterConfig.route_descriptions[label]` — تجاوز صريح. +2. `Flow.builtin_route_descriptions[label]` — نص جاهز من الإطار لـ `converse` و`end` و`answer_from_history` (مصاغ لـ LLM التوجيه). +3. أول سطر غير فارغ من docstring معالج `@listen(label)`. +4. فارغ (المسار يظهر في الفهرس بلا وصف). + +عملياً، **إضافة مسار جديد = `@listen("X")` + docstring من سطر واحد**: + +```python +@listen("INTERNET_SEARCH") +def handle_internet_search(self) -> str: + """Fresh web research, current news, real-time lookups.""" + ... +``` + +…وسيرى LLM التوجيه: + +``` +Routes: +- CREWAI_DOCS: Look up the CrewAI documentation for framework/API questions. +- INTERNET_SEARCH: Fresh web research, current news, real-time lookups. +- converse: Ordinary chat, follow-ups, summaries, clarifications… +- end: User signals the conversation is finished (goodbye, exit, done). +``` + +`RouterConfig.prompt` مخصص لـ **تأطير النطاق** (شخصية المساعد، قواعد العمل، النبرة). فهرس المسارات يُبنى تلقائياً — لا تُدرج المسارات في `prompt`؛ سيختل التزامن لحظة إضافة معالج جديد. + +### المسارات المدمجة + +| المسار | المعالج | الغرض | +|--------|---------|-------| +| `converse` | `converse_turn` | معالج الدردشة الافتراضي. يستدعي `ConversationConfig.llm` بـ system prompt + التاريخ القانوني للرسائل. | +| `end` | `end_conversation` | يضبط `state.ended = True` ويُصدر رد إنهاء. | +| `answer_from_history` | `answer_from_history_turn` | اختياري. يُوجَّه إليه عندما يكون `ConversationConfig.answer_from_history_llm` مُعيَّناً ويمكن الإجابة على الرسالة من التاريخ فقط. | + +يمكنك تجاوز أي من هذه بتعريف معالج بنفس الاسم في الصنف الفرعي. + +### دلالات `handle_turn()` + +`flow.handle_turn(message)` يُشغّل جولة واحدة: + +1. يعيد ضبط تعقّب التنفيذ لكل جولة (`_completed_methods`, `_method_outputs`) ليُعاد تشغيل الرسم — بدون ذلك، استدعاءات `kickoff` المتكررة على نفس النسخة ستُحدث دائرة قصر من الجولة الثانية لأن `Flow.kickoff_async` يعتبر `inputs={"id": ...}` استعادة من نقطة تفتيش. +2. يُلحق رسالة المستخدم بـ `state.messages` ويضبط `current_user_message` / `last_user_message`. يُحافَظ على `last_intent` **من الجولة السابقة** كي يستخدمها LLM التوجيه كإشارة. +3. يُشغّل `conversation_start` → `route_conversation` → معالج `@listen` المختار. +4. يخزّن الموجّه قراره في `state.last_intent` (يكون مرئياً لسياق التوجيه في الجولة التالية). +5. إذا أعاد معالجك سلسلة نصية ولم يستدعِ `append_assistant_message`، فإن `handle_turn` يُلحقها نيابةً عنك. + +استدعِ `handle_turn()` لرسائل الدردشة. استدعاء `kickoff(inputs={"id": ...})` مباشرةً يشغل الرسم بدون غلاف الجولة المحادثية. + +### `chat()` للـ REPL المحلي + +`flow.chat()` هو غلاف الطرفية الجاهز فوق `handle_turn()`: + +```python +flow = SupportFlow() +flow.chat() +``` + +يتولى الحلقة المحلية الشائعة: + +1. يطلب رسالة من المستخدم. +2. يتوقف عند `exit` / `quit` أو `EOFError` أو `KeyboardInterrupt`. +3. يستدعي `handle_turn(message, session_id=...)`. +4. يطبع نتيجة المساعد. +5. ينهي traces الجلسة المؤجلة داخل كتلة `finally`. + +خصص سلوك الطرفية عبر I/O قابل للحقن: + +```python +flow.chat( + session_id="demo-session", + prompt="You: ", + assistant_prefix="Assistant: ", + exit_commands=("exit", "quit", "bye"), +) +``` + +لتطبيقات الويب والـ workers الخلفية والاختبارات ووسائط النقل المخصصة، استمر في استخدام `handle_turn()` مباشرةً. + +### سلوك موجّه مخصص + +لتشغيل آثار جانبية (إعداد ناقل أحداث، قياس عن بُعد) في كل قرار توجيه، تجاوز `route_turn`: + +```python +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context: dict[str, Any]) -> str | None: + self.event_bus = MyBus(self) + return super().route_turn(context) +``` + +لتجاوز موجّه LLM واختيار مسار برمجياً، أعد سلسلة نصية من `route_turn`؛ إعادة `None` تسقط إلى `_route_with_config(...)`. + +### `append_assistant_message` و`append_agent_result` + +داخل معالج `@listen(label)`، اختر: + +- `self.append_assistant_message(text)` — يضيف جولة مساعد مرئية للمستخدم إلى `state.messages`. سيراها `converse_turn` في الجولة التالية. +- `self.append_agent_result(agent_name, result, visibility="private")` — يسجّل حدثاً منظماً في `state.events` وموضوعاً في `state.agent_threads[agent_name]`. الرؤية العامة تستدعي `append_assistant_message` أيضاً. استخدم النتائج الخاصة للعمل الجانبي الذي يجب ألا يلوث التاريخ القانوني. + +يمكن لـ `ConversationConfig.visible_agent_outputs` رفع النتائج الخاصة لـ agents محددين إلى عامة عالمياً (`"all"` أو قائمة بالأسماء). + +## التتبع عبر الجولات + +مع `defer_trace_finalization=True` (افتراضي في `ConversationalConfig`): + +- **دفعة trace واحدة** لجلسة الدردشة. +- **`flow_started`** في الجولة الأولى فقط؛ **`flow_finished`** مرة في `finalize_session_traces()`. +- **`kickoff` لكل جولة** لا يطبع "Trace batch finalized". +- **العمل المتداخل** (`Agent.kickoff()`, crews, Exa) يُلحق بدفعة **الأب**؛ flow داخلي من `AgentExecutor` لا يغلق دفعة الجلسة مبكراً. + +```python +flow.chat(session_id=session_id) +``` + +`flow.chat()` يستدعي `finalize_session_traces()` نيابةً عنك. عندما تملك الحلقة عبر `handle_turn()` أو `kickoff(...)`، استدعِ `finalize_session_traces()` عند انتهاء الجلسة. + +`suppress_flow_events=True` يخفي لوحات Rich فقط؛ أحداث trace والـ methods تُصدر. + +### دورة حياة trace لـ `Flow` المحادثاتي + +يستخدم [`Flow` المحادثاتي](#flow-المحادثاتي-تجريبي) التجريبي نفس دورة حياة tracing: `defer_trace_finalization` افتراضياً `True`، فيبقي كل `handle_turn()` أثر الجلسة مفتوحاً. أنهِ دوماً عند نهاية الجلسة — لُف حلقتك بـ `try/finally` واستدعِ `flow.finalize_session_traces()` عند الخروج. بدون ذلك، تبقى الدفعة مفتوحة وقد لا تُصدَّر آخر محادثة أبداً. + +## البث + +اضبط `stream = True` على صنف `Flow`. عندئذٍ يُصدر `kickoff(...)` أحداث `assistant_delta` (وما يرتبط بها) عبر ناقل الأحداث القياسي. + +## الاستيراد + +```python +from crewai.flow import ( + ChatState, + ConversationalConfig, + ConversationalInputs, + Flow, + listen, + persist, + router, + start, +) +``` + +## مراجع + +- [إتقان إدارة حالة Flow](/ar/guides/flows/mastering-flow-state) +- [أنشئ أول Flow](/ar/guides/flows/first-flow) +- Demo: `lib/crewai/runner_conversational_flow_simple.py` — REPL بسيط مع `RESEARCH` ووكيل Exa diff --git a/docs/v1.15.13/ar/guides/flows/first-flow.mdx b/docs/v1.15.13/ar/guides/flows/first-flow.mdx new file mode 100644 index 0000000000..322e71c2a0 --- /dev/null +++ b/docs/v1.15.13/ar/guides/flows/first-flow.mdx @@ -0,0 +1,222 @@ +--- +title: ابنِ أول Flow لك +description: تعلم كيفية إنشاء سير عمل منظمة قائمة على الأحداث مع تحكم دقيق في التنفيذ. +icon: diagram-project +mode: "wide" +--- + +## التحكم في سير عمل AI مع Flows + +تمثل CrewAI Flows المستوى التالي في تنسيق AI - الجمع بين القوة التعاونية لفرق Agents AI مع دقة ومرونة البرمجة الإجرائية. بينما تتفوق Crews في تعاون الـ Agents، تمنحك Flows تحكمًا دقيقًا في كيفية ووقت تفاعل المكونات المختلفة لنظام AI. + +في هذا الدليل، سنمشي عبر إنشاء CrewAI Flow قوي ينشئ دليلًا تعليميًا شاملاً حول أي موضوع. + +### ما يجعل Flows قوية + +تمكّنك Flows من: + +1. **الجمع بين أنماط تفاعل AI مختلفة** - استخدام Crews للمهام التعاونية المعقدة واستدعاءات LLM المباشرة للعمليات الأبسط والكود العادي للمنطق الإجرائي +2. **بناء أنظمة قائمة على الأحداث** - تحديد كيفية استجابة المكونات لأحداث وتغييرات بيانات محددة +3. **الحفاظ على الحالة عبر المكونات** - مشاركة وتحويل البيانات بين أجزاء مختلفة من تطبيقك +4. **التكامل مع الأنظمة الخارجية** - ربط سير عمل AI بسلاسة مع قواعد البيانات وواجهات API وواجهات المستخدم +5. **إنشاء مسارات تنفيذ معقدة** - تصميم فروع شرطية ومعالجة متوازية وسير عمل ديناميكية + +### المتطلبات المسبقة + +قبل البدء، تأكد من: + +1. تثبيت CrewAI باتباع [دليل التثبيت](/ar/installation) +2. إعداد مفتاح API لنموذج LLM في بيئتك، باتباع [دليل إعداد LLM](/ar/concepts/llms#setting-up-your-llm) +3. فهم أساسي لـ Python + +## الخطوة 1: إنشاء مشروع CrewAI Flow جديد + +```bash +crewai create flow guide_creator_flow +cd guide_creator_flow +``` + + + نظرة عامة على إطار عمل CrewAI + + +## الخطوة 2: فهم هيكل المشروع + +يستخدم الـ crew المبدئي المضمّن في مشروع Flow بنية Python/YAML الكلاسيكية. لاستخدام crew بنمط JSON-first داخل Flow، أنشئ `crew.jsonc` و `agents/*.jsonc` داخل مجلد الـ crew وحمّله عبر `crewai.project.load_crew` كما في [Flows](/ar/concepts/flows#building-your-crews). + +``` +guide_creator_flow/ +├── .gitignore +├── pyproject.toml +├── README.md +├── .env +└── src/ + └── guide_creator_flow/ + ├── __init__.py + ├── main.py + ├── crews/ + │ └── poem_crew/ + │ ├── config/ + │ │ ├── agents.yaml + │ │ └── tasks.yaml + │ └── poem_crew.py + └── tools/ + └── custom_tool.py +``` + +يوفر هذا الهيكل فصلاً واضحًا بين مكونات Flow المختلفة. سنعدّل هذا الهيكل لإنشاء Flow منشئ الدليل. + +## الخطوة 3: إضافة Crew كتابة المحتوى + +```bash +crewai flow add-crew content-crew +``` + +## الخطوة 4: تهيئة Crew كتابة المحتوى + +سنهيئ crew كتابة المحتوى باستخدام JSONC. سنعرّف Agent للكتابة وAgent للمراجعة، ثم نحمّل `crew.jsonc` من خطوة Flow. + +1. أنشئ `src/guide_creator_flow/crews/content_crew/agents/content_writer.jsonc`: + +```jsonc +{ + "role": "Educational Content Writer", + "goal": "Create engaging, informative content that thoroughly explains the assigned topic and provides valuable insights to the reader.", + "backstory": "You are a talented educational writer who explains complex concepts in accessible language and organizes information clearly.", + "llm": "provider/model-id", + "settings": { + "verbose": true + } +} +``` + +2. أنشئ `src/guide_creator_flow/crews/content_crew/agents/content_reviewer.jsonc`: + +```jsonc +{ + "role": "Educational Content Reviewer and Editor", + "goal": "Ensure content is accurate, comprehensive, well-structured, and consistent with previously written sections.", + "backstory": "You are a meticulous editor with an eye for detail, clarity, and coherence.", + "llm": "provider/model-id", + "settings": { + "verbose": true + } +} +``` + +استبدل `provider/model-id` بالنموذج الذي تستخدمه، مثل `openai/gpt-4o` أو `gemini/gemini-2.0-flash-001` أو `anthropic/claude-sonnet-4-6`. + +3. أنشئ `src/guide_creator_flow/crews/content_crew/crew.jsonc`: + +```jsonc +{ + "name": "Content Crew", + "agents": ["content_writer", "content_reviewer"], + "tasks": [ + { + "name": "write_section_task", + "description": "Write a comprehensive section on the topic: \"{section_title}\".\n\nSection description: {section_description}\nTarget audience: {audience_level} level learners\n\nYour content should begin with a brief introduction, explain key concepts clearly with examples, include practical applications where appropriate, end with a summary, and be approximately 500-800 words.\n\nPreviously written sections:\n{previous_sections}", + "expected_output": "A well-structured, comprehensive section in Markdown format that thoroughly explains the topic and is appropriate for the target audience.", + "agent": "content_writer", + "markdown": true + }, + { + "name": "review_section_task", + "description": "Review and improve this section on \"{section_title}\":\n\n{draft_content}\n\nTarget audience: {audience_level} level learners\nPreviously written sections:\n{previous_sections}\n\nFix errors, improve clarity, verify consistency, enhance structure, and add missing key information.", + "expected_output": "An improved, polished version of the section that maintains the original structure but enhances clarity, accuracy, and consistency.", + "agent": "content_reviewer", + "context": ["write_section_task"], + "markdown": true + } + ], + "process": "sequential", + "verbose": true +} +``` + +4. استبدل `src/guide_creator_flow/crews/content_crew/content_crew.py` بمحمل صغير: + +```python +from pathlib import Path + +from crewai.project import load_crew + + +def kickoff_content_crew(inputs: dict): + crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc")) + return crew.kickoff(inputs={**default_inputs, **inputs}) +``` + +## الخطوة 5: إنشاء Flow + +الآن الجزء المثير - إنشاء Flow الذي سينسّق عملية إنشاء الدليل بالكامل. راجع الملف الإنجليزي الأصلي للكود الكامل لـ `main.py` حيث أن الكود يبقى كما هو. + +## الخطوة 6: إعداد متغيرات البيئة + +أنشئ ملف `.env` في جذر مشروعك بمفاتيح API. راجع [دليل إعداد LLM](/ar/concepts/llms#setting-up-your-llm) لتفاصيل تهيئة المزود. + +```sh .env +OPENAI_API_KEY=your_openai_api_key +# or +GEMINI_API_KEY=your_gemini_api_key +# or +ANTHROPIC_API_KEY=your_anthropic_api_key +``` + +## الخطوة 7: تثبيت التبعيات + +```bash +crewai install +``` + +## الخطوة 8: تشغيل Flow + +```bash +crewai run +``` + +عند تشغيل هذا الأمر، ستشاهد Flow يعمل: +1. سيطلب منك موضوعًا ومستوى الجمهور +2. سينشئ مخططًا منظمًا لدليلك +3. سيعالج كل قسم مع تعاون الكاتب والمراجع +4. أخيرًا سيجمع كل شيء في دليل شامل + +## الخطوة 9: تصوير Flow + +```bash +crewai flow plot +``` + +سينشئ ملف HTML يوضح هيكل Flow بما في ذلك العلاقات بين الخطوات المختلفة. + +## الخطوة 10: مراجعة المخرجات + +بمجرد اكتمال Flow، ستجد ملفين في مجلد `output`: + +1. `guide_outline.json`: يحتوي على المخطط المنظم للدليل +2. `complete_guide.md`: الدليل الشامل بجميع الأقسام + +## الميزات الرئيسية الموضّحة + +يوضح Flow منشئ الدليل عدة ميزات قوية لـ CrewAI: + +1. **تفاعل المستخدم**: يجمع Flow مدخلات مباشرة من المستخدم +2. **استدعاءات LLM المباشرة**: يستخدم فئة LLM لتفاعلات AI فعّالة وأحادية الغرض +3. **بيانات منظمة مع Pydantic**: يستخدم نماذج Pydantic لضمان سلامة الأنواع +4. **معالجة تسلسلية مع سياق**: يكتب الأقسام بالترتيب ويوفر الأقسام السابقة كسياق +5. **Crews متعددة الـ Agents**: يستفيد من Agents متخصصة (كاتب ومراجع) لإنشاء المحتوى +6. **إدارة الحالة**: يحافظ على الحالة عبر خطوات العملية المختلفة +7. **بنية قائمة على الأحداث**: يستخدم مزخرف `@listen` للاستجابة للأحداث + +## الخطوات التالية + +1. جرّب هياكل Flow أكثر تعقيدًا وأنماطًا +2. جرّب استخدام `@router()` لإنشاء فروع شرطية +3. استكشف دوال `and_` و`or_` لتنفيذ متوازٍ أكثر تعقيدًا +4. اربط Flow بواجهات API خارجية وقواعد بيانات وواجهات مستخدم +5. ادمج عدة Crews متخصصة في Flow واحد +6. أنشئ تطبيقات دردشة متعددة الجولات مع [تدفقات المحادثة](/ar/guides/flows/conversational-flows) (`kickoff` لكل رسالة، `ChatSession`، تأجيل التتبع) + + +تهانينا! لقد بنيت بنجاح أول CrewAI Flow يجمع بين الكود العادي واستدعاءات LLM المباشرة ومعالجة Crew لإنشاء دليل شامل. هذه المهارات الأساسية تمكّنك من إنشاء تطبيقات AI متطورة بشكل متزايد. + diff --git a/docs/v1.15.13/ar/guides/flows/inputs-id-deprecation.mdx b/docs/v1.15.13/ar/guides/flows/inputs-id-deprecation.mdx new file mode 100644 index 0000000000..3e29b2baf0 --- /dev/null +++ b/docs/v1.15.13/ar/guides/flows/inputs-id-deprecation.mdx @@ -0,0 +1,102 @@ +--- +title: "الانتقال من inputs.id إلى restore_from_state_id" +description: "نقل تدفقات @persist من ترطيب inputs.id المهجور إلى حقل restore_from_state_id المدعوم" +icon: "arrow-right-arrow-left" +--- + + + تمرير `id` داخل `inputs` لترطيب تدفق `@persist` هو **مهجور** ومقرر إزالته في إصدار مستقبلي. البديل، `restore_from_state_id`، متاح في CrewAI **v1.14.5 وما بعده** — الخطوات أدناه تنطبق بمجرد أن تقوم بالتحديث. + + +## نظرة عامة + +الطريقة الموثقة لترطيب تدفق `@persist` من تنفيذ سابق هي تمرير UUID لذلك التنفيذ كـ `inputs.id`. الآن، تكشف CrewAI عن حقل مخصص، `restore_from_state_id`، الذي يقوم بنفس الترطيب دون تحميل حمولة `inputs` — ودون ربط مفتاح الترطيب بهوية التنفيذ الجديد. + +## الانتقال + +إذا كنت حالياً تبدأ تدفق `@persist` باستخدام `inputs={"id": ...}`: + +```python +# مهجور +flow = CounterFlow() +flow.kickoff(inputs={"id": "abcd1234-5678-90ef-ghij-klmnopqrstuv"}) +``` + +انتقل إلى `restore_from_state_id`: + +```python +# مدعوم +flow = CounterFlow() +flow.kickoff(restore_from_state_id="abcd1234-5678-90ef-ghij-klmnopqrstuv") +``` + +تتمتع الوضعيتان بمعاني سلالة مختلفة: + +- `inputs={"id": }` (مهجور) — **استئناف**: تكتب الكتابات تحت المعرف المقدم، مما يمدد نفس تاريخ `flow_uuid`. +- `restore_from_state_id=` — **تفرع**: يترطب الحالة من اللقطة، ثم يكتب تحت `state.id` جديدة. يتم الحفاظ على تاريخ التدفق المصدر. + +لأغلب سيناريوهات الإنتاج — إعادة تشغيل تدفق تم تهيئته من حالة سابقة — فإن التفرع هو ما تريده. راجع [إتقان حالة التدفق](/ar/guides/flows/mastering-flow-state) للحصول على النموذج الذهني الكامل. + +إذا كنت تبدأ تدفقك عبر واجهة برمجة تطبيقات CrewAI AMP REST، راجع [AMP](#amp) أدناه لهجرة الحمولة المعادلة. + +## لماذا نقوم بإهمال `inputs.id` لـ `@persist` + +`inputs.id` هو حالياً الطريقة الموثقة لاستئناف تدفق `@persist` من تنفيذ سابق. المشكلة هي أن نفس UUID يقوم بوظيفتين في وقت واحد: + +1. **يحدد أي لقطة يترطب منها `@persist`** — تحميل الحالة المحفوظة تحت ذلك UUID. +2. **يصبح معرف تنفيذ التدفق الجديد** (`state.id` في SDK؛ يظهر كـ `flow_id` في بعض السياقات) — كل كتابة `@persist` من هذه البداية أيضاً تقع تحت نفس UUID. + +هذه الوظيفة المزدوجة هي السبب الجذري للمشاكل التي يصفها هذا الدليل. لأن UUID المقدم هو أيضاً معرف التنفيذ الجديد، فإن بدايتين تمرران نفس `inputs.id` ليست تنفيذين متميزين — إنهما تشتركان في معرف، وتشاركان في سجل الاستمرارية، و(على AMP) تشتركان في صف في قائمة التنفيذات. لا توجد طريقة للقول "ترطب من هذه اللقطة، ولكن سجل هذا التشغيل بشكل منفصل" دون تقسيم المسؤوليتين. + +`restore_from_state_id` هو هذا الانقسام. إنه يخبر `@persist` من أي لقطة يترطب، بينما يترك التنفيذ الجديد حراً لاستلام `state.id` جديدة. لم يعد مصدر الترطيب والتشغيل المسجل نفس UUID — وهو ما تريده معظم سيناريوهات الإنتاج فعلياً. + +## جدول إزالة + +من المقرر إزالة `inputs.id` لترطيب `@persist` في إصدار مستقبلي من CrewAI. لا يوجد قطع صارم فوري — تظل التدفقات الحالية تعمل — ولكن بمجرد أن تقوم بالتحديث إلى v1.14.5 أو ما بعده، يجب أن يستخدم الكود الجديد `restore_from_state_id`، ويجب أن تهاجر التدفقات الحالية في الفرصة المناسبة التالية. + +## AMP + +إذا كنت تنشر تدفقك إلى CrewAI AMP، فإن الهجرة تمتد إلى الحمولة التي تبدأ بها المرسلة إلى طاقمك المنشور، وتظهر الأعراض المرئية لإعادة استخدام `inputs.id` على لوحة معلومات النشر. تغطي القسمان الفرعيان أدناه كلاهما. + +### هجرة حمولة البداية + +إذا كنت حالياً تبدأ تدفقاً منشوراً عن طريق تضمين `id` في `inputs`: + +```bash +# مهجور +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + -d '{"inputs": {"id": "abcd1234-5678-90ef-ghij-klmnopqrstuv", "topic": "AI Agent Frameworks"}}' \ + https://your-crew-url.crewai.com/kickoff +``` + +نقل UUID إلى حقل `restoreFromStateId` في المستوى الأعلى: + +```bash +# مدعوم +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + -d '{ + "inputs": {"topic": "AI Agent Frameworks"}, + "restoreFromStateId": "abcd1234-5678-90ef-ghij-klmnopqrstuv" + }' \ + https://your-crew-url.crewai.com/kickoff +``` + +يجلس `restoreFromStateId` بجانب `inputs` في حمولة البداية، وليس داخلها. الآن، يحمل كائن `inputs` فقط القيم التي تستهلكها تدفقك فعلياً. + +### ماذا يحدث عند إعادة استخدام `inputs.id` + +عندما تتلقى AMP بداية لتدفق يتطابق `inputs.id` الخاص به مع تنفيذ موجود، فإنه يحل إلى السجل الموجود بدلاً من إنشاء سجل جديد. من لوحة معلومات النشر سترى: + +- **حالة التنفيذ** — حالة التشغيل الجديد تحل محل حالة التشغيل السابق. يمكن أن تعود تنفيذات مكتملة إلى `جارية`، أو يمكن أن تتحول تشغيلات `مكتملة` إلى `خطأ` إذا فشلت البداية الجديدة — في كلتا الحالتين، لم تعد لوحة المعلومات تعكس التشغيل الأصلي. +- **التتبع** — تتراكم تتبعات OTel عبر البدايات لأنها تشترك في نفس معرف التنفيذ؛ تتبعات التشغيل السابق إما تُستبدل بـ، أو تُخلط مع، تشغيل الجديد. لم يعد إعادة التشغيل خطوة بخطوة يتوافق مع تنفيذ واحد. +- **قائمة التنفيذات** — البدايات التي يجب أن تظهر كصفوف منفصلة تتقلص إلى إدخال واحد، مما يخفي التاريخ. + +تساعد الهجرة إلى `restoreFromStateId` في الحفاظ على كل بداية كتنفيذ خاص بها — مع حالتها الخاصة، وتتبعها، وصفها في القائمة — بينما لا تزال ترطب الحالة من تشغيل سابق. + + + اتصل بفريق الدعم لدينا إذا لم تكن متأكداً من أي وضع يحتاجه تدفقك أو واجهت مشاكل أثناء الهجرة. + \ No newline at end of file diff --git a/docs/v1.15.13/ar/guides/flows/mastering-flow-state.mdx b/docs/v1.15.13/ar/guides/flows/mastering-flow-state.mdx new file mode 100644 index 0000000000..2311a44627 --- /dev/null +++ b/docs/v1.15.13/ar/guides/flows/mastering-flow-state.mdx @@ -0,0 +1,228 @@ +--- +title: إتقان إدارة حالة Flow +description: دليل شامل لإدارة الحالة وحفظها والاستفادة منها في CrewAI Flows لبناء تطبيقات AI قوية. +icon: diagram-project +mode: "wide" +--- + +## فهم قوة الحالة في Flows + +إدارة الحالة هي العمود الفقري لأي سير عمل AI متطور. في CrewAI Flows، يتيح لك نظام الحالة الحفاظ على السياق ومشاركة البيانات بين الخطوات وبناء منطق تطبيق معقد. إتقان إدارة الحالة ضروري لإنشاء تطبيقات AI موثوقة وقابلة للصيانة وقوية. + +### لماذا تهم إدارة الحالة + +تمكّنك إدارة الحالة الفعّالة من: + +1. **الحفاظ على السياق عبر خطوات التنفيذ** - تمرير المعلومات بسلاسة بين مراحل سير العمل المختلفة +2. **بناء منطق شرطي معقد** - اتخاذ قرارات بناءً على البيانات المتراكمة +3. **إنشاء تطبيقات مستمرة** - حفظ واستعادة تقدم سير العمل +4. **معالجة الأخطاء بلطف** - تنفيذ أنماط استرداد لتطبيقات أكثر قوة +5. **توسيع تطبيقاتك** - دعم سير العمل المعقدة بتنظيم بيانات مناسب +6. **تمكين التطبيقات الحوارية** - تخزين والوصول إلى سجل المحادثات للتفاعلات الواعية بالسياق + +للدردشة متعددة الجولات (`kickoff` لكل سطر مستخدم، `ChatState`، توجيه النية، تأجيل التتبع، و`ChatSession`)، راجع [تدفقات المحادثة](/ar/guides/flows/conversational-flows). + +## أساسيات إدارة الحالة + +### نهجان لإدارة الحالة + +يوفر CrewAI طريقتين لإدارة الحالة في Flows: + +1. **الحالة غير المنظمة** - استخدام كائنات شبيهة بالقاموس للمرونة +2. **الحالة المنظمة** - استخدام نماذج Pydantic لسلامة الأنواع والتحقق + +### مثال الحالة غير المنظمة + +```python +from crewai.flow.flow import Flow, listen, start + +class UnstructuredStateFlow(Flow): + @start() + def initialize_data(self): + self.state["user_name"] = "Alex" + self.state["preferences"] = {"theme": "dark", "language": "English"} + self.state["items"] = [] + return "Initialized" + + @listen(initialize_data) + def process_data(self, previous_result): + user = self.state["user_name"] + self.state["items"].append("item1") + self.state["processed"] = True + return "Processed" + +flow = UnstructuredStateFlow() +result = flow.kickoff() +``` + +### مثال الحالة المنظمة + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel, Field +from typing import List, Dict, Optional + +class AppState(BaseModel): + user_name: str = "" + items: List[str] = [] + processed: bool = False + completion_percentage: float = 0.0 + +class StructuredStateFlow(Flow[AppState]): + @start() + def initialize_data(self): + self.state.user_name = "Taylor" + return "Initialized" + + @listen(initialize_data) + def process_data(self, previous_result): + self.state.items.append("item1") + self.state.processed = True + self.state.completion_percentage = 50.0 + return "Processed" + +flow = StructuredStateFlow() +result = flow.kickoff() +``` + +### فوائد الحالة المنظمة + +1. **سلامة الأنواع** - اكتشاف أخطاء الأنواع في وقت التطوير +2. **توثيق ذاتي** - نموذج الحالة يوثّق بوضوح البيانات المتاحة +3. **التحقق** - التحقق التلقائي من أنواع البيانات والقيود +4. **دعم IDE** - إكمال تلقائي وتوثيق مضمّن +5. **قيم افتراضية** - تعريف بدائل سهلة للبيانات المفقودة + +## حفظ حالة Flow + +يوفر مزخرف `@persist()` حفظ حالة تلقائي عند نقاط رئيسية في التنفيذ. + +```python +from crewai.flow.flow import Flow, listen, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + value: int = 0 + +@persist() +class PersistentCounterFlow(Flow[CounterState]): + @start() + def increment(self): + self.state.value += 1 + return self.state.value + + @listen(increment) + def double(self, value): + self.state.value = value * 2 + return self.state.value +``` + +#### تفرع الحالة المستمرة + +يدعم `@persist` نمطين متميزين للترطيب في `kickoff` / `kickoff_async`. استخدم **استئناف** (`inputs["id"]`) لمواصلة نفس النسب؛ استخدم **تفرع** (`restore_from_state_id`) لبدء نسبٍ جديد من لقطة: + +| | `state.id` بعد kickoff | كتابات `@persist` تذهب إلى | +|---|---|---| +| `inputs["id"]` (استئناف) | المعرّف المقدم | المعرّف المقدم (يمد التاريخ) | +| `restore_from_state_id` (تفرع) | معرّف جديد، أو `inputs["id"]` إذا ثُبّت | المعرّف الجديد (المصدر محفوظ) | + +```python +from crewai.flow.flow import Flow, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + id: str = "" + counter: int = 0 + +@persist +class CounterFlow(Flow[CounterState]): + @start() + def step(self): + self.state.counter += 1 + +# التشغيل 1: حالة جديدة، العداد 0 -> 1 +flow_1 = CounterFlow() +flow_1.kickoff() + +# التفرع: الترطيب من أحدث لقطة لـ flow_1، لكن الكتابة تحت state.id جديد +flow_2 = CounterFlow() +flow_2.kickoff(restore_from_state_id=flow_1.state.id) +# يبدأ flow_2 بـ counter=1 (مرطّب)، ثم تزيده step() إلى 2. +# تاريخ flow_uuid لـ flow_1 لم يتغيّر. +``` + +ملاحظات السلوك: + +- `restore_from_state_id` غير موجود في الاستمرارية → يعود kickoff بصمت إلى السلوك الافتراضي (يعكس سلوك `inputs["id"]` عند عدم العثور عليه). لا يُطلق أي استثناء. +- الجمع بين `restore_from_state_id` و `from_checkpoint` يطلق `ValueError` — يستهدفان نظامي حالة مختلفين (`@persist` مقابل Checkpointing) ولا يمكن الجمع بينهما. +- `restore_from_state_id=None` (افتراضي) متطابق بايت ببايت مع kickoff بدون المعامل. +- تثبيت `inputs["id"]` أثناء التفرع يعني أن التشغيل الجديد يشارك مفتاح الاستمرارية مع تدفق آخر — عادةً ما تريد فقط `restore_from_state_id`. + +## أنماط حالة متقدمة + +### المنطق الشرطي المبني على الحالة + +```python +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +class PaymentState(BaseModel): + amount: float = 0.0 + is_approved: bool = False + retry_count: int = 0 + +class PaymentFlow(Flow[PaymentState]): + @start() + def process_payment(self): + self.state.amount = 100.0 + self.state.is_approved = self.state.amount < 1000 + return "Payment processed" + + @router(process_payment) + def check_approval(self, previous_result): + if self.state.is_approved: + return "approved" + elif self.state.retry_count < 3: + return "retry" + else: + return "rejected" + + @listen("approved") + def handle_approval(self): + return f"Payment of ${self.state.amount} approved!" + + @listen("retry") + def handle_retry(self): + self.state.retry_count += 1 + return "Retry initiated" + + @listen("rejected") + def handle_rejection(self): + return f"Payment of ${self.state.amount} rejected after {self.state.retry_count} retries." +``` + +## أفضل الممارسات لإدارة الحالة + +1. **اجعل الحالة مركّزة** - صمم الحالة لتحتوي فقط على ما هو ضروري +2. **استخدم الحالة المنظمة للـ Flows المعقدة** - مع نمو التعقيد تصبح الحالة المنظمة أكثر قيمة +3. **وثّق انتقالات الحالة** - للـ Flows المعقدة، وثّق كيف تتغير الحالة عبر التنفيذ +4. **عالج أخطاء الحالة بلطف** - طبّق معالجة أخطاء للوصول إلى الحالة +5. **استخدم الحالة لتتبع التقدم** - استفد من الحالة لتتبع التقدم في Flows طويلة التشغيل +6. **استخدم العمليات غير المتغيرة عند الإمكان** - خاصة مع الحالة المنظمة + +## الخلاصة + +إتقان إدارة الحالة في CrewAI Flows يمنحك القدرة على بناء تطبيقات AI متطورة وقوية تحافظ على السياق وتتخذ قرارات معقدة وتقدم نتائج متسقة. + + +لقد أتقنت الآن مفاهيم وممارسات إدارة الحالة في CrewAI Flows! بهذه المعرفة، يمكنك إنشاء سير عمل AI قوية تحافظ على السياق بفعالية وتشارك البيانات بين الخطوات وتبني منطق تطبيق متطور. + + +## الخطوات التالية + +- جرّب الحالة المنظمة وغير المنظمة في Flows +- جرّب تطبيق حفظ الحالة لسير العمل طويلة التشغيل +- استكشف [بناء أول Crew](/ar/guides/crews/first-crew) لمعرفة كيف تعمل Crews وFlows معًا +- اطلع على [توثيق مرجع Flow](/ar/concepts/flows) لمزيد من الميزات المتقدمة diff --git a/docs/v1.15.13/ar/guides/migration/migrating-from-langgraph.mdx b/docs/v1.15.13/ar/guides/migration/migrating-from-langgraph.mdx new file mode 100644 index 0000000000..913854ae84 --- /dev/null +++ b/docs/v1.15.13/ar/guides/migration/migrating-from-langgraph.mdx @@ -0,0 +1,103 @@ +--- +title: "الانتقال من LangGraph إلى CrewAI: دليل عملي للمهندسين" +description: إذا كنت قد بنيت بالفعل مع LangGraph، تعلم كيفية نقل مشاريعك بسرعة إلى CrewAI +icon: switch +mode: "wide" +--- + +لقد بنيت Agents مع LangGraph. لقد تعاملت مع `StateGraph`، وربطت الحواف الشرطية، وصححت أخطاء قواميس الحالة في الثانية صباحًا. إنه يعمل — لكن في مرحلة ما، بدأت تتساءل عما إذا كان هناك مسار أفضل نحو الإنتاج. + +هناك بالفعل. **CrewAI Flows** يمنحك نفس القوة — تنسيق قائم على الأحداث، توجيه شرطي، حالة مشتركة — مع نموذج كود أبسط بشكل كبير ونموذج ذهني يتماشى مع طريقة تفكيرك الفعلية في سير عمل AI متعدد الخطوات. + +تمشي هذه المقالة عبر المفاهيم الأساسية جنبًا إلى جنب، وتعرض مقارنات كود حقيقية، وتوضح لماذا CrewAI Flows هو إطار العمل الذي ستريد الوصول إليه بعد ذلك. + +--- + +## تحول النموذج الذهني + +LangGraph يطلب منك التفكير في **رسوم بيانية**: عقد وحواف وقواميس حالة. كل سير عمل هو رسم بياني موجّه تربط فيه الانتقالات صراحةً بين خطوات الحساب. + +CrewAI Flows يطلب منك التفكير في **أحداث**: طرق تبدأ الأشياء، وطرق تستمع للنتائج، وطرق توجّه التنفيذ. طوبولوجيا سير العمل تنبثق من تعليقات المزخرفات بدلاً من بناء رسم بياني صريح. + +إليك الخريطة الأساسية: + +| مفهوم LangGraph | المكافئ في CrewAI Flows | +| --- | --- | +| `StateGraph` class | `Flow` class | +| `add_node()` | طرق مزخرفة بـ `@start`، `@listen` | +| `add_edge()` / `add_conditional_edges()` | مزخرفات `@listen()` / `@router()` | +| `TypedDict` state | حالة Pydantic `BaseModel` | +| `START` / `END` constants | مزخرف `@start()` / إرجاع طبيعي للطريقة | +| `graph.compile()` | `flow.kickoff()` | +| Checkpointer / persistence | ذاكرة مدمجة (مدعومة بـ LanceDB) | + +--- + +## العرض 1: خط أنابيب تسلسلي بسيط + +تخيل أنك تبني خط أنابيب يأخذ موضوعًا، ويبحث فيه، ويكتب ملخصًا، وينسّق المخرجات. راجع الملف الإنجليزي الأصلي لأمثلة الكود الكاملة لكلا النهجين. + +الفرق الرئيسي: لا بناء رسم بياني، لا ربط حواف، لا خطوة ترجمة. ترتيب التنفيذ مُعلَن مباشرة حيث يوجد المنطق. `@start()` يحدد نقطة الدخول، و`@listen(method_name)` يربط الخطوات. + +--- + +## العرض 2: التوجيه الشرطي + +مزخرف `@router()` يحوّل طريقة إلى نقطة قرار. يعيد سلسلة تطابق مستمعًا — بلا قواميس تعيين، بلا دوال توجيه منفصلة. منطق التفرع يُقرأ كتعبير `if` في Python لأنه كذلك فعلاً. + +--- + +## العرض 3: دمج فرق Agents AI في Flows + +هنا تتجلى القوة الحقيقية لـ CrewAI. الـ Flows لا تقتصر على ربط استدعاءات LLM — بل تنسّق **Crews** كاملة من Agents مستقلة. + +الفكرة الرئيسية: **الـ Flows توفر طبقة التنسيق، والـ Crews توفر طبقة الذكاء.** كل خطوة في Flow يمكنها تشغيل فريق كامل من Agents متعاونة. + +--- + +## العرض 4: التنفيذ المتوازي والمزامنة + +المشغّل `and_()` على مزخرف `@listen` يضمن أن الطريقة تُنفَّذ فقط بعد اكتمال *جميع* الطرق السابقة. هناك أيضًا `or_()` للمتابعة بمجرد اكتمال *أي* مهمة سابقة. + +--- + +## لماذا CrewAI Flows للإنتاج + +- **حفظ حالة مدمج.** حالة Flow مدعومة بـ LanceDB. +- **إدارة حالة آمنة الأنواع.** نماذج Pydantic توفر التحقق والتسلسل ودعم IDE. +- **تنسيق Agents أصلي.** الـ Crews بنية أساسية أصلية. +- **نموذج ذهني أبسط.** المزخرفات تعلن عن النية. +- **تكامل CLI.** شغّل Flows بـ `crewai run`. + +--- + +## ورقة الغش للترحيل + +1. **عيّن حالتك.** حوّل `TypedDict` إلى Pydantic `BaseModel`. +2. **حوّل العقد إلى طرق.** كل دالة `add_node` تصبح طريقة على فئة `Flow` الفرعية. +3. **استبدل الحواف بمزخرفات.** `add_edge(START, "first_node")` يصبح `@start()`. `add_edge("a", "b")` يصبح `@listen(a)`. +4. **استبدل الحواف الشرطية بـ `@router`.** دالة التوجيه و`add_conditional_edges()` تصبح طريقة `@router()` واحدة. +5. **استبدل compile + invoke بـ kickoff.** احذف `graph.compile()`. استدعِ `flow.kickoff()` بدلاً منه. +6. **فكّر أين تناسب الـ Crews.** أي عقدة بها منطق Agent معقد متعدد الخطوات هي مرشحة لاستخراجها في Crew. + +--- + +## البدء + +```bash +pip install crewai +crewai create flow my_first_flow +cd my_first_flow +``` + +```bash +crewai run +``` + +--- + +## أفكار أخيرة + +LangGraph علّم المنظومة أن سير عمل AI تحتاج هيكلاً. كان ذلك درسًا مهمًا. لكن CrewAI Flows يأخذ ذلك الدرس ويقدمه في شكل أسرع في الكتابة وأسهل في القراءة وأقوى في الإنتاج — خاصة عندما تتضمن سير عملك عدة Agents متعاونة. + +ابدأ بـ `crewai create flow`. لن تنظر للخلف. diff --git a/docs/v1.15.13/ar/guides/migration/upgrading-crewai.mdx b/docs/v1.15.13/ar/guides/migration/upgrading-crewai.mdx new file mode 100644 index 0000000000..3726893354 --- /dev/null +++ b/docs/v1.15.13/ar/guides/migration/upgrading-crewai.mdx @@ -0,0 +1,190 @@ +--- +title: "ترقية CrewAI" +description: "كيفية ترقية CrewAI في مشروعك والتكيّف مع التغييرات الجذرية بين الإصدارات." +icon: "arrow-up-circle" +--- + +## نظرة عامة + +تجلب إصدارات CrewAI قدرات جديدة بانتظام. يرشدك هذا الدليل خلال الخطوات العملية للحفاظ على تثبيتك محدّثًا — سواء أداة سطر الأوامر أو البيئة الافتراضية لمشروعك. + +إذا كنت تبدأ من الصفر، راجع [التثبيت](/ar/installation). إذا كنت قادمًا من إطار عمل آخر، راجع [الترحيل من LangGraph](/ar/guides/migration/migrating-from-langgraph). + +--- + +## الشيئان اللذان قد ترغب في ترقيتهما + +يوجد CrewAI في مكانين على جهازك، ويتم ترقيتهما بشكل مستقل: + +| ماذا | كيف يُثبَّت | كيف تتم الترقية | +|---|---|---| +| **أداة سطر الأوامر العامة `crewai`** | `uv tool install crewai` | `uv tool install crewai --upgrade` | +| **بيئة venv للمشروع** (حيث يعمل الكود) | `crewai install` / `uv sync` | `uv add "crewai[...]>=X.Y.Z"` ثم `crewai install` | + +يمكن لهما — وغالبًا ما يحدث — أن يخرجا عن التزامن. تشغيل `crewai --version` يُظهر إصدار سطر الأوامر. تشغيل `uv pip show crewai` داخل مشروعك يُظهر إصدار venv. إذا اختلفا، فهذا طبيعي؛ ما يهم بالنسبة للكود قيد التشغيل هو إصدار venv. + +## لماذا لا يقوم `crewai install` وحده بالترقية + +`crewai install` هو غلاف رفيع حول `uv sync`. يُثبّت بالضبط ما يقوله ملف `uv.lock` الحالي — وهو **لا** يرفع أي قيود إصدار. + +إذا كان `pyproject.toml` يقول `crewai>=1.11.1` وقد قام ملف القفل بحلّه إلى `1.11.1`، فإن تشغيل `crewai install` سيُبقيك على `1.11.1` للأبد، حتى وإن كان الإصدار `1.14.4` متاحًا. + +للترقية فعلًا، عليك: + +1. تحديث قيد الإصدار في `pyproject.toml` +2. إعادة حلّ ملف القفل +3. مزامنة venv + +`uv add` يقوم بالثلاثة في خطوة واحدة. + +## كيفية ترقية مشروعك + +```bash +# يرفع القيد ويعيد القفل في أمر واحد +uv add "crewai[tools]>=1.14.4" + +# يزامن venv (crewai install يستدعي uv sync تحت الغطاء) +crewai install + +# تحقّق +uv pip show crewai +# → Version: 1.14.4 +``` + +استبدل `[tools]` بأي إضافات يستخدمها مشروعك (مثلًا `[tools,anthropic]`). تحقّق من قائمة `dependencies` في `pyproject.toml` إن لم تكن متأكدًا. + + + يحدّث `uv add` كلا من `pyproject.toml` **و** `uv.lock` بشكل ذرّي. إذا قمت بتحرير `pyproject.toml` يدويًا، فإنك لا تزال بحاجة إلى تشغيل `uv lock --upgrade-package crewai` لإعادة حلّ ملف القفل قبل أن يلتقط `crewai install` الإصدار الجديد. + + +## ترقية أداة سطر الأوامر العامة + +أداة سطر الأوامر العامة منفصلة عن مشروعك. قم بترقيتها عبر: + +```bash +uv tool install crewai --upgrade +``` + +إذا حذّرك الـ shell بشأن `PATH` بعد الترقية، قم بتحديثه: + +```bash +uv tool update-shell +``` + +هذا **لا** يمسّ بيئة venv الخاصة بمشروعك — لا تزال بحاجة إلى `uv add` + `crewai install` داخل المشروع. + +## التحقق من تزامن الاثنين + +```bash +# إصدار سطر الأوامر العام +crewai --version + +# إصدار venv للمشروع +uv pip show crewai | grep Version +``` + +ليس من الضروري أن يتطابقا — لكن إصدار venv للمشروع هو ما يهم لسلوك التشغيل. + + + يتطلب CrewAI `Python >=3.10, <3.14`. إذا كان `uv` مثبَّتًا مقابل مفسّر أقدم، فأعد إنشاء venv للمشروع باستخدام إصدار Python مدعوم قبل تشغيل `crewai install`. + + +--- + +## التغييرات الجذرية وملاحظات الترحيل + +تتطلب معظم الترقيات تعديلات صغيرة فقط. المناطق أدناه هي تلك التي تنكسر بصمت أو بتتبعات مكدّس مربكة. + +### مسارات الاستيراد: tools و`BaseTool` + +الموقع الرسمي لاستيراد الـ tools هو `crewai.tools`. لا تزال المسارات القديمة تظهر في الدروس لكن يجب تحديثها. + +```python +# قبل +from crewai_tools import BaseTool +from crewai.agents.tools import tool + +# بعد +from crewai.tools import BaseTool, tool +``` + +كلٌ من المُزخرف `@tool` والفئة الفرعية `BaseTool` يقعان في `crewai.tools`. `AgentFinish` والرموز الأخرى الداخلية للوكيل لم تعد جزءًا من السطح العام — إذا كنت تستوردها، فانتقل إلى event listeners أو callbacks الـ `Task` بدلًا منها. + +### تغييرات معاملات `Agent` + +```python +from crewai import Agent + +agent = Agent( + role="Researcher", + goal="Find authoritative sources on {topic}", + backstory="You are a careful, source-driven researcher.", + llm="gpt-4o-mini", # اسم نموذج كسلسلة نصية أو كائن LLM + verbose=True, # bool وليس مستوى عددي صحيح + max_iter=15, # تغيّر الافتراضي بين الإصدارات — حدّده بشكل صريح + allow_delegation=False, +) +``` + +- يقبل `llm` إما اسم نموذج كسلسلة نصية (يُحلَّ عبر المزوّد المهيّأ) أو كائن `LLM` للتحكم الدقيق. +- `verbose` هو `bool` بسيط. تمرير عدد صحيح لم يعد يبدّل مستويات السجل. +- تغيّرت افتراضات `max_iter` بين الإصدارات. إذا توقف وكيلك بصمت عن التكرار بعد أول استدعاء tool، فحدّد `max_iter` صراحةً. + +### معاملات `Crew` + +```python +from crewai import Crew, Process + +crew = Crew( + agents=[...], + tasks=[...], + process=Process.sequential, # أو Process.hierarchical + memory=True, + cache=True, + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}}, +) +``` + +- يتطلب `process=Process.hierarchical` إما `manager_llm=` أو `manager_agent=`. بدون أحدهما، يرفع kickoff خطأً عند التحقّق. +- `memory=True` مع مزوّد embedding غير افتراضي يحتاج إلى قاموس `embedder` — راجع [إعداد الذاكرة وembedder](#memory-embedder-config) أدناه. + +### الإخراج المُهيكل لـ `Task` + +استخدم `output_pydantic` أو `output_json` أو `output_file` لإلزام نتيجة المهمة بشكل مكتوب الأنواع: + +```python +from pydantic import BaseModel +from crewai import Task + +class Article(BaseModel): + title: str + body: str + +write = Task( + description="Write an article about {topic}", + expected_output="A short article with a title and body", + agent=writer, + output_pydantic=Article, # الفئة، وليس مثيلًا منها + output_file="output/article.md", +) +``` + +`output_pydantic` يأخذ **الفئة** نفسها. تمرير `Article(title="", body="")` خطأ شائع ويفشل بخطأ تحقّق مربك. + +### إعداد الذاكرة وembedder {#memory-embedder-config} + +إذا كان `memory=True` وأنت لا تستخدم embeddings الافتراضية الخاصة بـ OpenAI، فيجب أن تمرّر `embedder`: + +```python +crew = Crew( + agents=[...], + tasks=[...], + memory=True, + embedder={ + "provider": "ollama", + "config": {"model": "nomic-embed-text"}, + }, +) +``` + +ضع بيانات اعتماد المزوّد المعنيّة (`OPENAI_API_KEY`, `OLLAMA_HOST`, إلخ) في ملف `.env`. مسارات تخزين الذاكرة محلية بالنسبة للمشروع افتراضيًا — احذف مجلد ذاكرة المشروع إذا غيّرت embedders، لأن الأبعاد لا تختلط. diff --git a/docs/v1.15.13/ar/guides/tools/publish-custom-tools.mdx b/docs/v1.15.13/ar/guides/tools/publish-custom-tools.mdx new file mode 100644 index 0000000000..f181e0e254 --- /dev/null +++ b/docs/v1.15.13/ar/guides/tools/publish-custom-tools.mdx @@ -0,0 +1,96 @@ +--- +title: نشر أدوات مخصصة +description: كيفية بناء وتعبئة ونشر أدواتك الخاصة المتوافقة مع CrewAI على PyPI ليتمكن أي مستخدم CrewAI من تثبيتها واستخدامها. +icon: box-open +mode: "wide" +--- + +## نظرة عامة + +نظام الأدوات في CrewAI مصمم للتوسيع. إذا بنيت أداة يمكن أن تفيد الآخرين، يمكنك تعبئتها كمكتبة Python مستقلة ونشرها على PyPI وإتاحتها لأي مستخدم CrewAI — دون الحاجة لطلب سحب إلى مستودع CrewAI. + +يمشي هذا الدليل عبر العملية الكاملة: تنفيذ عقد الأدوات، وهيكلة حزمتك، والنشر على PyPI. + + +إذا كنت تحتاج فقط أداة مخصصة لمشروعك، راجع دليل [إنشاء أدوات مخصصة](/ar/learn/create-custom-tools) بدلاً من ذلك. + + +## عقد الأدوات + +كل أداة CrewAI يجب أن تستوفي إحدى الواجهتين: + +### الخيار 1: وراثة `BaseTool` + +ورث من `crewai.tools.BaseTool` وطبّق طريقة `_run`. عرّف `name` و`description` واختياريًا `args_schema` للتحقق من المدخلات. + +```python +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + + +class GeolocateInput(BaseModel): + """Input schema for GeolocateTool.""" + address: str = Field(..., description="The street address to geolocate.") + + +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converts a street address into latitude/longitude coordinates." + args_schema: type[BaseModel] = GeolocateInput + + def _run(self, address: str) -> str: + return f"40.7128, -74.0060" +``` + +### الخيار 2: استخدام مزخرف `@tool` + +للأدوات الأبسط، يحوّل مزخرف `@tool` دالة إلى أداة CrewAI. يجب أن تحتوي الدالة على سلسلة توثيق (تُستخدم كوصف الأداة) وتعليقات أنواع. + +```python +from crewai.tools import tool + + +@tool("Geolocate") +def geolocate(address: str) -> str: + """Converts a street address into latitude/longitude coordinates.""" + return "40.7128, -74.0060" +``` + +### المتطلبات الأساسية + +بغض النظر عن النهج الذي تستخدمه، يجب أن تحتوي أداتك على: + +- **`name`** — معرّف قصير ووصفي. +- **`description`** — يخبر الـ Agent متى وكيف يستخدم الأداة. +- **`_run`** (BaseTool) أو **جسم الدالة** (@tool) — منطق التنفيذ المتزامن. +- **تعليقات أنواع** على جميع المعاملات وقيم الإرجاع. +- إرجاع نتيجة **نصية** (أو شيء يمكن تحويله لنص). + +## هيكل الحزمة + +``` +crewai-geolocate/ +├── pyproject.toml +├── LICENSE +├── README.md +└── src/ + └── crewai_geolocate/ + ├── __init__.py + └── tools.py +``` + +## النشر على PyPI + +```bash +# Build the package +uv build + +# Publish to PyPI +uv publish +``` + +بعد النشر، يمكن للمستخدمين تثبيت أداتك بـ: + +```bash +uv add crewai-geolocate +``` diff --git a/docs/v1.15.13/ar/index.mdx b/docs/v1.15.13/ar/index.mdx new file mode 100644 index 0000000000..e952df35f7 --- /dev/null +++ b/docs/v1.15.13/ar/index.mdx @@ -0,0 +1,105 @@ +--- +title: "توثيق CrewAI" +description: "ابنِ Agents ذكاء اصطناعي تعاونية وCrews وFlows — جاهزة للإنتاج من اليوم الأول." +icon: "house" +mode: "wide" +--- + +
+ CrewAI +
+

أطلق أنظمة متعددة الـ Agents بثقة

+

+ صمم Agents، ونسّق Crews، وأتمت Flows مع حواجز حماية وذاكرة ومعرفة ومراقبة مدمجة. +

+
+ + + +
+ +
+ +## ابدأ + + + + نظرة عامة على مفاهيم CrewAI وبنيته المعمارية وما يمكنك بناؤه باستخدام Agents وCrews وFlows. + + + التثبيت عبر `uv`، وإعداد مفاتيح API، وتهيئة CLI للتطوير المحلي. + + + أنشئ أول Crew لك في دقائق. تعلم بيئة التشغيل الأساسية وهيكل المشروع ودورة التطوير. + + + +## ابنِ الأساسيات + + + + أنشئ Agents بأدوات وذاكرة ومعرفة ومخرجات منظمة باستخدام Pydantic. يتضمن قوالب وأفضل الممارسات. + + + نسّق خطوات start/listen/router، وأدر الحالة، واحفظ التنفيذ، واستأنف سير العمل الطويل. + + + حدد عمليات متسلسلة أو هرمية أو مختلطة مع حواجز حماية واستدعاءات راجعة ومحفزات تدخل بشري. + + + +## رحلة المؤسسات + + + + إدارة البيئات وإعادة النشر بأمان ومراقبة التشغيل المباشر من لوحة تحكم المؤسسات. + + + ربط Gmail وSlack وSalesforce والمزيد. تمرير بيانات المحفزات إلى Crews وFlows تلقائيًا. + + + دعوة أعضاء الفريق وتهيئة التحكم في الوصول المبني على الأدوار وإدارة الوصول إلى أتمتة الإنتاج. + + + +## ما الجديد + + + + نظرة شاملة موحدة على Gmail وDrive وOutlook وTeams وOneDrive وHubSpot والمزيد — الآن مع نماذج بيانات وCrews. + + + استدعاء أتمتة CrewAI الحالية أو Amazon Bedrock Agents مباشرة من Crews باستخدام مجموعة أدوات التكامل المحدّثة. + + + + + تصفح الأمثلة وكتب الوصفات للحصول على تطبيقات مرجعية شاملة عبر Agents وFlows وأتمتة المؤسسات. + + +## ابقَ على تواصل + + + + إذا ساعدك CrewAI في الإطلاق بشكل أسرع، امنحنا نجمة وشارك مشاريعك مع المجتمع. + + + اطرح أسئلة واعرض سير العمل واطلب ميزات جديدة جنبًا إلى جنب مع المطورين الآخرين. + + diff --git a/docs/v1.15.13/ar/installation.mdx b/docs/v1.15.13/ar/installation.mdx new file mode 100644 index 0000000000..1b6df571c5 --- /dev/null +++ b/docs/v1.15.13/ar/installation.mdx @@ -0,0 +1,216 @@ +--- +title: التثبيت +description: ابدأ مع CrewAI - التثبيت والتهيئة وبناء أول فريق AI +icon: wrench +mode: "wide" +--- + +### شاهد: بناء Agents و Flows في CrewAI باستخدام Coding Agent Skills + +قم بتثبيت مهارات وكيل البرمجة الخاصة بنا (Claude Code، Codex، ...) لتشغيل وكلاء البرمجة بسرعة مع CrewAI. + +يمكنك تثبيتها باستخدام `npx skills add crewaiinc/skills` + + + +## فيديو تعليمي + +شاهد هذا الفيديو التعليمي لعرض تفصيلي لعملية التثبيت: + + + +## دليل نصي + + + **متطلبات إصدار Python** + +يتطلب CrewAI إصدار `Python >=3.10 and <3.14`. إليك كيفية التحقق من إصدارك: + +```bash +python3 --version +``` + +إذا كنت بحاجة لتحديث Python، قم بزيارة [python.org/downloads](https://python.org/downloads) + + + + + **متطلبات OpenAI SDK** + +يتطلب CrewAI 0.175.0 إصدار `openai >= 1.13.3`. إذا كنت تدير التبعيات بنفسك، تأكد من أن بيئتك تستوفي هذا الشرط لتجنب مشاكل الاستيراد/التشغيل. + + + +يستخدم CrewAI أداة `uv` لإدارة التبعيات والحزم. وهي تبسّط إعداد المشروع وتنفيذه وتوفر تجربة سلسة. + +إذا لم تكن قد ثبّتت `uv` بعد، اتبع **الخطوة 1** لإعدادها بسرعة على نظامك، وإلا يمكنك الانتقال إلى **الخطوة 2**. + + + + - **على macOS/Linux:** + + استخدم `curl` لتحميل السكريبت وتنفيذه عبر `sh`: + + ```shell + curl -LsSf https://astral.sh/uv/install.sh | sh + ``` + إذا لم يكن `curl` متاحًا على نظامك، يمكنك استخدام `wget`: + + ```shell + wget -qO- https://astral.sh/uv/install.sh | sh + ``` + + - **على Windows:** + + استخدم `irm` لتحميل السكريبت و`iex` لتنفيذه: + + ```shell + powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" + ``` + إذا واجهت أي مشاكل، راجع [دليل تثبيت UV](https://docs.astral.sh/uv/getting-started/installation/) لمزيد من المعلومات. + + + + - شغّل الأمر التالي لتثبيت واجهة سطر أوامر `crewai`: + ```shell + uv tool install crewai + ``` + + إذا ظهر تحذير بشأن `PATH`، شغّل هذا الأمر لتحديث الصدفة: + ```shell + uv tool update-shell + ``` + + + + إذا واجهت خطأ بناء `chroma-hnswlib==0.7.6` (`fatal error C1083: Cannot open include file: 'float.h'`) على Windows، ثبّت [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/) مع خيار *Desktop development with C++*. + + + - للتحقق من تثبيت `crewai`، شغّل: + ```shell + uv tool list + ``` + - يجب أن ترى شيئًا مثل: + ```shell + crewai v0.102.0 + - crewai + ``` + - إذا كنت بحاجة لتحديث `crewai`، شغّل: + ```shell + uv tool install crewai --upgrade + ``` + تم التثبيت بنجاح! أنت جاهز لإنشاء أول Crew! + + + + +# إنشاء مشروع CrewAI + +يقوم `crewai create crew` الآن بإنشاء مشروع crew بأسلوب JSON-first. توضع الـ Agents في `agents/*.jsonc`، وتوضع المهام وإعدادات الـ crew في `crew.jsonc`، ويحمّل `crewai run` هذا التعريف مباشرة. + + + + - شغّل أمر `crewai` عبر CLI: + ```shell + crewai create crew + ``` + + - سينشئ هذا مشروعًا جديدًا بالهيكل التالي: + ``` + my_project/ + ├── .gitignore + ├── .env + ├── agents/ + │ └── researcher.jsonc + ├── crew.jsonc + ├── knowledge/ + ├── pyproject.toml + ├── README.md + ├── skills/ + └── tools/ + ``` + + - إذا احتجت إلى البنية القديمة Python/YAML التي تحتوي على `crew.py` و `config/agents.yaml` و `config/tasks.yaml`، شغّل: + ```shell + crewai create crew --classic + ``` + + + + + - سيحتوي مشروعك على هذه الملفات الأساسية: + | الملف | الغرض | + | --- | --- | + | `crew.jsonc` | إعداد الـ crew وترتيب المهام والعملية وقيم الإدخال الافتراضية | + | `agents/*.jsonc` | تعريف دور كل Agent وهدفه و backstory والـ LLM والأدوات والسلوك | + | `.env` | تخزين مفاتيح API ومتغيرات البيئة | + | `tools/` | ملفات Python اختيارية لأدوات `custom:` | + | `knowledge/` | ملفات معرفة اختيارية للـ Agents | + | `skills/` | ملفات skills اختيارية تطبق على الـ crew | + + - ابدأ بتحرير `crew.jsonc` والملفات داخل `agents/` لتعريف سلوك الـ crew. + - استخدم قيم `{placeholder}` في نصوص الـ Agents والمهام، ثم ضع القيم الافتراضية في `inputs` داخل `crew.jsonc`. عند تشغيل `crewai run` ستطلب CLI أي قيم ناقصة. + - احتفظ بالمعلومات الحساسة مثل مفاتيح API في `.env`. + + + + + - قبل تشغيل الـ Crew، تأكد من تنفيذ: + ```bash + crewai install + ``` + - إذا كنت بحاجة لتثبيت حزم إضافية، استخدم: + ```shell + uv add + ``` + - لتشغيل الـ Crew، نفّذ الأمر التالي في جذر مشروعك: + ```bash + crewai run + ``` + + + +## خيارات التثبيت للمؤسسات + + +للفرق والمؤسسات، يوفر CrewAI خيارات نشر مؤسسية تزيل تعقيد الإعداد: + +### CrewAI AMP (SaaS) + +- لا يتطلب أي تثبيت - فقط سجّل مجانًا على [app.crewai.com](https://app.crewai.com) +- تحديثات وصيانة تلقائية +- بنية تحتية مُدارة وقابلة للتوسع +- بناء Crews بدون كتابة كود + +### CrewAI Factory (استضافة ذاتية) + +- نشر بالحاويات على بنيتك التحتية +- يدعم أي مزود سحابي بما في ذلك النشر المحلي +- تكامل مع أنظمة الأمان الحالية + + + تعرّف على عروض CrewAI للمؤسسات وجدول عرضًا توضيحيًا + + + +## الخطوات التالية + + + + اتبع البداية السريعة لإنشاء Flow وتشغيل طاقم بوكيل واحد وإنتاج تقرير. + + + تواصل مع مطورين آخرين واحصل على المساعدة وشارك تجاربك مع CrewAI. + + diff --git a/docs/v1.15.13/ar/introduction.mdx b/docs/v1.15.13/ar/introduction.mdx new file mode 100644 index 0000000000..58d441c6e7 --- /dev/null +++ b/docs/v1.15.13/ar/introduction.mdx @@ -0,0 +1,152 @@ +--- +title: مقدمة +description: ابنِ فرق Agents ذكاء اصطناعي تعمل معًا لمعالجة المهام المعقدة +icon: handshake +mode: "wide" +--- + +# ما هو CrewAI؟ + +**CrewAI هو إطار العمل مفتوح المصدر الرائد لتنسيق Agents الذكاء الاصطناعي المستقلة وبناء سير العمل المعقدة.** + +يمكّن المطورين من بناء أنظمة متعددة الـ Agents جاهزة للإنتاج من خلال الجمع بين الذكاء التعاوني لـ **Crews** والتحكم الدقيق لـ **Flows**. + +- **[CrewAI Flows](/ar/guides/flows/first-flow)**: العمود الفقري لتطبيق الذكاء الاصطناعي. تتيح لك Flows إنشاء سير عمل منظمة قائمة على الأحداث تدير الحالة وتتحكم في التنفيذ. وهي توفر البنية الأساسية التي تعمل ضمنها Agents الذكاء الاصطناعي. +- **[CrewAI Crews](/ar/guides/crews/first-crew)**: وحدات العمل ضمن Flow. الـ Crews هي فرق من Agents مستقلة تتعاون لحل مهام محددة يفوضها إليها Flow. + +مع أكثر من 100,000 مطور معتمد عبر دوراتنا المجتمعية، يُعد CrewAI المعيار لأتمتة الذكاء الاصطناعي الجاهزة للمؤسسات. + +### شاهد: بناء Agents و Flows في CrewAI باستخدام Coding Agent Skills + +قم بتثبيت مهارات وكيل البرمجة الخاصة بنا (Claude Code، Codex، ...) لتشغيل وكلاء البرمجة بسرعة مع CrewAI. + +يمكنك تثبيتها باستخدام `npx skills add crewaiinc/skills` + + + +## بنية CrewAI المعمارية + +صُممت بنية CrewAI لتحقيق التوازن بين الاستقلالية والتحكم. + +### 1. Flows: العمود الفقري + + + فكّر في Flow كـ "المدير" أو "تعريف العملية" لتطبيقك. يحدد الخطوات والمنطق وكيفية تدفق البيانات عبر نظامك. + + + + نظرة عامة على إطار عمل CrewAI + + +توفر Flows: +- **إدارة الحالة**: حفظ البيانات عبر الخطوات والتنفيذات. +- **تنفيذ قائم على الأحداث**: تشغيل إجراءات بناءً على أحداث أو مدخلات خارجية. +- **التحكم في التدفق**: استخدام المنطق الشرطي والحلقات والتفرع. + +### 2. Crews: الذكاء + + + الـ Crews هي "الفرق" التي تقوم بالعمل الثقيل. ضمن Flow، يمكنك تشغيل Crew لمعالجة مشكلة معقدة تتطلب إبداعًا وتعاونًا. + + + + نظرة عامة على إطار عمل CrewAI + + +توفر Crews: +- **Agents بأدوار محددة**: Agents متخصصة بأهداف وأدوات محددة. +- **تعاون مستقل**: تعمل الـ Agents معًا لحل المهام. +- **تفويض المهام**: يتم تعيين المهام وتنفيذها بناءً على قدرات الـ Agent. + +## كيف يعمل الكل معًا + +1. يبدأ **Flow** حدثًا أو يشغّل عملية. +2. يدير **Flow** الحالة ويقرر ما يجب فعله بعد ذلك. +3. يفوّض **Flow** مهمة معقدة إلى **Crew**. +4. تتعاون Agents الـ **Crew** لإكمال المهمة. +5. يعيد **Crew** النتيجة إلى **Flow**. +6. يستمر **Flow** في التنفيذ بناءً على النتيجة. + +## الميزات الرئيسية + + + + ابنِ سير عمل موثوقة وذات حالة يمكنها التعامل مع العمليات طويلة التشغيل والمنطق المعقد. + + + انشر فرقًا من الـ Agents يمكنها التخطيط والتنفيذ والتعاون لتحقيق أهداف عالية المستوى. + + + اربط Agents بأي API أو قاعدة بيانات أو أداة محلية. + + + مصمم مع مراعاة الأمان والامتثال لعمليات نشر المؤسسات. + + + +## متى تستخدم Crews مقابل Flows + +**الإجابة المختصرة: استخدم كليهما.** + +لأي تطبيق جاهز للإنتاج، **ابدأ بـ Flow**. + +- **استخدم Flow** لتعريف الهيكل العام والحالة والمنطق لتطبيقك. +- **استخدم Crew** ضمن خطوة Flow عندما تحتاج فريقًا من الـ Agents لأداء مهمة معقدة محددة تتطلب استقلالية. + +| حالة الاستخدام | البنية المعمارية | +| :--- | :--- | +| **أتمتة بسيطة** | Flow واحد مع مهام Python | +| **بحث معقد** | Flow يدير الحالة -> Crew يجري البحث | +| **واجهة تطبيق خلفية** | Flow يعالج طلبات API -> Crew ينشئ المحتوى -> Flow يحفظ في قاعدة البيانات | + +## لماذا تختار CrewAI؟ + +- **تشغيل مستقل**: تتخذ الـ Agents قرارات ذكية بناءً على أدوارها وأدواتها المتاحة +- **تفاعل طبيعي**: تتواصل الـ Agents وتتعاون كأعضاء فريق بشري +- **تصميم قابل للتوسيع**: سهولة إضافة أدوات وأدوار وقدرات جديدة +- **جاهز للإنتاج**: مبني للموثوقية والتوسع في التطبيقات الواقعية +- **موجّه نحو الأمان**: مصمم مع مراعاة متطلبات أمان المؤسسات +- **كفاءة التكلفة**: محسّن لتقليل استخدام الرموز المميزة واستدعاءات API + +## هل أنت مستعد للبدء في البناء؟ + + + + تعلم كيفية إنشاء سير عمل منظمة قائمة على الأحداث مع تحكم دقيق في التنفيذ. + + + دليل تفصيلي لإنشاء فريق AI تعاوني يعمل معًا لحل المشكلات المعقدة. + + + + + + ابدأ مع CrewAI في بيئة التطوير الخاصة بك. + + + أنشئ Flow وشغّل طاقمًا بوكيل واحد وأنشئ تقريرًا من البداية للنهاية. + + + تواصل مع مطورين آخرين واحصل على المساعدة وشارك تجاربك مع CrewAI. + + diff --git a/docs/v1.15.13/ar/learn/a2a-agent-delegation.mdx b/docs/v1.15.13/ar/learn/a2a-agent-delegation.mdx new file mode 100644 index 0000000000..d743d98fb7 --- /dev/null +++ b/docs/v1.15.13/ar/learn/a2a-agent-delegation.mdx @@ -0,0 +1,87 @@ +--- +title: بروتوكول Agent-to-Agent (A2A) +description: الـ Agents تفوّض المهام إلى Agents A2A بعيدة و/أو تعمل كـ Agents خادم متوافقة مع A2A. +icon: network-wired +mode: "wide" +--- + +## تفويض Agent A2A + +يعامل CrewAI [بروتوكول A2A](https://a2a-protocol.org/latest/) كبنية تفويض أساسية، مما يمكّن الـ Agents من تفويض المهام وطلب المعلومات والتعاون مع Agents بعيدة، وكذلك العمل كـ Agents خادم متوافقة مع A2A. في وضع العميل، تختار الـ Agents تلقائيًا بين التنفيذ المحلي والتفويض البعيد بناءً على متطلبات المهمة. + +## كيف يعمل + +عندما يُهيَّأ Agent بقدرات A2A: + +1. يحلل الـ Agent كل مهمة +2. يقرر إما: + - معالجة المهمة مباشرة باستخدام قدراته الخاصة + - التفويض إلى Agent A2A بعيد للمعالجة المتخصصة +3. إذا فوّض، يتواصل الـ Agent مع Agent A2A البعيد عبر البروتوكول +4. تُعاد النتائج إلى سير عمل CrewAI + + + تفويض A2A يتطلب حزمة `a2a-sdk`. ثبّتها بـ: `uv add 'crewai[a2a]'` أو `pip install 'crewai[a2a]'` + + +## التهيئة الأساسية + + + `crewai.a2a.config.A2AConfig` مهمل وسيُزال في v2.0.0. استخدم `A2AClientConfig` للاتصال بـ Agents بعيدة و/أو `A2AServerConfig` لعرض الـ Agents كخوادم. + + +```python Code +from crewai import Agent, Crew, Task +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=A2AClientConfig( + endpoint="https://example.com/.well-known/agent-card.json", + timeout=120, + max_turns=10 + ) +) + +task = Task( + description="Research the latest developments in quantum computing", + expected_output="A comprehensive research report", + agent=agent +) + +crew = Crew(agents=[agent], tasks=[task], verbose=True) +result = crew.kickoff() +``` + +## خيارات تهيئة العميل + +راجع الملف الإنجليزي الأصلي للحصول على القائمة الكاملة لمعاملات `A2AClientConfig` وخيارات المصادقة وآليات التحديث وتهيئة الخادم. + +## أفضل الممارسات + + + + هيّئ المهلات بناءً على أوقات استجابة Agent A2A المتوقعة. + + + + استخدم `max_turns` لمنع التبادل المفرط. + + + + عيّن `fail_fast=False` لبيئات الإنتاج مع عدة Agents. + + + + خزّن رموز المصادقة وبيانات الاعتماد كمتغيرات بيئة، ليس في الكود. + + + +## تعلم المزيد + +- [توثيق بروتوكول A2A](https://a2a-protocol.org) +- [تطبيقات A2A النموذجية](https://github.com/a2aproject/a2a-samples) +- [A2A Python SDK](https://github.com/a2aproject/a2a-python) diff --git a/docs/v1.15.13/ar/learn/before-and-after-kickoff-hooks.mdx b/docs/v1.15.13/ar/learn/before-and-after-kickoff-hooks.mdx new file mode 100644 index 0000000000..0766a0f0db --- /dev/null +++ b/docs/v1.15.13/ar/learn/before-and-after-kickoff-hooks.mdx @@ -0,0 +1,47 @@ +--- +title: خطافات قبل وبعد الانطلاق +description: تعلم كيفية استخدام خطافات قبل وبعد الانطلاق في CrewAI +mode: "wide" +--- + +يوفر CrewAI خطافات تتيح لك تنفيذ كود قبل وبعد انطلاق Crew. هذه الخطافات مفيدة لمعالجة المدخلات مسبقًا أو معالجة النتائج لاحقًا. + +## خطاف قبل الانطلاق + +يُنفَّذ خطاف قبل الانطلاق قبل أن يبدأ Crew مهامه. يتلقى قاموس المدخلات ويمكنه تعديله قبل تمريره إلى Crew. يمكنك استخدام هذا الخطاف لإعداد بيئتك أو تحميل البيانات اللازمة أو معالجة المدخلات مسبقًا. + +```python +from crewai import CrewBase +from crewai.project import before_kickoff + +@CrewBase +class MyCrew: + @before_kickoff + def prepare_data(self, inputs): + inputs['processed'] = True + return inputs +``` + +## خطاف بعد الانطلاق + +يُنفَّذ خطاف بعد الانطلاق بعد إتمام Crew مهامه. يتلقى كائن النتيجة الذي يحتوي على مخرجات تنفيذ Crew. هذا الخطاف مثالي لمعالجة النتائج لاحقًا مثل التسجيل أو تحويل البيانات أو التحليل الإضافي. + +```python +from crewai import CrewBase +from crewai.project import after_kickoff + +@CrewBase +class MyCrew: + @after_kickoff + def log_results(self, result): + print("Crew execution completed with result:", result) + return result +``` + +## استخدام كلا الخطافين + +يمكن استخدام كلا الخطافين معًا لتوفير عملية إعداد وتفكيك شاملة لتنفيذ Crew. وهما مفيدان بشكل خاص في الحفاظ على بنية كود نظيفة من خلال فصل المسؤوليات وتعزيز نمطية تنفيذات CrewAI. + +## الخلاصة + +توفر خطافات قبل وبعد الانطلاق في CrewAI طرقًا قوية للتفاعل مع دورة حياة تنفيذ Crew. من خلال فهم واستخدام هذه الخطافات، يمكنك تعزيز متانة ومرونة Agents الذكاء الاصطناعي بشكل كبير. diff --git a/docs/v1.15.13/ar/learn/bring-your-own-agent.mdx b/docs/v1.15.13/ar/learn/bring-your-own-agent.mdx new file mode 100644 index 0000000000..d3b76446da --- /dev/null +++ b/docs/v1.15.13/ar/learn/bring-your-own-agent.mdx @@ -0,0 +1,41 @@ +--- +title: أحضر Agent الخاص بك +description: تعلم كيفية إحضار Agents خاصة بك تعمل ضمن Crew. +icon: robots +mode: "wide" +--- + +قابلية التشغيل البيني مفهوم أساسي في CrewAI. يوضح هذا الدليل كيفية إحضار Agents خاصة بك تعمل ضمن Crew. + +## دليل المحوّلات لإحضار Agents الخاصة (Agents من LangGraph وOpenAI وغيرها...) + +نتطلب 3 محوّلات لتحويل أي Agent من أطر عمل مختلفة للعمل ضمن Crew. + +1. BaseAgentAdapter +2. BaseToolAdapter +3. BaseConverter + +## BaseAgentAdapter + +تعرّف هذه الفئة المجردة الواجهة المشتركة والوظائف التي يجب أن تنفذها جميع محوّلات الـ Agent. تمتد BaseAgent للحفاظ على التوافق مع إطار عمل CrewAI مع إضافة متطلبات خاصة بالمحوّل. + +الطرق المطلوبة: + +1. `def configure_tools` +2. `def configure_structured_output` + +## إنشاء محوّل خاص بك + +لدمج Agent من إطار عمل مختلف في CrewAI، تحتاج لإنشاء محوّل مخصص بوراثة `BaseAgentAdapter`. يعمل هذا المحوّل كطبقة توافق تترجم بين واجهات CrewAI والمتطلبات المحددة للـ Agent الخارجي. + +راجع الملف الإنجليزي الأصلي لأمثلة الكود التفصيلية لتنفيذ BaseAgentAdapter وBaseToolAdapter وBaseConverter. + +## محوّلات جاهزة للاستخدام + +نوفر محوّلات جاهزة للأطر التالية: +1. LangGraph +2. OpenAI Agents + +## تشغيل Crew مع Agents محوّلة: + +راجع الملف الإنجليزي الأصلي للحصول على مثال الكود الكامل الذي يوضح استخدام CrewAI Agent وOpenAI Agent Adapter وLangGraph Agent Adapter معًا في Crew واحد. diff --git a/docs/v1.15.13/ar/learn/coding-agents.mdx b/docs/v1.15.13/ar/learn/coding-agents.mdx new file mode 100644 index 0000000000..f5f2f18d96 --- /dev/null +++ b/docs/v1.15.13/ar/learn/coding-agents.mdx @@ -0,0 +1,80 @@ +--- +title: Agents البرمجة +description: تعلم كيفية تمكين Agents CrewAI من كتابة وتنفيذ الكود، واستكشف الميزات المتقدمة لوظائف محسّنة. +icon: rectangle-code +mode: "wide" +--- + +## مقدمة + +أصبح لدى CrewAI Agents القدرة القوية على كتابة وتنفيذ الكود، مما يعزز قدراتها في حل المشكلات بشكل كبير. هذه الميزة مفيدة بشكل خاص للمهام التي تتطلب حلولاً حسابية أو برمجية. + +## تمكين تنفيذ الكود + +لتمكين تنفيذ الكود لـ Agent، عيّن معامل `allow_code_execution` إلى `True` عند إنشاء الـ Agent. + +```python Code +from crewai import Agent + +coding_agent = Agent( + role="Senior Python Developer", + goal="Craft well-designed and thought-out code", + backstory="You are a senior Python developer with extensive experience in software architecture and best practices.", + allow_code_execution=True +) +``` + + +لاحظ أن معامل `allow_code_execution` يكون `False` افتراضيًا. + + +## اعتبارات مهمة + +1. **اختيار النموذج**: يُوصى بشدة باستخدام نماذج أكثر قدرة مثل Claude 3.5 Sonnet وGPT-4 عند تمكين تنفيذ الكود. + +2. **معالجة الأخطاء**: تتضمن ميزة تنفيذ الكود معالجة أخطاء. إذا أثار الكود المُنفَّذ استثناءً، سيتلقى الـ Agent رسالة الخطأ ويمكنه محاولة تصحيح الكود. يتحكم معامل `max_retry_limit` (الافتراضي 2) في الحد الأقصى لعدد المحاولات. + +3. **التبعيات**: لاستخدام ميزة تنفيذ الكود، تحتاج لتثبيت حزمة `crewai_tools`. + +## عملية تنفيذ الكود + + + + يحلل الـ Agent المهمة ويحدد أن تنفيذ الكود ضروري. + + + يصيغ كود Python اللازم لحل المشكلة. + + + يُرسَل الكود إلى أداة تنفيذ الكود الداخلية (`CodeInterpreterTool`). + + + يفسر الـ Agent النتيجة ويدمجها في استجابته أو يستخدمها لمزيد من حل المشكلات. + + + +## مثال استخدام + +```python Code +from crewai import Agent, Task, Crew + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants.", + agent=coding_agent +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +result = analysis_crew.kickoff() +print(result) +``` diff --git a/docs/v1.15.13/ar/learn/conditional-tasks.mdx b/docs/v1.15.13/ar/learn/conditional-tasks.mdx new file mode 100644 index 0000000000..818d72aac8 --- /dev/null +++ b/docs/v1.15.13/ar/learn/conditional-tasks.mdx @@ -0,0 +1,14 @@ +--- +title: المهام الشرطية +description: تعلم كيفية استخدام المهام الشرطية في انطلاق crewAI +icon: diagram-subtask +mode: "wide" +--- + +## مقدمة + +تتيح المهام الشرطية في crewAI التكيف الديناميكي لسير العمل بناءً على نتائج المهام السابقة. تمكّن هذه الميزة القوية الـ Crews من اتخاذ قرارات وتنفيذ المهام بشكل انتقائي، مما يعزز مرونة وكفاءة عملياتك المدفوعة بالذكاء الاصطناعي. + +## مثال استخدام + +راجع الملف الإنجليزي الأصلي للحصول على مثال الكود الكامل الذي يوضح استخدام `ConditionalTask` مع دالة شرط `is_data_missing` للتحكم في تنفيذ المهام بناءً على مخرجات المهام السابقة. diff --git a/docs/v1.15.13/ar/learn/create-custom-tools.mdx b/docs/v1.15.13/ar/learn/create-custom-tools.mdx new file mode 100644 index 0000000000..da82f5b457 --- /dev/null +++ b/docs/v1.15.13/ar/learn/create-custom-tools.mdx @@ -0,0 +1,77 @@ +--- +title: إنشاء أدوات مخصصة +description: دليل شامل لصياغة واستخدام وإدارة الأدوات المخصصة ضمن إطار عمل CrewAI، بما في ذلك الوظائف الجديدة ومعالجة الأخطاء. +icon: hammer +mode: "wide" +--- + +## إنشاء واستخدام الأدوات في CrewAI + +يقدم هذا الدليل تعليمات مفصلة لإنشاء أدوات مخصصة لإطار عمل CrewAI وكيفية إدارة واستخدام هذه الأدوات بكفاءة، مع دمج أحدث الوظائف مثل تفويض الأدوات ومعالجة الأخطاء واستدعاء الأدوات الديناميكي. + + + **هل تريد نشر أداتك للمجتمع؟** إذا كنت تبني أداة يمكن أن تفيد الآخرين، اطلع على دليل [نشر أدوات مخصصة](/ar/guides/tools/publish-custom-tools) لتعلم كيفية تعبئة وتوزيع أداتك على PyPI. + + +### وراثة `BaseTool` + +لإنشاء أداة مخصصة، ورث من `BaseTool` وعرّف السمات الضرورية بما في ذلك `args_schema` للتحقق من المدخلات وطريقة `_run`. + +```python Code +from typing import Type +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class MyToolInput(BaseModel): + """Input schema for MyCustomTool.""" + argument: str = Field(..., description="Description of the argument.") + +class MyCustomTool(BaseTool): + name: str = "Name of my tool" + description: str = "What this tool does. It's vital for effective utilization." + args_schema: Type[BaseModel] = MyToolInput + + def _run(self, argument: str) -> str: + return "Tool's result" +``` + +### استخدام مزخرف `tool` + +```python Code +from crewai.tools import tool + +@tool("Tool Name") +def my_simple_tool(question: str) -> str: + """Tool description for clarity.""" + return "Tool output" +``` + +### تعريف دالة تخزين مؤقت للأداة + +```python Code +@tool("Tool with Caching") +def cached_tool(argument: str) -> str: + """Tool functionality description.""" + return "Cacheable result" + +def my_cache_strategy(arguments: dict, result: str) -> bool: + return True if some_condition else False + +cached_tool.cache_function = my_cache_strategy +``` + +### إنشاء أدوات غير متزامنة + +يدعم CrewAI الأدوات غير المتزامنة لعمليات I/O غير المحجوبة. + +```python Code +import aiohttp +from crewai.tools import tool + +@tool("Async Web Fetcher") +async def fetch_webpage(url: str) -> str: + """Fetch content from a webpage asynchronously.""" + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.text() +``` diff --git a/docs/v1.15.13/ar/learn/custom-llm.mdx b/docs/v1.15.13/ar/learn/custom-llm.mdx new file mode 100644 index 0000000000..a02222356c --- /dev/null +++ b/docs/v1.15.13/ar/learn/custom-llm.mdx @@ -0,0 +1,55 @@ +--- +title: تنفيذ LLM مخصص +description: تعلم كيفية إنشاء تنفيذات LLM مخصصة في CrewAI. +icon: code +mode: "wide" +--- + +## نظرة عامة + +يدعم CrewAI تنفيذات LLM المخصصة من خلال فئة `BaseLLM` المجردة. يتيح لك ذلك دمج أي مزود LLM لا يحظى بدعم مدمج في LiteLLM، أو تنفيذ آليات مصادقة مخصصة. + +## بداية سريعة + +راجع الملف الإنجليزي الأصلي للحصول على تنفيذ LLM مخصص كامل يوضح طريقة `call()` المطلوبة والطرق الاختيارية مثل `supports_function_calling()` و`get_context_window_size()`. + +## استخدام LLM المخصص + +```python +from crewai import Agent, Task, Crew + +custom_llm = CustomLLM( + model="my-custom-model", + api_key="your-api-key", + endpoint="https://api.example.com/v1/chat/completions", + temperature=0.7 +) + +agent = Agent( + role="Research Assistant", + goal="Find and analyze information", + backstory="You are a research assistant.", + llm=custom_llm +) + +task = Task( + description="Research the latest developments in AI", + expected_output="A comprehensive summary", + agent=agent +) + +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() +``` + +## الطرق المطلوبة + +### البنّاء: `__init__()` + +**مهم**: يجب استدعاء `super().__init__(model, temperature)` مع المعاملات المطلوبة. + +### الطريقة المجردة: `call()` + +طريقة `call()` هي قلب تنفيذ LLM. يجب أن تقبل الرسائل وتعيد استجابة نصية وتعالج الأدوات واستدعاء الدوال إذا كانت مدعومة. + +يغطي هذا الدليل أساسيات تنفيذ LLM مخصصة في CrewAI. diff --git a/docs/v1.15.13/ar/learn/custom-manager-agent.mdx b/docs/v1.15.13/ar/learn/custom-manager-agent.mdx new file mode 100644 index 0000000000..c20f8a2720 --- /dev/null +++ b/docs/v1.15.13/ar/learn/custom-manager-agent.mdx @@ -0,0 +1,81 @@ +--- +title: Agent مدير مخصص +description: تعلم كيفية تعيين Agent مخصص كمدير في CrewAI، مما يوفر مزيدًا من التحكم في إدارة المهام والتنسيق. +icon: user-shield +mode: "wide" +--- + +# تعيين Agent محدد كمدير في CrewAI + +يتيح CrewAI للمستخدمين تعيين Agent محدد كمدير للـ Crew، مما يوفر مزيدًا من التحكم في إدارة المهام وتنسيقها. + +## استخدام سمة `manager_agent` + +تتيح لك سمة `manager_agent` تعريف Agent مخصص لإدارة الـ Crew. سيشرف هذا الـ Agent على العملية بأكملها لضمان إتمام المهام بكفاءة وبأعلى المعايير. + +```python Code +import os +from crewai import Agent, Task, Crew, Process + +researcher = Agent( + role="Researcher", + goal="Conduct thorough research and analysis on AI and AI agents", + backstory="You're an expert researcher...", + allow_delegation=False, +) + +writer = Agent( + role="Senior Writer", + goal="Create compelling content about AI and AI agents", + backstory="You're a senior writer...", + allow_delegation=False, +) + +task = Task( + description="Generate a list of 5 interesting ideas for an article...", + expected_output="5 bullet points, each with a paragraph and accompanying notes.", +) + +manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager...", + allow_delegation=True, +) + +crew = Crew( + agents=[researcher, writer], + tasks=[task], + manager_agent=manager, + process=Process.hierarchical, +) + +result = crew.kickoff() +``` + +## فوائد Agent المدير المخصص + +- **تحكم محسّن**: تخصيص نهج الإدارة ليناسب الاحتياجات المحددة لمشروعك. +- **تنسيق محسّن**: ضمان تنسيق المهام وإدارتها بكفاءة من قبل Agent ذي خبرة. +- **إدارة قابلة للتخصيص**: تعريف أدوار ومسؤوليات إدارية تتماشى مع أهداف مشروعك. + +## تعيين LLM للمدير + +إذا كنت تستخدم العملية الهرمية ولا تريد تعيين Agent مدير مخصص، يمكنك تحديد نموذج اللغة للمدير: + +```python Code +from crewai import LLM + +manager_llm = LLM(model="gpt-4o") + +crew = Crew( + agents=[researcher, writer], + tasks=[task], + process=Process.hierarchical, + manager_llm=manager_llm +) +``` + + +يجب تعيين إما `manager_agent` أو `manager_llm` عند استخدام العملية الهرمية. + diff --git a/docs/v1.15.13/ar/learn/customizing-agents.mdx b/docs/v1.15.13/ar/learn/customizing-agents.mdx new file mode 100644 index 0000000000..54ce5977cd --- /dev/null +++ b/docs/v1.15.13/ar/learn/customizing-agents.mdx @@ -0,0 +1,67 @@ +--- +title: تخصيص الـ Agents +description: دليل شامل لتخصيص الـ Agents لأدوار ومهام محددة وتخصيصات متقدمة ضمن إطار عمل CrewAI. +icon: user-pen +mode: "wide" +--- + +## السمات القابلة للتخصيص + +يعتمد بناء فريق CrewAI فعّال على القدرة على تخصيص Agents الذكاء الاصطناعي ديناميكيًا لتلبية المتطلبات الفريدة لأي مشروع. يغطي هذا القسم السمات الأساسية التي يمكنك تخصيصها. + +### السمات الرئيسية للتخصيص + +| السمة | الوصف | +|:-----------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Role** | يحدد وظيفة الـ Agent ضمن Crew، مثل 'محلل' أو 'ممثل خدمة عملاء'. | +| **Goal** | يعرّف أهداف الـ Agent، متوافقة مع دوره ومهمة Crew الشاملة. | +| **Backstory** | يوفر عمقًا لشخصية الـ Agent، معززًا الدوافع والتفاعلات ضمن Crew. | +| **Tools** *(اختياري)* | يمثل القدرات أو الطرق التي يستخدمها الـ Agent للمهام. | +| **Cache** *(اختياري)* | يحدد ما إذا كان الـ Agent يجب أن يستخدم ذاكرة مؤقتة لاستخدام الأدوات. | +| **Max RPM** | يعيّن الحد الأقصى للطلبات في الدقيقة (`max_rpm`). | +| **Verbose** *(اختياري)* | يمكّن التسجيل التفصيلي للتصحيح والتحسين. | +| **Allow Delegation** *(اختياري)* | يتحكم في تفويض المهام لـ Agents أخرى، الافتراضي `False`. | +| **Max Iter** *(اختياري)* | يحد الحد الأقصى لعدد التكرارات (`max_iter`) لمهمة، الافتراضي 25. | + +## خيارات تخصيص متقدمة + +### تخصيص نموذج اللغة + +يمكن تخصيص الـ Agents بنماذج لغة محددة (`llm`) ونماذج لغة لاستدعاء الدوال (`function_calling_llm`)، مما يوفر تحكمًا متقدمًا في قدرات المعالجة وصنع القرار. + +## إعدادات الأداء والتصحيح + +- **وضع التفصيل**: يمكّن التسجيل التفصيلي لإجراءات الـ Agent. +- **حد RPM**: يعيّن الحد الأقصى للطلبات في الدقيقة. + +### مثال: تعيين أدوات لـ Agent + +```python Code +import os +from crewai import Agent +from crewai_tools import SerperDevTool + +os.environ["OPENAI_API_KEY"] = "Your Key" +os.environ["SERPER_API_KEY"] = "Your Key" + +search_tool = SerperDevTool() + +agent = Agent( + role='Research Analyst', + goal='Provide up-to-date market analysis', + backstory='An expert analyst with a keen eye for market trends.', + tools=[search_tool], + memory=True, + verbose=True, + max_rpm=None, + max_iter=25, +) +``` + +## التفويض والاستقلالية + +التحكم في قدرة الـ Agent على تفويض المهام أو طرح الأسئلة أمر حيوي لتخصيص استقلاليته وديناميكيات التعاون. افتراضيًا، سمة `allow_delegation` معيّنة على `False`. + +## الخلاصة + +تخصيص الـ Agents في CrewAI من خلال تعيين أدوارهم وأهدافهم وخلفياتهم وأدواتهم، إلى جانب خيارات متقدمة مثل تخصيص نموذج اللغة والذاكرة وإعدادات الأداء وتفضيلات التفويض، يجهّز فريق AI دقيق وقادر جاهز للتحديات المعقدة. diff --git a/docs/v1.15.13/ar/learn/dalle-image-generation.mdx b/docs/v1.15.13/ar/learn/dalle-image-generation.mdx new file mode 100644 index 0000000000..0ab1c3754a --- /dev/null +++ b/docs/v1.15.13/ar/learn/dalle-image-generation.mdx @@ -0,0 +1,52 @@ +--- +title: "إنشاء الصور باستخدام DALL-E" +description: "تعلم كيفية استخدام DALL-E لإنشاء صور مدعومة بالذكاء الاصطناعي في مشاريع CrewAI" +icon: "image" +mode: "wide" +--- + +يدعم CrewAI التكامل مع DALL-E من OpenAI، مما يتيح لـ Agents الذكاء الاصطناعي إنشاء صور كجزء من مهامهم. سيرشدك هذا الدليل عبر كيفية إعداد واستخدام أداة DALL-E في مشاريع CrewAI. + +## المتطلبات المسبقة + +- crewAI مثبّت (أحدث إصدار) +- مفتاح OpenAI API مع وصول إلى DALL-E + +## إعداد أداة DALL-E + + + + ```python + from crewai_tools import DallETool + ``` + + + + ```python + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + tools=[SerperDevTool(), DallETool()], + allow_delegation=False, + verbose=True + ) + ``` + + + +## استخدام أداة DALL-E + +بمجرد إضافة أداة DALL-E إلى Agent، يمكنه إنشاء صور بناءً على مطالبات نصية. ستعيد الأداة رابط URL للصورة المُنشأة. + +## أفضل الممارسات + +1. **كن محددًا في مطالبات إنشاء الصور** للحصول على أفضل النتائج. +2. **ضع في اعتبارك وقت الإنشاء** - قد يستغرق إنشاء الصور بعض الوقت. +3. **اتبع سياسات الاستخدام** - التزم دائمًا بسياسات استخدام OpenAI عند إنشاء الصور. + +## استكشاف الأخطاء + +1. **تحقق من وصول API** - تأكد من أن مفتاح OpenAI API لديه وصول إلى DALL-E. +2. **توافق الإصدارات** - تأكد من استخدام أحدث إصدار من crewAI وcrewai-tools. +3. **تهيئة الأداة** - تحقق من إضافة أداة DALL-E بشكل صحيح لقائمة أدوات الـ Agent. diff --git a/docs/v1.15.13/ar/learn/execution-hooks.mdx b/docs/v1.15.13/ar/learn/execution-hooks.mdx new file mode 100644 index 0000000000..1444eb58dc --- /dev/null +++ b/docs/v1.15.13/ar/learn/execution-hooks.mdx @@ -0,0 +1,86 @@ +--- +title: نظرة عامة على خطافات التنفيذ +description: فهم واستخدام خطافات التنفيذ في CrewAI للتحكم الدقيق في عمليات الـ Agent +mode: "wide" +--- + +توفر خطافات التنفيذ تحكمًا دقيقًا في سلوك وقت تشغيل Agents CrewAI. على عكس خطافات الانطلاق التي تعمل قبل وبعد تنفيذ Crew، تعترض خطافات التنفيذ عمليات محددة أثناء تنفيذ الـ Agent، مما يتيح لك تعديل السلوك وتنفيذ فحوصات أمان وإضافة مراقبة شاملة. + +## أنواع خطافات التنفيذ + +### 1. [خطافات استدعاء LLM](/learn/llm-hooks) + +التحكم ومراقبة تفاعلات نموذج اللغة: +- **قبل استدعاء LLM**: تعديل المطالبات، التحقق من المدخلات، بوابات الموافقة +- **بعد استدعاء LLM**: تحويل الاستجابات، تنقية المخرجات، تحديث سجل المحادثة + +### 2. [خطافات استدعاء الأدوات](/learn/tool-hooks) + +التحكم ومراقبة تنفيذ الأدوات: +- **قبل استدعاء الأداة**: تعديل المدخلات، التحقق من المعاملات، حظر العمليات الخطرة +- **بعد استدعاء الأداة**: تحويل النتائج، تنقية المخرجات، تسجيل تفاصيل التنفيذ + +## طرق تسجيل الخطافات + +### 1. خطافات بالمزخرفات (مُوصى بها) + +```python +from crewai.hooks import before_llm_call, after_llm_call, before_tool_call, after_tool_call + +@before_llm_call +def limit_iterations(context): + if context.iterations > 10: + return False + return None + +@after_llm_call +def sanitize_response(context): + if "API_KEY" in context.response: + return context.response.replace("API_KEY", "[REDACTED]") + return None + +@before_tool_call +def block_dangerous_tools(context): + if context.tool_name == "delete_database": + return False + return None +``` + +### 2. خطافات نطاق Crew + +```python +from crewai import CrewBase +from crewai.project import crew +from crewai.hooks import before_llm_call_crew, after_tool_call_crew + +@CrewBase +class MyProjCrew: + @before_llm_call_crew + def validate_inputs(self, context): + print(f"LLM call in {self.__class__.__name__}") + return None + + @after_tool_call_crew + def log_results(self, context): + print(f"Tool result: {context.tool_result[:50]}...") + return None +``` + +## أفضل الممارسات + +1. **اجعل الخطافات مركّزة** - كل خطاف يجب أن يكون له مسؤولية واحدة واضحة +2. **عالج الأخطاء بلطف** +3. **عدّل السياق في مكانه** +4. **استخدم تلميحات الأنواع** +5. **نظّف في الاختبارات** + +## التوثيق ذو الصلة + +- [خطافات استدعاء LLM](/learn/llm-hooks) +- [خطافات استدعاء الأدوات](/learn/tool-hooks) +- [خطافات قبل وبعد الانطلاق](/learn/before-and-after-kickoff-hooks) +- [التدخل البشري](/learn/human-in-the-loop) + +## الخلاصة + +توفر خطافات التنفيذ تحكمًا قويًا في سلوك وقت تشغيل الـ Agent. استخدمها لتنفيذ حواجز أمان وسير عمل موافقة ومراقبة شاملة ومنطق أعمال مخصص. diff --git a/docs/v1.15.13/ar/learn/force-tool-output-as-result.mdx b/docs/v1.15.13/ar/learn/force-tool-output-as-result.mdx new file mode 100644 index 0000000000..8551e76803 --- /dev/null +++ b/docs/v1.15.13/ar/learn/force-tool-output-as-result.mdx @@ -0,0 +1,45 @@ +--- +title: فرض مخرجات الأداة كنتيجة +description: تعلم كيفية فرض مخرجات الأداة كنتيجة لمهمة Agent في CrewAI. +icon: wrench-simple +mode: "wide" +--- + +## مقدمة + +في CrewAI، يمكنك فرض مخرجات أداة كنتيجة لمهمة Agent. هذه الميزة مفيدة عندما تريد التأكد من التقاط مخرجات الأداة وإعادتها كنتيجة للمهمة، متجنبًا أي تعديل من قبل الـ Agent أثناء تنفيذ المهمة. + +## فرض مخرجات الأداة كنتيجة + +لفرض مخرجات الأداة كنتيجة لمهمة Agent، تحتاج لتعيين معامل `result_as_answer` إلى `True` عند إضافة أداة إلى الـ Agent. + +```python Code +from crewai.agent import Agent +from my_tool import MyCustomTool + +coding_agent = Agent( + role="Data Scientist", + goal="Produce amazing reports on AI", + backstory="You work with data and AI", + tools=[MyCustomTool(result_as_answer=True)], + ) + +task_result = coding_agent.execute_task(task) +``` + +## سير العمل أثناء التنفيذ + + + + ينفذ الـ Agent المهمة باستخدام الأداة المقدمة. + + + تولّد الأداة المخرجات التي تُلتقط كنتيجة للمهمة. + + + قد يتأمل الـ Agent ويستخلص دروسًا من الأداة لكن لا يعدّل المخرجات. + + + تُعاد مخرجات الأداة كنتيجة للمهمة دون أي تعديلات. + + diff --git a/docs/v1.15.13/ar/learn/hierarchical-process.mdx b/docs/v1.15.13/ar/learn/hierarchical-process.mdx new file mode 100644 index 0000000000..af783bdcd2 --- /dev/null +++ b/docs/v1.15.13/ar/learn/hierarchical-process.mdx @@ -0,0 +1,76 @@ +--- +title: العملية الهرمية +description: دليل شامل لفهم وتطبيق العملية الهرمية ضمن مشاريع CrewAI. +icon: sitemap +mode: "wide" +--- + +## مقدمة + +تقدم العملية الهرمية في CrewAI نهجًا منظمًا لإدارة المهام، محاكاةً للتسلسلات الهرمية التنظيمية التقليدية للتفويض والتنفيذ الفعّال للمهام. + + + صُممت العملية الهرمية للاستفادة من نماذج متقدمة مثل GPT-4، مما يحسّن استخدام الرموز المميزة مع التعامل مع المهام المعقدة بكفاءة أكبر. + + +## نظرة عامة على العملية الهرمية + +افتراضيًا، تُدار المهام في CrewAI من خلال عملية متسلسلة. لكن اعتماد نهج هرمي يتيح تسلسلاً واضحًا في إدارة المهام، حيث يقوم Agent 'مدير' بتنسيق سير العمل وتفويض المهام والتحقق من النتائج. + +### الميزات الرئيسية + +- **تفويض المهام**: Agent مدير يوزّع المهام بين أعضاء Crew بناءً على أدوارهم وقدراتهم. +- **التحقق من النتائج**: يقيّم المدير النتائج لضمان استيفائها للمعايير المطلوبة. +- **سير عمل فعّال**: يحاكي الهياكل المؤسسية مقدمًا نهجًا منظمًا لإدارة المهام. + +## تنفيذ العملية الهرمية + +```python Code +from crewai import Crew, Process, Agent + +researcher = Agent( + role='Researcher', + goal='Conduct in-depth analysis', + backstory='Experienced data analyst with a knack for uncovering hidden trends.', +) +writer = Agent( + role='Writer', + goal='Create engaging content', + backstory='Creative writer passionate about storytelling in technical domains.', +) + +project_crew = Crew( + tasks=[...], + agents=[researcher, writer], + manager_llm="gpt-4o", + process=Process.hierarchical, + planning=True, +) +``` + +### استخدام Agent مدير مخصص + +```python +manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager...", + allow_delegation=True, +) + +project_crew = Crew( + tasks=[...], + agents=[researcher, writer], + manager_agent=manager, + process=Process.hierarchical, + planning=True, +) +``` + + + لمزيد من التفاصيل حول إنشاء وتخصيص Agent مدير، اطلع على [توثيق Agent المدير المخصص](/ar/learn/custom-manager-agent). + + +## الخلاصة + +اعتماد العملية الهرمية في CrewAI مع التهيئات الصحيحة وفهم قدرات النظام يسهّل نهجًا منظمًا وفعّالاً لإدارة المشاريع. استفد من الميزات المتقدمة والتخصيصات لتكييف سير العمل لاحتياجاتك المحددة. diff --git a/docs/v1.15.13/ar/learn/human-feedback-in-flows.mdx b/docs/v1.15.13/ar/learn/human-feedback-in-flows.mdx new file mode 100644 index 0000000000..11aeffcf6a --- /dev/null +++ b/docs/v1.15.13/ar/learn/human-feedback-in-flows.mdx @@ -0,0 +1,98 @@ +--- +title: التغذية الراجعة البشرية في Flows +description: تعلم كيفية دمج التغذية الراجعة البشرية مباشرة في CrewAI Flows باستخدام مزخرف @human_feedback +icon: user-check +mode: "wide" +--- + +## نظرة عامة + + +يتطلب مزخرف `@human_feedback` إصدار **CrewAI 1.8.0 أو أحدث**. تأكد من تحديث تثبيتك قبل استخدام هذه الميزة. + + +يمكّن مزخرف `@human_feedback` سير العمل البشري في الحلقة (HITL) مباشرة ضمن CrewAI Flows. يتيح لك إيقاف تنفيذ Flow مؤقتًا وعرض المخرجات لإنسان للمراجعة وجمع تعليقاته واختياريًا التوجيه إلى مستمعين مختلفين بناءً على نتيجة التعليقات. + +هذا مفيد بشكل خاص لـ: + +- **ضمان الجودة**: مراجعة المحتوى المُنشأ بالذكاء الاصطناعي قبل استخدامه +- **بوابات القرار**: السماح للبشر باتخاذ قرارات حرجة في سير العمل الآلي +- **سير عمل الموافقة**: تنفيذ أنماط الموافقة/الرفض/المراجعة +- **التحسين التفاعلي**: جمع التعليقات لتحسين المخرجات تكراريًا + +## بداية سريعة + +```python Code +from crewai.flow.flow import Flow, start, listen +from crewai.flow.human_feedback import human_feedback + +class SimpleReviewFlow(Flow): + @start() + @human_feedback(message="Please review this content:") + def generate_content(self): + return "This is AI-generated content that needs review." + + @listen(generate_content) + def process_feedback(self, result): + print(f"Content: {result.output}") + print(f"Human said: {result.feedback}") + +flow = SimpleReviewFlow() +flow.kickoff() +``` + +## التوجيه مع emit + +عند تحديد `emit`، يصبح المزخرف موجّهًا. يُفسَّر التعليق البشري الحر بواسطة LLM ويُختزل إلى إحدى النتائج المحددة: + +```python Code +from crewai.flow.flow import Flow, start, listen, or_ +from crewai.flow.human_feedback import human_feedback + +class ReviewFlow(Flow): + @start() + def generate_content(self): + return "Draft blog post content here..." + + @human_feedback( + message="Do you approve this content for publication?", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + @listen(or_("generate_content", "needs_revision")) + def review_content(self): + return "Draft blog post content here..." + + @listen("approved") + def publish(self, result): + print(f"Publishing! User said: {result.feedback}") + + @listen("rejected") + def discard(self, result): + print(f"Discarding. Reason: {result.feedback}") +``` + +## التعلم من التغذية الراجعة + +معامل `learn=True` يمكّن حلقة تغذية راجعة بين المراجعين البشريين ونظام الذاكرة. عند تمكينه، يحسّن النظام مخرجاته تدريجيًا بالتعلم من التصحيحات البشرية السابقة. + +## أفضل الممارسات + +1. **اكتب رسائل طلب واضحة** +2. **اختر نتائج ذات معنى** +3. **وفّر دائمًا نتيجة افتراضية** +4. **استخدم سجل التعليقات لمسارات التدقيق** + +## التغذية الراجعة البشرية غير المتزامنة (غير محجوبة) + +استخدم معامل `provider` لتحديد استراتيجية جمع تعليقات مخصصة تتكامل مع أنظمة خارجية مثل Slack والبريد الإلكتروني وWebhooks وواجهات API. + +## التوثيق ذو الصلة + +- [نظرة عامة على Flows](/ar/concepts/flows) +- [إدارة حالة Flow](/ar/guides/flows/mastering-flow-state) +- [حفظ Flow](/ar/concepts/flows#persistence) +- [التوجيه مع @router](/ar/concepts/flows#router) +- [إدخال بشري عند التنفيذ](/ar/learn/human-input-on-execution) +- [الذاكرة](/ar/concepts/memory) diff --git a/docs/v1.15.13/ar/learn/human-in-the-loop.mdx b/docs/v1.15.13/ar/learn/human-in-the-loop.mdx new file mode 100644 index 0000000000..1ad91c95f1 --- /dev/null +++ b/docs/v1.15.13/ar/learn/human-in-the-loop.mdx @@ -0,0 +1,80 @@ +--- +title: "سير عمل التدخل البشري (HITL)" +description: "تعلم كيفية تنفيذ سير عمل التدخل البشري في CrewAI لتعزيز صنع القرار" +icon: "user-check" +mode: "wide" +--- + +التدخل البشري (HITL) هو نهج قوي يجمع بين الذكاء الاصطناعي والخبرة البشرية لتعزيز صنع القرار وتحسين نتائج المهام. يوفر CrewAI طرقًا متعددة لتنفيذ HITL حسب احتياجاتك. + +## اختيار نهج HITL + +يوفر CrewAI نهجين رئيسيين لتنفيذ سير عمل التدخل البشري: + +| النهج | الأنسب لـ | التكامل | الإصدار | +|----------|----------|-------------|---------| +| **قائم على Flow** (مزخرف `@human_feedback`) | التطوير المحلي، المراجعة عبر وحدة التحكم، سير العمل المتزامن | [التغذية الراجعة البشرية في Flows](/ar/learn/human-feedback-in-flows) | **1.8.0+** | +| **قائم على Webhook** (المؤسسات) | نشر الإنتاج، سير العمل غير المتزامن، التكاملات الخارجية (Slack، Teams، إلخ) | هذا الدليل | - | + + +إذا كنت تبني Flows وتريد إضافة خطوات مراجعة بشرية مع توجيه بناءً على التعليقات، اطلع على دليل [التغذية الراجعة البشرية في Flows](/ar/learn/human-feedback-in-flows) لمزخرف `@human_feedback`. + + +## إعداد سير عمل HITL القائم على Webhook + + + + أعدّ مهمتك مع تمكين إدخال بشري. + + + + عند تشغيل Crew، أدرج عنوان Webhook URL لإدخال بشري. + + + + بمجرد إتمام Crew المهمة التي تتطلب إدخالاً بشريًا، ستتلقى إشعار Webhook. + + + + سيتوقف النظام في حالة `Pending Human Input`. راجع مخرجات المهمة بعناية. + + + + استدعِ نقطة نهاية الاستئناف لـ Crew. + + + **مهم: يجب توفير عناوين Webhook URL مرة أخرى**: + يجب توفير نفس عناوين Webhook URL في استدعاء الاستئناف التي استخدمتها في استدعاء الانطلاق. + + + + + إذا قدمت تعليقات سلبية، سيعيد Crew محاولة المهمة مع سياق إضافي من تعليقاتك. + + + + عند إرسال تعليقات إيجابية، سيستمر التنفيذ إلى الخطوات التالية. + + + +## أفضل الممارسات + +- **كن محددًا**: قدم تعليقات واضحة وقابلة للتنفيذ +- **ابقَ ذا صلة**: أدرج فقط معلومات تساعد في تحسين تنفيذ المهمة +- **كن في الوقت المناسب**: استجب لمطالبات HITL بسرعة لتجنب تأخير سير العمل +- **راجع بعناية**: تحقق من تعليقاتك قبل الإرسال لضمان الدقة + +## حالات الاستخدام الشائعة + +سير عمل HITL مفيدة بشكل خاص لـ: +- ضمان الجودة والتحقق +- سيناريوهات صنع القرار المعقدة +- العمليات الحساسة أو عالية المخاطر +- المهام الإبداعية التي تتطلب حكمًا بشريًا +- مراجعات الامتثال والتنظيم + +## ميزات المؤسسات + + + يوفر CrewAI Enterprise نظام إدارة HITL شامل لـ Flows مع مراجعة داخل المنصة وتعيين المستجيبين والأذونات وسياسات التصعيد وإدارة SLA والتوجيه الديناميكي والتحليلات الكاملة. [تعلم المزيد](https://docs-platform.crewai.com/platform/ar/features/flow-hitl-management) + diff --git a/docs/v1.15.13/ar/learn/human-input-on-execution.mdx b/docs/v1.15.13/ar/learn/human-input-on-execution.mdx new file mode 100644 index 0000000000..756f170a0e --- /dev/null +++ b/docs/v1.15.13/ar/learn/human-input-on-execution.mdx @@ -0,0 +1,99 @@ +--- +title: الإدخال البشري أثناء التنفيذ +description: دمج CrewAI مع الإدخال البشري أثناء التنفيذ في عمليات اتخاذ القرارات المعقدة والاستفادة الكاملة من إمكانيات خصائص وأدوات الوكيل. +icon: user-plus +mode: "wide" +--- + +## الإدخال البشري في تنفيذ الوكيل + +يُعد الإدخال البشري أمراً بالغ الأهمية في العديد من سيناريوهات تنفيذ الوكلاء، حيث يسمح للوكلاء بطلب معلومات إضافية أو توضيحات عند الضرورة. +هذه الميزة مفيدة بشكل خاص في عمليات اتخاذ القرارات المعقدة أو عندما يحتاج الوكلاء إلى مزيد من التفاصيل لإكمال مهمة بفعالية. + +## استخدام الإدخال البشري مع CrewAI + +لدمج الإدخال البشري في تنفيذ الوكيل، قم بتعيين علامة `human_input` في تعريف المهمة. عند تفعيلها، يطلب الوكيل من المستخدم إدخالاً قبل تقديم إجابته النهائية. +يمكن أن يوفر هذا الإدخال سياقاً إضافياً، أو يوضح الغموض، أو يتحقق من مخرجات الوكيل. + +### مثال: + +```shell +pip install crewai +``` + +```python Code +import os +from crewai import Agent, Task, Crew +from crewai_tools import SerperDevTool + +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key +os.environ["OPENAI_API_KEY"] = "Your Key" + +# Loading Tools +search_tool = SerperDevTool() + +# Define your agents with roles, goals, tools, and additional attributes +researcher = Agent( + role='Senior Research Analyst', + goal='Uncover cutting-edge developments in AI and data science', + backstory=( + "You are a Senior Research Analyst at a leading tech think tank. " + "Your expertise lies in identifying emerging trends and technologies in AI and data science. " + "You have a knack for dissecting complex data and presenting actionable insights." + ), + verbose=True, + allow_delegation=False, + tools=[search_tool] +) +writer = Agent( + role='Tech Content Strategist', + goal='Craft compelling content on tech advancements', + backstory=( + "You are a renowned Tech Content Strategist, known for your insightful and engaging articles on technology and innovation. " + "With a deep understanding of the tech industry, you transform complex concepts into compelling narratives." + ), + verbose=True, + allow_delegation=True, + tools=[search_tool], + cache=False, # Disable cache for this agent +) + +# Create tasks for your agents +task1 = Task( + description=( + "Conduct a comprehensive analysis of the latest advancements in AI in 2025. " + "Identify key trends, breakthrough technologies, and potential industry impacts. " + "Compile your findings in a detailed report. " + "Make sure to check with a human if the draft is good before finalizing your answer." + ), + expected_output='A comprehensive full report on the latest AI advancements in 2025, leave nothing out', + agent=researcher, + human_input=True +) + +task2 = Task( + description=( + "Using the insights from the researcher\'s report, develop an engaging blog post that highlights the most significant AI advancements. " + "Your post should be informative yet accessible, catering to a tech-savvy audience. " + "Aim for a narrative that captures the essence of these breakthroughs and their implications for the future." + ), + expected_output='A compelling 3 paragraphs blog post formatted as markdown about the latest AI advancements in 2025', + agent=writer, + human_input=True +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[researcher, writer], + tasks=[task1, task2], + verbose=True, + memory=True, + planning=True # Enable planning feature for the crew +) + +# Get your crew to work! +result = crew.kickoff() + +print("######################") +print(result) +``` diff --git a/docs/v1.15.13/ar/learn/kickoff-async.mdx b/docs/v1.15.13/ar/learn/kickoff-async.mdx new file mode 100644 index 0000000000..dfe446ba03 --- /dev/null +++ b/docs/v1.15.13/ar/learn/kickoff-async.mdx @@ -0,0 +1,306 @@ +--- +title: تشغيل الطاقم بشكل غير متزامن +description: تشغيل الطاقم بشكل غير متزامن +icon: rocket-launch +mode: "wide" +--- + +## مقدمة + +يوفر CrewAI القدرة على تشغيل طاقم بشكل غير متزامن، مما يتيح لك بدء تنفيذ الطاقم بطريقة غير حاجبة. +هذه الميزة مفيدة بشكل خاص عندما تريد تشغيل عدة أطقم بشكل متزامن أو عندما تحتاج إلى أداء مهام أخرى أثناء تنفيذ الطاقم. + +يقدم CrewAI نهجين للتنفيذ غير المتزامن: + +| الطريقة | النوع | الوصف | +|--------|------|-------------| +| `akickoff()` | غير متزامن أصلي | async/await أصلي عبر سلسلة التنفيذ بالكامل | +| `kickoff_async()` | قائم على الخيوط | يغلف التنفيذ المتزامن في `asyncio.to_thread` | + + +لأحمال العمل عالية التزامن، يُوصى باستخدام `akickoff()` لأنه يستخدم async أصلي لتنفيذ المهام وعمليات الذاكرة واسترجاع المعرفة. + + +## التنفيذ غير المتزامن الأصلي مع `akickoff()` + +توفر طريقة `akickoff()` تنفيذاً غير متزامن أصلياً حقيقياً، باستخدام async/await عبر سلسلة التنفيذ بالكامل بما في ذلك تنفيذ المهام وعمليات الذاكرة واستعلامات المعرفة. + +### توقيع الطريقة + +```python Code +async def akickoff(self, inputs: dict) -> CrewOutput: +``` + +### المعاملات + +- `inputs` (dict): قاموس يحتوي على بيانات الإدخال المطلوبة للمهام. + +### القيمة المُرجعة + +- `CrewOutput`: كائن يمثل نتيجة تنفيذ الطاقم. + +### مثال: تنفيذ طاقم غير متزامن أصلي + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +# Create an agent +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +# Create a crew +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +# Native async execution +async def main(): + result = await analysis_crew.akickoff(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + +asyncio.run(main()) +``` + +### مثال: عدة أطقم غير متزامنة أصلية + +تشغيل عدة أطقم بشكل متزامن باستخدام `asyncio.gather()` مع async أصلي: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +task_1 = Task( + description="Analyze the first dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +task_2 = Task( + description="Analyze the second dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +crew_1 = Crew(agents=[coding_agent], tasks=[task_1]) +crew_2 = Crew(agents=[coding_agent], tasks=[task_2]) + +async def main(): + results = await asyncio.gather( + crew_1.akickoff(inputs={"ages": [25, 30, 35, 40, 45]}), + crew_2.akickoff(inputs={"ages": [20, 22, 24, 28, 30]}) + ) + + for i, result in enumerate(results, 1): + print(f"Crew {i} Result:", result) + +asyncio.run(main()) +``` + +### مثال: async أصلي لمدخلات متعددة + +استخدم `akickoff_for_each()` لتنفيذ طاقمك على مدخلات متعددة بشكل متزامن مع async أصلي: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +async def main(): + datasets = [ + {"ages": [25, 30, 35, 40, 45]}, + {"ages": [20, 22, 24, 28, 30]}, + {"ages": [30, 35, 40, 45, 50]} + ] + + results = await analysis_crew.akickoff_for_each(datasets) + + for i, result in enumerate(results, 1): + print(f"Dataset {i} Result:", result) + +asyncio.run(main()) +``` + +## التنفيذ غير المتزامن القائم على الخيوط مع `kickoff_async()` + +توفر طريقة `kickoff_async()` تنفيذاً غير متزامن عن طريق تغليف `kickoff()` المتزامن في خيط. هذا مفيد للتكامل البسيط مع async أو للتوافق مع الإصدارات السابقة. + +### توقيع الطريقة + +```python Code +async def kickoff_async(self, inputs: dict) -> CrewOutput: +``` + +### المعاملات + +- `inputs` (dict): قاموس يحتوي على بيانات الإدخال المطلوبة للمهام. + +### القيمة المُرجعة + +- `CrewOutput`: كائن يمثل نتيجة تنفيذ الطاقم. + +### مثال: تنفيذ غير متزامن قائم على الخيوط + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +async def async_crew_execution(): + result = await analysis_crew.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + +asyncio.run(async_crew_execution()) +``` + +### مثال: عدة أطقم غير متزامنة قائمة على الخيوط + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +task_1 = Task( + description="Analyze the first dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +task_2 = Task( + description="Analyze the second dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +crew_1 = Crew(agents=[coding_agent], tasks=[task_1]) +crew_2 = Crew(agents=[coding_agent], tasks=[task_2]) + +async def async_multiple_crews(): + result_1 = crew_1.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + result_2 = crew_2.kickoff_async(inputs={"ages": [20, 22, 24, 28, 30]}) + + results = await asyncio.gather(result_1, result_2) + + for i, result in enumerate(results, 1): + print(f"Crew {i} Result:", result) + +asyncio.run(async_multiple_crews()) +``` + +## البث غير المتزامن + +تدعم كلتا الطريقتين غير المتزامنتين البث عند تعيين `stream=True` على الطاقم: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +agent = Agent( + role="Researcher", + goal="Research and summarize topics", + backstory="You are an expert researcher." +) + +task = Task( + description="Research the topic: {topic}", + agent=agent, + expected_output="A comprehensive summary of the topic." +) + +crew = Crew( + agents=[agent], + tasks=[task], + stream=True # Enable streaming +) + +async def main(): + streaming_output = await crew.akickoff(inputs={"topic": "AI trends in 2024"}) + + # Async iteration over streaming chunks + async for chunk in streaming_output: + print(f"Chunk: {chunk.content}") + + # Access final result after streaming completes + result = streaming_output.result + print(f"Final result: {result.raw}") + +asyncio.run(main()) +``` + +## حالات الاستخدام المحتملة + +- **توليد المحتوى بالتوازي**: تشغيل عدة أطقم مستقلة بشكل غير متزامن، كل منها مسؤول عن توليد محتوى حول مواضيع مختلفة. على سبيل المثال، قد يبحث طاقم ويصوغ مقالاً عن اتجاهات الذكاء الاصطناعي، بينما يولد طاقم آخر منشورات وسائل التواصل الاجتماعي حول إطلاق منتج جديد. + +- **مهام أبحاث السوق المتزامنة**: إطلاق عدة أطقم بشكل غير متزامن لإجراء أبحاث السوق بالتوازي. قد يحلل طاقم اتجاهات الصناعة، بينما يفحص آخر استراتيجيات المنافسين، ويقيّم ثالث مشاعر المستهلكين. + +- **وحدات تخطيط السفر المستقلة**: تنفيذ أطقم منفصلة للتخطيط المستقل لجوانب مختلفة من رحلة. قد يتعامل طاقم مع خيارات الرحلات الجوية، وآخر مع الإقامة، وثالث يخطط للأنشطة. + +## الاختيار بين `akickoff()` و `kickoff_async()` + +| الميزة | `akickoff()` | `kickoff_async()` | +|---------|--------------|-------------------| +| نموذج التنفيذ | async/await أصلي | غلاف قائم على الخيوط | +| تنفيذ المهام | غير متزامن مع `aexecute_sync()` | متزامن في مجمع الخيوط | +| عمليات الذاكرة | غير متزامنة | متزامنة في مجمع الخيوط | +| استرجاع المعرفة | غير متزامن | متزامن في مجمع الخيوط | +| الأفضل لـ | أحمال العمل عالية التزامن والمرتبطة بالإدخال/الإخراج | التكامل البسيط مع async | +| دعم البث | نعم | نعم | diff --git a/docs/v1.15.13/ar/learn/kickoff-for-each.mdx b/docs/v1.15.13/ar/learn/kickoff-for-each.mdx new file mode 100644 index 0000000000..a827799b01 --- /dev/null +++ b/docs/v1.15.13/ar/learn/kickoff-for-each.mdx @@ -0,0 +1,54 @@ +--- +title: تشغيل الطاقم لكل عنصر +description: تشغيل الطاقم لكل عنصر في قائمة +icon: at +mode: "wide" +--- + +## مقدمة + +يوفر CrewAI القدرة على تشغيل طاقم لكل عنصر في قائمة، مما يتيح لك تنفيذ الطاقم لكل عنصر في القائمة. +هذه الميزة مفيدة بشكل خاص عندما تحتاج إلى تنفيذ نفس مجموعة المهام لعناصر متعددة. + +## تشغيل طاقم لكل عنصر + +لتشغيل طاقم لكل عنصر في قائمة، استخدم طريقة `kickoff_for_each()`. +تنفذ هذه الطريقة الطاقم لكل عنصر في القائمة، مما يتيح لك معالجة عناصر متعددة بكفاءة. + +إليك مثالاً على كيفية تشغيل طاقم لكل عنصر في قائمة: + +```python Code +from crewai import Crew, Agent, Task + +# Create an agent with code execution enabled +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task that requires code execution +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age calculated from the dataset" +) + +# Create a crew and add the task +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task], + verbose=True, + memory=False +) + +datasets = [ + { "ages": [25, 30, 35, 40, 45] }, + { "ages": [20, 25, 30, 35, 40] }, + { "ages": [30, 35, 40, 45, 50] } +] + +# Execute the crew +result = analysis_crew.kickoff_for_each(inputs=datasets) +``` diff --git a/docs/v1.15.13/ar/learn/litellm-removal-guide.mdx b/docs/v1.15.13/ar/learn/litellm-removal-guide.mdx new file mode 100644 index 0000000000..b0e81d9199 --- /dev/null +++ b/docs/v1.15.13/ar/learn/litellm-removal-guide.mdx @@ -0,0 +1,358 @@ +--- +title: استخدام CrewAI بدون LiteLLM +description: كيفية استخدام CrewAI مع التكاملات الأصلية للمزودين وإزالة اعتمادية LiteLLM من مشروعك. +icon: shield-check +mode: "wide" +--- + +## نظرة عامة + +يدعم CrewAI مسارين للاتصال بمزودي LLM: + +1. **التكاملات الأصلية** — اتصالات SDK مباشرة مع OpenAI وAnthropic وGoogle Gemini وAzure OpenAI وAWS Bedrock +2. **LiteLLM كاحتياط** — طبقة ترجمة تدعم أكثر من 100 مزود إضافي + +يشرح هذا الدليل كيفية استخدام CrewAI حصرياً مع التكاملات الأصلية للمزودين، مع إزالة أي اعتمادية على LiteLLM. + + + تم عزل حزمة `litellm` على PyPI بسبب حادث أمني/موثوقية. إذا كنت تعتمد على مزودين يحتاجون LiteLLM، يجب عليك الانتقال إلى التكاملات الأصلية. توفر لك تكاملات CrewAI الأصلية الوظائف الكاملة بدون LiteLLM. + + +## لماذا إزالة LiteLLM؟ + +- **تقليل سطح الاعتماديات** — حزم أقل تعني مخاطر أقل محتملة في سلسلة التوريد +- **أداء أفضل** — تتواصل حزم SDK الأصلية مباشرة مع واجهات برمجة تطبيقات المزودين، مما يلغي طبقة الترجمة +- **تصحيح أخطاء أبسط** — طبقة تجريد واحدة أقل بين كودك والمزود +- **حجم تثبيت أصغر** — يجلب LiteLLM العديد من الاعتماديات العابرة + +## المزودون الأصليون (لا يحتاجون LiteLLM) + +هؤلاء المزودون يستخدمون حزم SDK الخاصة بهم ويعملون بدون تثبيت LiteLLM: + + + + GPT-4o، GPT-4o-mini، o1، o3-mini، والمزيد. + ```bash + uv add "crewai[openai]" + ``` + + + Claude Sonnet، Claude Haiku، والمزيد. + ```bash + uv add "crewai[anthropic]" + ``` + + + Gemini 2.0 Flash، Gemini 2.0 Pro، والمزيد. + ```bash + uv add "crewai[gemini]" + ``` + + + نماذج OpenAI المستضافة على Azure. + ```bash + uv add "crewai[azure]" + ``` + + + Claude، Llama، Titan، والمزيد عبر AWS. + ```bash + uv add "crewai[bedrock]" + ``` + + + + + إذا كنت تستخدم المزودين الأصليين فقط، فلن تحتاج **أبداً** لتثبيت `crewai[litellm]`. حزمة `crewai` الأساسية بالإضافة إلى الإضافة الخاصة بالمزود الذي اخترته هي كل ما تحتاجه. + + +## كيفية التحقق مما إذا كنت تستخدم LiteLLM + +### تحقق من سلاسل النماذج الخاصة بك + +إذا كان كودك يستخدم بادئات النماذج هذه، فأنت تمرر عبر LiteLLM: + +| البادئة | المزود | يستخدم LiteLLM؟ | +|--------|----------|---------------| +| `ollama/` | Ollama | ✅ نعم | +| `groq/` | Groq | ✅ نعم | +| `together_ai/` | Together AI | ✅ نعم | +| `mistral/` | Mistral | ✅ نعم | +| `cohere/` | Cohere | ✅ نعم | +| `huggingface/` | Hugging Face | ✅ نعم | +| `openai/` | OpenAI | ❌ أصلي | +| `anthropic/` | Anthropic | ❌ أصلي | +| `gemini/` | Google Gemini | ❌ أصلي | +| `azure/` | Azure OpenAI | ❌ أصلي | +| `bedrock/` | AWS Bedrock | ❌ أصلي | + +### تحقق مما إذا كان LiteLLM مثبتاً + +```bash +# Using pip +pip show litellm + +# Using uv +uv pip show litellm +``` + +إذا أرجع الأمر معلومات الحزمة، فإن LiteLLM مثبت في بيئتك. + +### تحقق من اعتمادياتك + +انظر إلى ملف `pyproject.toml` الخاص بك بحثاً عن `crewai[litellm]`: + +```toml +# If you see this, you have LiteLLM as a dependency +dependencies = [ + "crewai[litellm]>=0.100.0", # ← Uses LiteLLM +] + +# Change to a native provider extra instead +dependencies = [ + "crewai[openai]>=0.100.0", # ← Native, no LiteLLM +] +``` + +## دليل الانتقال + +### الخطوة 1: حدد مزودك الحالي + +ابحث عن جميع استدعاءات `LLM()` وسلاسل النماذج في كودك: + +```bash +# Search your codebase for LLM model strings +grep -r "LLM(" --include="*.py" . +grep -r "llm=" --include="*.yaml" . +grep -r "llm:" --include="*.yaml" . +``` + +### الخطوة 2: انتقل إلى مزود أصلي + + + + ```python + from crewai import LLM + + # Before (LiteLLM): + # llm = LLM(model="groq/llama-3.1-70b") + + # After (Native): + llm = LLM(model="openai/gpt-4o") + ``` + + ```bash + # Install + uv add "crewai[openai]" + + # Set your API key + export OPENAI_API_KEY="sk-..." + ``` + + + ```python + from crewai import LLM + + # Before (LiteLLM): + # llm = LLM(model="together_ai/meta-llama/Meta-Llama-3.1-70B") + + # After (Native): + llm = LLM(model="anthropic/claude-sonnet-4-20250514") + ``` + + ```bash + # Install + uv add "crewai[anthropic]" + + # Set your API key + export ANTHROPIC_API_KEY="sk-ant-..." + ``` + + + ```python + from crewai import LLM + + # Before (LiteLLM): + # llm = LLM(model="mistral/mistral-large-latest") + + # After (Native): + llm = LLM(model="gemini/gemini-2.0-flash") + ``` + + ```bash + # Install + uv add "crewai[gemini]" + + # Set your API key + export GEMINI_API_KEY="..." + ``` + + + ```python + from crewai import LLM + + # After (Native): + llm = LLM( + model="azure/your-deployment-name", + api_key="your-azure-api-key", + base_url="https://your-resource.openai.azure.com", + api_version="2024-06-01" + ) + ``` + + ```bash + # Install + uv add "crewai[azure]" + ``` + + + ```python + from crewai import LLM + + # After (Native): + llm = LLM( + model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0", + aws_region_name="us-east-1" + ) + ``` + + ```bash + # Install + uv add "crewai[bedrock]" + + # Configure AWS credentials + export AWS_ACCESS_KEY_ID="..." + export AWS_SECRET_ACCESS_KEY="..." + export AWS_DEFAULT_REGION="us-east-1" + ``` + + + +### الخطوة 3: الاحتفاظ بـ Ollama بدون LiteLLM + +إذا كنت تستخدم Ollama وتريد الاستمرار في استخدامه، يمكنك الاتصال عبر واجهة برمجة تطبيقات Ollama المتوافقة مع OpenAI: + +```python +from crewai import LLM + +# Before (LiteLLM): +# llm = LLM(model="ollama/llama3") + +# After (OpenAI-compatible mode, no LiteLLM needed): +llm = LLM( + model="openai/llama3", + base_url="http://localhost:11434/v1", + api_key="ollama" # Ollama doesn't require a real API key +) +``` + + + العديد من خوادم الاستدلال المحلية (Ollama، vLLM، LM Studio، llama.cpp) توفر واجهة برمجة تطبيقات متوافقة مع OpenAI. يمكنك استخدام بادئة `openai/` مع `base_url` مخصص للاتصال بأي منها بشكل أصلي. + + +### الخطوة 4: تحديث إعدادات YAML + +```yaml +# Before (LiteLLM providers): +researcher: + role: Research Specialist + goal: Conduct research + backstory: A dedicated researcher + llm: groq/llama-3.1-70b # ← LiteLLM + +# After (Native provider): +researcher: + role: Research Specialist + goal: Conduct research + backstory: A dedicated researcher + llm: openai/gpt-4o # ← Native +``` + +### الخطوة 5: إزالة LiteLLM + +بمجرد انتقال جميع مراجع النماذج الخاصة بك: + +```bash +# Remove litellm from your project +uv remove litellm + +# Or if using pip +pip uninstall litellm + +# Update your pyproject.toml: change crewai[litellm] to your provider extra +# e.g., crewai[openai], crewai[anthropic], crewai[gemini] +``` + +### الخطوة 6: التحقق + +شغّل مشروعك وتأكد من أن كل شيء يعمل: + +```bash +# Run your crew +crewai run + +# Or run your tests +uv run pytest +``` + +## مرجع سريع: خريطة سلاسل النماذج + +فيما يلي مسارات الانتقال الشائعة من المزودين المعتمدين على LiteLLM إلى المزودين الأصليين: + +```python +from crewai import LLM + +# ─── LiteLLM providers → Native alternatives ──────────────────── + +# Groq → OpenAI or Anthropic +# llm = LLM(model="groq/llama-3.1-70b") +llm = LLM(model="openai/gpt-4o-mini") # Fast & affordable +llm = LLM(model="anthropic/claude-haiku-3-5") # Fast & affordable + +# Together AI → OpenAI or Gemini +# llm = LLM(model="together_ai/meta-llama/Meta-Llama-3.1-70B") +llm = LLM(model="openai/gpt-4o") # High quality +llm = LLM(model="gemini/gemini-2.0-flash") # Fast & capable + +# Mistral → Anthropic or OpenAI +# llm = LLM(model="mistral/mistral-large-latest") +llm = LLM(model="anthropic/claude-sonnet-4-20250514") # High quality + +# Ollama → OpenAI-compatible (keep using local models) +# llm = LLM(model="ollama/llama3") +llm = LLM( + model="openai/llama3", + base_url="http://localhost:11434/v1", + api_key="ollama" +) +``` + +## الأسئلة الشائعة + + + + لا، إذا كنت تستخدم أحد المزودين الخمسة المدعومين أصلياً (OpenAI، Anthropic، Gemini، Azure، Bedrock). تدعم هذه التكاملات الأصلية جميع ميزات CrewAI بما في ذلك البث واستدعاء الأدوات والمخرجات المنظمة والمزيد. ستفقد فقط الوصول إلى المزودين المتاحين حصرياً عبر LiteLLM (مثل Groq وTogether AI وMistral كمزودين من الدرجة الأولى). + + + نعم. ثبّت إضافات متعددة واستخدم مزودين مختلفين لوكلاء مختلفين: + ```bash + uv add "crewai[openai,anthropic,gemini]" + ``` + ```python + researcher = Agent(llm="openai/gpt-4o", ...) + writer = Agent(llm="anthropic/claude-sonnet-4-20250514", ...) + ``` + + + بغض النظر عن حالة العزل، فإن تقليل سطح اعتمادياتك يُعد ممارسة أمنية جيدة. إذا كنت تحتاج فقط مزودين يدعمهم CrewAI أصلياً، فلا يوجد سبب لإبقاء LiteLLM مثبتاً. + + + يستخدم المزودون الأصليون نفس متغيرات البيئة التي اعتدت عليها. لا حاجة لتغييرات على `OPENAI_API_KEY` أو `ANTHROPIC_API_KEY` أو `GEMINI_API_KEY` وغيرها. + + + +## موارد ذات صلة + +- [اتصالات LLM](/ar/learn/llm-connections) — الدليل الكامل لربط CrewAI مع أي LLM +- [مفاهيم LLM](/ar/concepts/llms) — فهم نماذج اللغة الكبيرة في CrewAI +- [دليل اختيار LLM](/ar/learn/llm-selection-guide) — اختيار النموذج المناسب لحالة استخدامك diff --git a/docs/v1.15.13/ar/learn/llm-connections.mdx b/docs/v1.15.13/ar/learn/llm-connections.mdx new file mode 100644 index 0000000000..d748d115e9 --- /dev/null +++ b/docs/v1.15.13/ar/learn/llm-connections.mdx @@ -0,0 +1,214 @@ +--- +title: الاتصال بأي LLM +description: دليل شامل لدمج CrewAI مع نماذج اللغة الكبيرة المختلفة (LLMs) باستخدام LiteLLM، بما في ذلك المزودون المدعومون وخيارات الإعداد. +icon: brain-circuit +mode: "wide" +--- + +## ربط CrewAI بنماذج اللغة الكبيرة + +يتصل CrewAI بنماذج اللغة الكبيرة من خلال تكاملات SDK الأصلية لأكثر المزودين شيوعاً (OpenAI وAnthropic وGoogle Gemini وAzure وAWS Bedrock)، ويستخدم LiteLLM كاحتياط مرن لجميع المزودين الآخرين. + + + افتراضياً، يستخدم CrewAI نموذج `gpt-4o-mini`. يتم تحديد ذلك بواسطة متغير البيئة `OPENAI_MODEL_NAME`، الذي يكون قيمته الافتراضية "gpt-4o-mini" إذا لم يتم تعيينه. + يمكنك بسهولة إعداد وكلائك لاستخدام نموذج أو مزود مختلف كما هو موضح في هذا الدليل. + + +## المزودون المدعومون + +يدعم LiteLLM مجموعة واسعة من المزودين، بما في ذلك على سبيل المثال لا الحصر: + +- OpenAI +- Anthropic +- Google (Vertex AI, Gemini) +- Azure OpenAI +- AWS (Bedrock, SageMaker) +- Cohere +- VoyageAI +- Hugging Face +- Ollama +- Mistral AI +- Replicate +- Together AI +- AI21 +- Cloudflare Workers AI +- DeepInfra +- Groq +- SambaNova +- Nebius AI Studio +- [NVIDIA NIMs](https://docs.api.nvidia.com/nim/reference/models-1) +- والمزيد! + +للحصول على قائمة كاملة ومحدثة بالمزودين المدعومين، يرجى الرجوع إلى [وثائق مزودي LiteLLM](https://docs.litellm.ai/docs/providers). + + + لاستخدام أي مزود غير مغطى بتكامل أصلي، أضف LiteLLM كاعتمادية لمشروعك: + ```bash + uv add 'crewai[litellm]' + ``` + يستخدم المزودون الأصليون (OpenAI، Anthropic، Google Gemini، Azure، AWS Bedrock) إضافات SDK الخاصة بهم — راجع [أمثلة إعداد المزودين](/ar/concepts/llms#provider-configuration-examples). + + +## تغيير نموذج اللغة الكبير + +لاستخدام LLM مختلف مع وكلاء CrewAI، لديك عدة خيارات: + + + + مرر اسم النموذج كسلسلة نصية عند تهيئة الوكيل: + + ```python Code + from crewai import Agent + + # Using OpenAI's GPT-4 + openai_agent = Agent( + role='OpenAI Expert', + goal='Provide insights using GPT-4', + backstory="An AI assistant powered by OpenAI's latest model.", + llm='gpt-4' + ) + + # Using Anthropic's Claude + claude_agent = Agent( + role='Anthropic Expert', + goal='Analyze data using Claude', + backstory="An AI assistant leveraging Anthropic's language model.", + llm='claude-2' + ) + ``` + + + + لمزيد من الإعداد التفصيلي، استخدم فئة LLM: + + ```python Code + from crewai import Agent, LLM + + llm = LLM( + model="gpt-4", + temperature=0.7, + base_url="https://api.openai.com/v1", + api_key="your-api-key-here" + ) + + agent = Agent( + role='Customized LLM Expert', + goal='Provide tailored responses', + backstory="An AI assistant with custom LLM settings.", + llm=llm + ) + ``` + + + + +## خيارات الإعداد + +عند إعداد LLM لوكيلك، يمكنك الوصول إلى مجموعة واسعة من المعاملات: + +| المعامل | النوع | الوصف | +|:----------|:-----:|:-------------| +| **model** | `str` | اسم النموذج المراد استخدامه (مثل "gpt-4"، "claude-2") | +| **temperature** | `float` | يتحكم في العشوائية في المخرجات (0.0 إلى 1.0) | +| **max_tokens** | `int` | الحد الأقصى لعدد الرموز المولدة | +| **top_p** | `float` | يتحكم في تنوع المخرجات (0.0 إلى 1.0) | +| **frequency_penalty** | `float` | يعاقب الرموز الجديدة بناءً على تكرارها في النص حتى الآن | +| **presence_penalty** | `float` | يعاقب الرموز الجديدة بناءً على وجودها في النص حتى الآن | +| **stop** | `str`, `List[str]` | تسلسل(ات) لإيقاف التوليد | +| **base_url** | `str` | عنوان URL الأساسي لنقطة نهاية API | +| **api_key** | `str` | مفتاح API الخاص بك للمصادقة | + +للحصول على قائمة كاملة بالمعاملات وأوصافها، راجع وثائق فئة LLM. + +## الاتصال بنماذج LLM المتوافقة مع OpenAI + +يمكنك الاتصال بنماذج LLM المتوافقة مع OpenAI باستخدام متغيرات البيئة أو عن طريق تعيين خصائص محددة في فئة LLM: + + + + + ```python Generic + import os + + os.environ["OPENAI_API_KEY"] = "your-api-key" + os.environ["OPENAI_API_BASE"] = "https://api.your-provider.com/v1" + os.environ["OPENAI_MODEL_NAME"] = "your-model-name" + ``` + + ```python Google + import os + + # Example using Gemini's OpenAI-compatible API. + os.environ["OPENAI_API_KEY"] = "your-gemini-key" # Should start with AIza... + os.environ["OPENAI_API_BASE"] = "https://generativelanguage.googleapis.com/v1beta/openai/" + os.environ["OPENAI_MODEL_NAME"] = "openai/gemini-2.0-flash" # Add your Gemini model here, under openai/ + ``` + + + + + ```python Generic + llm = LLM( + model="custom-model-name", + api_key="your-api-key", + base_url="https://api.your-provider.com/v1" + ) + agent = Agent(llm=llm, ...) + ``` + + ```python Google + # Example using Gemini's OpenAI-compatible API + llm = LLM( + model="openai/gemini-2.0-flash", + base_url="https://generativelanguage.googleapis.com/v1beta/openai/", + api_key="your-gemini-key", # Should start with AIza... + ) + agent = Agent(llm=llm, ...) + ``` + + + + +## استخدام النماذج المحلية مع Ollama + +للنماذج المحلية مثل تلك التي يوفرها Ollama: + + + + [انقر هنا لتحميل وتثبيت Ollama](https://ollama.com/download) + + + على سبيل المثال، شغّل `ollama pull llama3.2` لتحميل النموذج. + + + + ```python Code + agent = Agent( + role='Local AI Expert', + goal='Process information using a local model', + backstory="An AI assistant running on local hardware.", + llm=LLM(model="ollama/llama3.2", base_url="http://localhost:11434") + ) + ``` + + + + +## تغيير عنوان URL الأساسي لـ API + +يمكنك تغيير عنوان URL الأساسي لـ API لأي مزود LLM عن طريق تعيين معامل `base_url`: + +```python Code +llm = LLM( + model="custom-model-name", + base_url="https://api.your-provider.com/v1", + api_key="your-api-key" +) +agent = Agent(llm=llm, ...) +``` + +هذا مفيد بشكل خاص عند العمل مع واجهات برمجة تطبيقات متوافقة مع OpenAI أو عندما تحتاج إلى تحديد نقطة نهاية مختلفة للمزود الذي اخترته. + +## الخاتمة + +من خلال الاستفادة من LiteLLM، يوفر CrewAI تكاملاً سلساً مع مجموعة واسعة من نماذج اللغة الكبيرة. تتيح لك هذه المرونة اختيار النموذج الأنسب لاحتياجاتك المحددة، سواء كنت تعطي الأولوية للأداء أو كفاءة التكلفة أو النشر المحلي. تذكر الرجوع إلى [وثائق LiteLLM](https://docs.litellm.ai/docs/) للحصول على أحدث المعلومات حول النماذج المدعومة وخيارات الإعداد. diff --git a/docs/v1.15.13/ar/learn/llm-hooks.mdx b/docs/v1.15.13/ar/learn/llm-hooks.mdx new file mode 100644 index 0000000000..445f99349d --- /dev/null +++ b/docs/v1.15.13/ar/learn/llm-hooks.mdx @@ -0,0 +1,427 @@ +--- +title: خطافات استدعاء LLM +description: تعلم كيفية استخدام خطافات استدعاء LLM لاعتراض وتعديل والتحكم في تفاعلات نماذج اللغة في CrewAI +mode: "wide" +--- + +توفر خطافات استدعاء LLM تحكماً دقيقاً في تفاعلات نماذج اللغة أثناء تنفيذ الوكيل. تتيح لك هذه الخطافات اعتراض استدعاءات LLM وتعديل المطالبات وتحويل الاستجابات وتنفيذ بوابات الموافقة وإضافة تسجيل أو مراقبة مخصصة. + +## نظرة عامة + +تُنفذ خطافات LLM في نقطتين حرجتين: +- **قبل استدعاء LLM**: تعديل الرسائل، التحقق من المدخلات، أو حظر التنفيذ +- **بعد استدعاء LLM**: تحويل الاستجابات، تنقية المخرجات، أو تعديل سجل المحادثة + +## أنواع الخطافات + +### خطافات ما قبل استدعاء LLM + +تُنفذ قبل كل استدعاء LLM، ويمكن لهذه الخطافات: +- فحص وتعديل الرسائل المرسلة إلى LLM +- حظر تنفيذ LLM بناءً على شروط +- تنفيذ تحديد معدل أو بوابات موافقة +- إضافة سياق أو رسائل نظام +- تسجيل تفاصيل الطلب + +**التوقيع:** +```python +def before_hook(context: LLMCallHookContext) -> bool | None: + # Return False to block execution + # Return True or None to allow execution + ... +``` + +### خطافات ما بعد استدعاء LLM + +تُنفذ بعد كل استدعاء LLM، ويمكن لهذه الخطافات: +- تعديل أو تنقية استجابات LLM +- إضافة بيانات وصفية أو تنسيق +- تسجيل تفاصيل الاستجابة +- تحديث سجل المحادثة +- تنفيذ تصفية المحتوى + +**التوقيع:** +```python +def after_hook(context: LLMCallHookContext) -> str | None: + # Return modified response string + # Return None to keep original response + ... +``` + +## سياق خطاف LLM + +يوفر كائن `LLMCallHookContext` وصولاً شاملاً لحالة التنفيذ: + +```python +class LLMCallHookContext: + executor: CrewAgentExecutor # Full executor reference + messages: list # Mutable message list + agent: Agent # Current agent + task: Task # Current task + crew: Crew # Crew instance + llm: BaseLLM # LLM instance + iterations: int # Current iteration count + response: str | None # LLM response (after hooks only) +``` + +### تعديل الرسائل + +**مهم:** قم دائماً بتعديل الرسائل في مكانها: + +```python +# ✅ Correct - modify in-place +def add_context(context: LLMCallHookContext) -> None: + context.messages.append({"role": "system", "content": "Be concise"}) + +# ❌ Wrong - replaces list reference +def wrong_approach(context: LLMCallHookContext) -> None: + context.messages = [{"role": "system", "content": "Be concise"}] +``` + +## طرق التسجيل + +### 1. تسجيل الخطافات العامة + +تسجيل خطافات تنطبق على جميع استدعاءات LLM عبر جميع الأطقم: + +```python +from crewai.hooks import register_before_llm_call_hook, register_after_llm_call_hook + +def log_llm_call(context): + print(f"LLM call by {context.agent.role} at iteration {context.iterations}") + return None # Allow execution + +register_before_llm_call_hook(log_llm_call) +``` + +### 2. التسجيل باستخدام المزخرفات + +استخدم المزخرفات لصياغة أنظف: + +```python +from crewai.hooks import before_llm_call, after_llm_call + +@before_llm_call +def validate_iteration_count(context): + if context.iterations > 10: + print("⚠️ Exceeded maximum iterations") + return False # Block execution + return None + +@after_llm_call +def sanitize_response(context): + if context.response and "API_KEY" in context.response: + return context.response.replace("API_KEY", "[REDACTED]") + return None +``` + +### 3. خطافات نطاق الطاقم + +تسجيل خطافات لمثيل طاقم محدد: + +```python +@CrewBase +class MyProjCrew: + @before_llm_call_crew + def validate_inputs(self, context): + # Only applies to this crew + if context.iterations == 0: + print(f"Starting task: {context.task.description}") + return None + + @after_llm_call_crew + def log_responses(self, context): + # Crew-specific response logging + print(f"Response length: {len(context.response)}") + return None + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +## حالات الاستخدام الشائعة + +### 1. تحديد التكرارات + +```python +@before_llm_call +def limit_iterations(context: LLMCallHookContext) -> bool | None: + max_iterations = 15 + if context.iterations > max_iterations: + print(f"⛔ Blocked: Exceeded {max_iterations} iterations") + return False # Block execution + return None +``` + +### 2. بوابة الموافقة البشرية + +```python +@before_llm_call +def require_approval(context: LLMCallHookContext) -> bool | None: + if context.iterations > 5: + response = context.request_human_input( + prompt=f"Iteration {context.iterations}: Approve LLM call?", + default_message="Press Enter to approve, or type 'no' to block:" + ) + if response.lower() == "no": + print("🚫 LLM call blocked by user") + return False + return None +``` + +### 3. إضافة سياق النظام + +```python +@before_llm_call +def add_guardrails(context: LLMCallHookContext) -> None: + # Add safety guidelines to every LLM call + context.messages.append({ + "role": "system", + "content": "Ensure responses are factual and cite sources when possible." + }) + return None +``` + +### 4. تنقية الاستجابات + +```python +@after_llm_call +def sanitize_sensitive_data(context: LLMCallHookContext) -> str | None: + if not context.response: + return None + + # Remove sensitive patterns + import re + sanitized = context.response + sanitized = re.sub(r'\b\d{3}-\d{2}-\d{4}\b', '[SSN-REDACTED]', sanitized) + sanitized = re.sub(r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', '[CARD-REDACTED]', sanitized) + + return sanitized +``` + +### 5. تتبع التكاليف + +```python +import tiktoken + +@before_llm_call +def track_token_usage(context: LLMCallHookContext) -> None: + encoding = tiktoken.get_encoding("cl100k_base") + total_tokens = sum( + len(encoding.encode(msg.get("content", ""))) + for msg in context.messages + ) + print(f"📊 Input tokens: ~{total_tokens}") + return None + +@after_llm_call +def track_response_tokens(context: LLMCallHookContext) -> None: + if context.response: + encoding = tiktoken.get_encoding("cl100k_base") + tokens = len(encoding.encode(context.response)) + print(f"📊 Response tokens: ~{tokens}") + return None +``` + +### 6. تسجيل التصحيح + +```python +@before_llm_call +def debug_request(context: LLMCallHookContext) -> None: + print(f""" + 🔍 LLM Call Debug: + - Agent: {context.agent.role} + - Task: {context.task.description[:50]}... + - Iteration: {context.iterations} + - Message Count: {len(context.messages)} + - Last Message: {context.messages[-1] if context.messages else 'None'} + """) + return None + +@after_llm_call +def debug_response(context: LLMCallHookContext) -> None: + if context.response: + print(f"✅ Response Preview: {context.response[:100]}...") + return None +``` + +## إدارة الخطافات + +### إلغاء تسجيل الخطافات + +```python +from crewai.hooks import ( + unregister_before_llm_call_hook, + unregister_after_llm_call_hook +) + +# Unregister specific hook +def my_hook(context): + ... + +register_before_llm_call_hook(my_hook) +# Later... +unregister_before_llm_call_hook(my_hook) # Returns True if found +``` + +### مسح الخطافات + +```python +from crewai.hooks import ( + clear_before_llm_call_hooks, + clear_after_llm_call_hooks, + clear_all_llm_call_hooks +) + +# Clear specific hook type +count = clear_before_llm_call_hooks() +print(f"Cleared {count} before hooks") + +# Clear all LLM hooks +before_count, after_count = clear_all_llm_call_hooks() +print(f"Cleared {before_count} before and {after_count} after hooks") +``` + +### عرض الخطافات المسجلة + +```python +from crewai.hooks import ( + get_before_llm_call_hooks, + get_after_llm_call_hooks +) + +# Get current hooks +before_hooks = get_before_llm_call_hooks() +after_hooks = get_after_llm_call_hooks() + +print(f"Registered: {len(before_hooks)} before, {len(after_hooks)} after") +``` + +## أنماط متقدمة + +### تنفيذ خطاف مشروط + +```python +@before_llm_call +def conditional_blocking(context: LLMCallHookContext) -> bool | None: + # Only block for specific agents + if context.agent.role == "researcher" and context.iterations > 10: + return False + + # Only block for specific tasks + if "sensitive" in context.task.description.lower() and context.iterations > 5: + return False + + return None +``` + +### تعديلات واعية بالسياق + +```python +@before_llm_call +def adaptive_prompting(context: LLMCallHookContext) -> None: + # Add different context based on iteration + if context.iterations == 0: + context.messages.append({ + "role": "system", + "content": "Start with a high-level overview." + }) + elif context.iterations > 3: + context.messages.append({ + "role": "system", + "content": "Focus on specific details and provide examples." + }) + return None +``` + +### ربط الخطافات + +```python +# Multiple hooks execute in registration order + +@before_llm_call +def first_hook(context): + print("1. First hook executed") + return None + +@before_llm_call +def second_hook(context): + print("2. Second hook executed") + return None + +@before_llm_call +def blocking_hook(context): + if context.iterations > 10: + print("3. Blocking hook - execution stopped") + return False # Subsequent hooks won't execute + print("3. Blocking hook - execution allowed") + return None +``` + +## أفضل الممارسات + +1. **اجعل الخطافات مركزة**: يجب أن يكون لكل خطاف مسؤولية واحدة +2. **تجنب الحسابات الثقيلة**: تُنفذ الخطافات في كل استدعاء LLM +3. **تعامل مع الأخطاء بأناقة**: استخدم try-except لمنع فشل الخطافات من كسر التنفيذ +4. **استخدم تلميحات الأنواع**: استفد من `LLMCallHookContext` لدعم أفضل في بيئة التطوير +5. **وثّق سلوك الخطاف**: خاصة لشروط الحظر +6. **اختبر الخطافات بشكل مستقل**: اختبر الخطافات وحدوياً قبل الاستخدام في الإنتاج +7. **امسح الخطافات في الاختبارات**: استخدم `clear_all_llm_call_hooks()` بين تشغيلات الاختبار +8. **عدّل في المكان**: قم دائماً بتعديل `context.messages` في مكانها، ولا تستبدلها + +## معالجة الأخطاء + +```python +@before_llm_call +def safe_hook(context: LLMCallHookContext) -> bool | None: + try: + # Your hook logic + if some_condition: + return False + except Exception as e: + print(f"⚠️ Hook error: {e}") + # Decide: allow or block on error + return None # Allow execution despite error +``` + +## أمان الأنواع + +```python +from crewai.hooks import LLMCallHookContext, BeforeLLMCallHookType, AfterLLMCallHookType + +# Explicit type annotations +def my_before_hook(context: LLMCallHookContext) -> bool | None: + return None + +def my_after_hook(context: LLMCallHookContext) -> str | None: + return None + +# Type-safe registration +register_before_llm_call_hook(my_before_hook) +register_after_llm_call_hook(my_after_hook) +``` + +## استكشاف الأخطاء وإصلاحها + +### الخطاف لا يُنفذ +- تحقق من أن الخطاف مسجل قبل تنفيذ الطاقم +- تحقق مما إذا كان خطاف سابق أرجع `False` (يحظر الخطافات اللاحقة) +- تأكد من أن توقيع الخطاف يطابق النوع المتوقع + +### تعديلات الرسائل لا تستمر +- استخدم التعديلات في المكان: `context.messages.append()` +- لا تستبدل القائمة: `context.messages = []` + +### تعديلات الاستجابة لا تعمل +- أرجع السلسلة النصية المعدلة من خطافات ما بعد +- إرجاع `None` يحتفظ بالاستجابة الأصلية + +## الخاتمة + +توفر خطافات استدعاء LLM إمكانيات قوية للتحكم في تفاعلات نماذج اللغة ومراقبتها في CrewAI. استخدمها لتنفيذ حواجز الأمان وبوابات الموافقة والتسجيل وتتبع التكاليف وتنقية الاستجابات. مع معالجة الأخطاء المناسبة وأمان الأنواع، تُمكّن الخطافات أنظمة وكلاء قوية وجاهزة للإنتاج. diff --git a/docs/v1.15.13/ar/learn/llm-selection-guide.mdx b/docs/v1.15.13/ar/learn/llm-selection-guide.mdx new file mode 100644 index 0000000000..f718651920 --- /dev/null +++ b/docs/v1.15.13/ar/learn/llm-selection-guide.mdx @@ -0,0 +1,821 @@ +--- +title: "دليل اختيار LLM الاستراتيجي" +description: "إطار عمل استراتيجي لاختيار نموذج اللغة الكبير المناسب لوكلاء الذكاء الاصطناعي في CrewAI وكتابة تعريفات فعالة للمهام والوكلاء" +icon: "brain-circuit" +mode: "wide" +--- + +## نهج CrewAI في اختيار LLM + +بدلاً من توصيات نماذج محددة، ندعو إلى **إطار تفكير** يساعدك على اتخاذ قرارات مستنيرة بناءً على حالة استخدامك المحددة وقيودك ومتطلباتك. يتطور مشهد LLM بسرعة، مع ظهور نماذج جديدة بانتظام وتحديث النماذج الحالية بشكل متكرر. الأهم هو تطوير نهج منظم للتقييم يبقى ذا صلة بغض النظر عن النماذج المتاحة تحديداً. + + + يركز هذا الدليل على التفكير الاستراتيجي بدلاً من توصيات نماذج محددة، + حيث يتطور مشهد LLM بسرعة. + + +## إطار القرار السريع + + + + ابدأ بفهم عميق لما تتطلبه مهامك فعلاً. ضع في الاعتبار التعقيد المعرفي + المطلوب وعمق الاستدلال اللازم وتنسيق المخرجات المتوقعة وحجم السياق الذي + سيحتاج النموذج لمعالجته. سيوجه هذا التحليل الأساسي كل قرار لاحق. + + + بمجرد فهم متطلباتك، اربطها بنقاط قوة النماذج. تتفوق عائلات النماذج + المختلفة في أنواع مختلفة من العمل؛ بعضها محسّن للاستدلال والتحليل وبعضها + للإبداع وتوليد المحتوى وبعضها للسرعة والكفاءة. + + + ضع في حسبانك قيودك التشغيلية الواقعية بما في ذلك قيود الميزانية ومتطلبات + زمن الاستجابة واحتياجات خصوصية البيانات وقدرات البنية التحتية. قد لا يكون + النموذج الأفضل نظرياً هو الخيار الأفضل عملياً لوضعك. + + + ابدأ بنماذج موثوقة ومفهومة جيداً وحسّن بناءً على الأداء الفعلي في حالة + استخدامك المحددة. غالباً ما تختلف النتائج الواقعية عن المعايير النظرية، لذا + فإن الاختبار التجريبي ضروري. + + + +## Core Selection Framework + +### a. Task-First Thinking + +The most critical step in LLM selection is understanding what your task actually demands. Too often, teams select models based on general reputation or benchmark scores without carefully analyzing their specific requirements. This approach leads to either over-engineering simple tasks with expensive, complex models, or under-powering sophisticated work with models that lack the necessary capabilities. + + + + - **Simple Tasks** represent the majority of everyday AI work and include basic instruction following, straightforward data processing, and simple formatting operations. These tasks typically have clear inputs and outputs with minimal ambiguity. The cognitive load is low, and the model primarily needs to follow explicit instructions rather than engage in complex reasoning. + + - **Complex Tasks** require multi-step reasoning, strategic thinking, and the ability to handle ambiguous or incomplete information. These might involve analyzing multiple data sources, developing comprehensive strategies, or solving problems that require breaking down into smaller components. The model needs to maintain context across multiple reasoning steps and often must make inferences that aren't explicitly stated. + + - **Creative Tasks** demand a different type of cognitive capability focused on generating novel, engaging, and contextually appropriate content. This includes storytelling, marketing copy creation, and creative problem-solving. The model needs to understand nuance, tone, and audience while producing content that feels authentic and engaging rather than formulaic. + + + + + - **Structured Data** tasks require precision and consistency in format adherence. When working with JSON, XML, or database formats, the model must reliably produce syntactically correct output that can be programmatically processed. These tasks often have strict validation requirements and little tolerance for format errors, making reliability more important than creativity. + + - **Creative Content** outputs demand a balance of technical competence and creative flair. The model needs to understand audience, tone, and brand voice while producing content that engages readers and achieves specific communication goals. Quality here is often subjective and requires models that can adapt their writing style to different contexts and purposes. + + - **Technical Content** sits between structured data and creative content, requiring both precision and clarity. Documentation, code generation, and technical analysis need to be accurate and comprehensive while remaining accessible to the intended audience. The model must understand complex technical concepts and communicate them effectively. + + + + + - **Short Context** scenarios involve focused, immediate tasks where the model needs to process limited information quickly. These are often transactional interactions where speed and efficiency matter more than deep understanding. The model doesn't need to maintain extensive conversation history or process large documents. + + - **Long Context** requirements emerge when working with substantial documents, extended conversations, or complex multi-part tasks. The model needs to maintain coherence across thousands of tokens while referencing earlier information accurately. This capability becomes crucial for document analysis, comprehensive research, and sophisticated dialogue systems. + + - **Very Long Context** scenarios push the boundaries of what's currently possible, involving massive document processing, extensive research synthesis, or complex multi-session interactions. These use cases require models specifically designed for extended context handling and often involve trade-offs between context length and processing speed. + + + + +### b. Model Capability Mapping + +Understanding model capabilities requires looking beyond marketing claims and benchmark scores to understand the fundamental strengths and limitations of different model architectures and training approaches. + + + + Reasoning models represent a specialized category designed specifically for complex, multi-step thinking tasks. These models excel when problems require careful analysis, strategic planning, or systematic problem decomposition. They typically employ techniques like chain-of-thought reasoning or tree-of-thought processing to work through complex problems step by step. + + The strength of reasoning models lies in their ability to maintain logical consistency across extended reasoning chains and to break down complex problems into manageable components. They're particularly valuable for strategic planning, complex analysis, and situations where the quality of reasoning matters more than speed of response. + + However, reasoning models often come with trade-offs in terms of speed and cost. They may also be less suitable for creative tasks or simple operations where their sophisticated reasoning capabilities aren't needed. Consider these models when your tasks involve genuine complexity that benefits from systematic, step-by-step analysis. + + + + + General purpose models offer the most balanced approach to LLM selection, providing solid performance across a wide range of tasks without extreme specialization in any particular area. These models are trained on diverse datasets and optimized for versatility rather than peak performance in specific domains. + + The primary advantage of general purpose models is their reliability and predictability across different types of work. They handle most standard business tasks competently, from research and analysis to content creation and data processing. This makes them excellent choices for teams that need consistent performance across varied workflows. + + While general purpose models may not achieve the peak performance of specialized alternatives in specific domains, they offer operational simplicity and reduced complexity in model management. They're often the best starting point for new projects, allowing teams to understand their specific needs before potentially optimizing with more specialized models. + + + + + Fast and efficient models prioritize speed, cost-effectiveness, and resource efficiency over sophisticated reasoning capabilities. These models are optimized for high-throughput scenarios where quick responses and low operational costs are more important than nuanced understanding or complex reasoning. + + These models excel in scenarios involving routine operations, simple data processing, function calling, and high-volume tasks where the cognitive requirements are relatively straightforward. They're particularly valuable for applications that need to process many requests quickly or operate within tight budget constraints. + + The key consideration with efficient models is ensuring that their capabilities align with your task requirements. While they can handle many routine operations effectively, they may struggle with tasks requiring nuanced understanding, complex reasoning, or sophisticated content generation. They're best used for well-defined, routine operations where speed and cost matter more than sophistication. + + + + + Creative models are specifically optimized for content generation, writing quality, and creative thinking tasks. These models typically excel at understanding nuance, tone, and style while producing engaging, contextually appropriate content that feels natural and authentic. + + The strength of creative models lies in their ability to adapt writing style to different audiences, maintain consistent voice and tone, and generate content that engages readers effectively. They often perform better on tasks involving storytelling, marketing copy, brand communications, and other content where creativity and engagement are primary goals. + + When selecting creative models, consider not just their ability to generate text, but their understanding of audience, context, and purpose. The best creative models can adapt their output to match specific brand voices, target different audience segments, and maintain consistency across extended content pieces. + + + + + Open source models offer unique advantages in terms of cost control, customization potential, data privacy, and deployment flexibility. These models can be run locally or on private infrastructure, providing complete control over data handling and model behavior. + + The primary benefits of open source models include elimination of per-token costs, ability to fine-tune for specific use cases, complete data privacy, and independence from external API providers. They're particularly valuable for organizations with strict data privacy requirements, budget constraints, or specific customization needs. + + However, open source models require more technical expertise to deploy and maintain effectively. Teams need to consider infrastructure costs, model management complexity, and the ongoing effort required to keep models updated and optimized. The total cost of ownership may be higher than cloud-based alternatives when factoring in technical overhead. + + + + +## Strategic Configuration Patterns + +### a. Multi-Model Approach + + + Use different models for different purposes within the same crew to optimize + both performance and cost. + + +The most sophisticated CrewAI implementations often employ multiple models strategically, assigning different models to different agents based on their specific roles and requirements. This approach allows teams to optimize for both performance and cost by using the most appropriate model for each type of work. + +Planning agents benefit from reasoning models that can handle complex strategic thinking and multi-step analysis. These agents often serve as the "brain" of the operation, developing strategies and coordinating other agents' work. Content agents, on the other hand, perform best with creative models that excel at writing quality and audience engagement. Processing agents handling routine operations can use efficient models that prioritize speed and cost-effectiveness. + +**Example: Research and Analysis Crew** + +```python +from crewai import Agent, Task, Crew, LLM + +# High-capability reasoning model for strategic planning +manager_llm = LLM(model="gemini-2.5-flash-preview-05-20", temperature=0.1) + +# Creative model for content generation +content_llm = LLM(model="claude-3-5-sonnet-20241022", temperature=0.7) + +# Efficient model for data processing +processing_llm = LLM(model="gpt-4o-mini", temperature=0) + +research_manager = Agent( + role="Research Strategy Manager", + goal="Develop comprehensive research strategies and coordinate team efforts", + backstory="Expert research strategist with deep analytical capabilities", + llm=manager_llm, # High-capability model for complex reasoning + verbose=True +) + +content_writer = Agent( + role="Research Content Writer", + goal="Transform research findings into compelling, well-structured reports", + backstory="Skilled writer who excels at making complex topics accessible", + llm=content_llm, # Creative model for engaging content + verbose=True +) + +data_processor = Agent( + role="Data Analysis Specialist", + goal="Extract and organize key data points from research sources", + backstory="Detail-oriented analyst focused on accuracy and efficiency", + llm=processing_llm, # Fast, cost-effective model for routine tasks + verbose=True +) + +crew = Crew( + agents=[research_manager, content_writer, data_processor], + tasks=[...], # Your specific tasks + manager_llm=manager_llm, # Manager uses the reasoning model + verbose=True +) +``` + +The key to successful multi-model implementation is understanding how different agents interact and ensuring that model capabilities align with agent responsibilities. This requires careful planning but can result in significant improvements in both output quality and operational efficiency. + +### b. Component-Specific Selection + + + + The manager LLM plays a crucial role in hierarchical CrewAI processes, serving as the coordination point for multiple agents and tasks. This model needs to excel at delegation, task prioritization, and maintaining context across multiple concurrent operations. + + Effective manager LLMs require strong reasoning capabilities to make good delegation decisions, consistent performance to ensure predictable coordination, and excellent context management to track the state of multiple agents simultaneously. The model needs to understand the capabilities and limitations of different agents while optimizing task allocation for efficiency and quality. + + Cost considerations are particularly important for manager LLMs since they're involved in every operation. The model needs to provide sufficient capability for effective coordination while remaining cost-effective for frequent use. This often means finding models that offer good reasoning capabilities without the premium pricing of the most sophisticated options. + + + + + Function calling LLMs handle tool usage across all agents, making them critical for crews that rely heavily on external tools and APIs. These models need to excel at understanding tool capabilities, extracting parameters accurately, and handling tool responses effectively. + + The most important characteristics for function calling LLMs are precision and reliability rather than creativity or sophisticated reasoning. The model needs to consistently extract the correct parameters from natural language requests and handle tool responses appropriately. Speed is also important since tool usage often involves multiple round trips that can impact overall performance. + + Many teams find that specialized function calling models or general purpose models with strong tool support work better than creative or reasoning-focused models for this role. The key is ensuring that the model can reliably bridge the gap between natural language instructions and structured tool calls. + + + + + Individual agents can override crew-level LLM settings when their specific needs differ significantly from the general crew requirements. This capability allows for fine-tuned optimization while maintaining operational simplicity for most agents. + + Consider agent-specific overrides when an agent's role requires capabilities that differ substantially from other crew members. For example, a creative writing agent might benefit from a model optimized for content generation, while a data analysis agent might perform better with a reasoning-focused model. + + The challenge with agent-specific overrides is balancing optimization with operational complexity. Each additional model adds complexity to deployment, monitoring, and cost management. Teams should focus overrides on agents where the performance improvement justifies the additional complexity. + + + + +## Task Definition Framework + +### a. Focus on Clarity Over Complexity + +Effective task definition is often more important than model selection in determining the quality of CrewAI outputs. Well-defined tasks provide clear direction and context that enable even modest models to perform well, while poorly defined tasks can cause even sophisticated models to produce unsatisfactory results. + + + + The best task descriptions strike a balance between providing sufficient detail and maintaining clarity. They should define the specific objective clearly enough that there's no ambiguity about what success looks like, while explaining the approach or methodology in enough detail that the agent understands how to proceed. + + Effective task descriptions include relevant context and constraints that help the agent understand the broader purpose and any limitations they need to work within. They break complex work into focused steps that can be executed systematically, rather than presenting overwhelming, multi-faceted objectives that are difficult to approach systematically. + + Common mistakes include being too vague about objectives, failing to provide necessary context, setting unclear success criteria, or combining multiple unrelated tasks into a single description. The goal is to provide enough information for the agent to succeed while maintaining focus on a single, clear objective. + + + + + Expected output guidelines serve as a contract between the task definition and the agent, clearly specifying what the deliverable should look like and how it will be evaluated. These guidelines should describe both the format and structure needed, as well as the key elements that must be included for the output to be considered complete. + + The best output guidelines provide concrete examples of quality indicators and define completion criteria clearly enough that both the agent and human reviewers can assess whether the task has been completed successfully. This reduces ambiguity and helps ensure consistent results across multiple task executions. + + Avoid generic output descriptions that could apply to any task, missing format specifications that leave agents guessing about structure, unclear quality standards that make evaluation difficult, or failing to provide examples or templates that help agents understand expectations. + + + + +### b. Task Sequencing Strategy + + + + Sequential task dependencies are essential when tasks build upon previous outputs, information flows from one task to another, or quality depends on the completion of prerequisite work. This approach ensures that each task has access to the information and context it needs to succeed. + + Implementing sequential dependencies effectively requires using the context parameter to chain related tasks, building complexity gradually through task progression, and ensuring that each task produces outputs that serve as meaningful inputs for subsequent tasks. The goal is to maintain logical flow between dependent tasks while avoiding unnecessary bottlenecks. + + Sequential dependencies work best when there's a clear logical progression from one task to another and when the output of one task genuinely improves the quality or feasibility of subsequent tasks. However, they can create bottlenecks if not managed carefully, so it's important to identify which dependencies are truly necessary versus those that are merely convenient. + + + + + Parallel execution becomes valuable when tasks are independent of each other, time efficiency is important, or different expertise areas are involved that don't require coordination. This approach can significantly reduce overall execution time while allowing specialized agents to work on their areas of strength simultaneously. + + Successful parallel execution requires identifying tasks that can truly run independently, grouping related but separate work streams effectively, and planning for result integration when parallel tasks need to be combined into a final deliverable. The key is ensuring that parallel tasks don't create conflicts or redundancies that reduce overall quality. + + Consider parallel execution when you have multiple independent research streams, different types of analysis that don't depend on each other, or content creation tasks that can be developed simultaneously. However, be mindful of resource allocation and ensure that parallel execution doesn't overwhelm your available model capacity or budget. + + + + +## Optimizing Agent Configuration for LLM Performance + +### a. Role-Driven LLM Selection + + + Generic agent roles make it impossible to select the right LLM. Specific roles + enable targeted model optimization. + + +The specificity of your agent roles directly determines which LLM capabilities matter most for optimal performance. This creates a strategic opportunity to match precise model strengths with agent responsibilities. + +**Generic vs. Specific Role Impact on LLM Choice:** + +When defining roles, think about the specific domain knowledge, working style, and decision-making frameworks that would be most valuable for the tasks the agent will handle. The more specific and contextual the role definition, the better the model can embody that role effectively. + +```python +# ✅ Specific role - clear LLM requirements +specific_agent = Agent( + role="SaaS Revenue Operations Analyst", # Clear domain expertise needed + goal="Analyze recurring revenue metrics and identify growth opportunities", + backstory="Specialist in SaaS business models with deep understanding of ARR, churn, and expansion revenue", + llm=LLM(model="gpt-4o") # Reasoning model justified for complex analysis +) +``` + +**Role-to-Model Mapping Strategy:** + +- **"Research Analyst"** → Reasoning model (GPT-4o, Claude Sonnet) for complex analysis +- **"Content Editor"** → Creative model (Claude, GPT-4o) for writing quality +- **"Data Processor"** → Efficient model (GPT-4o-mini, Gemini Flash) for structured tasks +- **"API Coordinator"** → Function-calling optimized model (GPT-4o, Claude) for tool usage + +### b. Backstory as Model Context Amplifier + + + Strategic backstories multiply your chosen LLM's effectiveness by providing + domain-specific context that generic prompting cannot achieve. + + +A well-crafted backstory transforms your LLM choice from generic capability to specialized expertise. This is especially crucial for cost optimization - a well-contextualized efficient model can outperform a premium model without proper context. + +**Context-Driven Performance Example:** + +```python +# Context amplifies model effectiveness +domain_expert = Agent( + role="B2B SaaS Marketing Strategist", + goal="Develop comprehensive go-to-market strategies for enterprise software", + backstory=""" + You have 10+ years of experience scaling B2B SaaS companies from Series A to IPO. + You understand the nuances of enterprise sales cycles, the importance of product-market + fit in different verticals, and how to balance growth metrics with unit economics. + You've worked with companies like Salesforce, HubSpot, and emerging unicorns, giving + you perspective on both established and disruptive go-to-market strategies. + """, + llm=LLM(model="claude-3-5-sonnet", temperature=0.3) # Balanced creativity with domain knowledge +) + +# This context enables Claude to perform like a domain expert +# Without it, even it would produce generic marketing advice +``` + +**Backstory Elements That Enhance LLM Performance:** + +- **Domain Experience**: "10+ years in enterprise SaaS sales" +- **Specific Expertise**: "Specializes in technical due diligence for Series B+ rounds" +- **Working Style**: "Prefers data-driven decisions with clear documentation" +- **Quality Standards**: "Insists on citing sources and showing analytical work" + +### c. Holistic Agent-LLM Optimization + +The most effective agent configurations create synergy between role specificity, backstory depth, and LLM selection. Each element reinforces the others to maximize model performance. + +**Optimization Framework:** + +```python +# Example: Technical Documentation Agent +tech_writer = Agent( + role="API Documentation Specialist", # Specific role for clear LLM requirements + goal="Create comprehensive, developer-friendly API documentation", + backstory=""" + You're a technical writer with 8+ years documenting REST APIs, GraphQL endpoints, + and SDK integration guides. You've worked with developer tools companies and + understand what developers need: clear examples, comprehensive error handling, + and practical use cases. You prioritize accuracy and usability over marketing fluff. + """, + llm=LLM( + model="claude-3-5-sonnet", # Excellent for technical writing + temperature=0.1 # Low temperature for accuracy + ), + tools=[code_analyzer_tool, api_scanner_tool], + verbose=True +) +``` + +**Alignment Checklist:** + +- ✅ **Role Specificity**: Clear domain and responsibilities +- ✅ **LLM Match**: Model strengths align with role requirements +- ✅ **Backstory Depth**: Provides domain context the LLM can leverage +- ✅ **Tool Integration**: Tools support the agent's specialized function +- ✅ **Parameter Tuning**: Temperature and settings optimize for role needs + +The key is creating agents where every configuration choice reinforces your LLM selection strategy, maximizing performance while optimizing costs. + +## Practical Implementation Checklist + +Rather than repeating the strategic framework, here's a tactical checklist for implementing your LLM selection decisions in CrewAI: + + + + **What to Review:** + - Are all agents using the same LLM by default? + - Which agents handle the most complex reasoning tasks? + - Which agents primarily do data processing or formatting? + - Are any agents heavily tool-dependent? + + **Action**: Document current agent roles and identify optimization opportunities. + + + + + **Set Your Baseline:** + ```python + # Start with a reliable default for the crew + default_crew_llm = LLM(model="gpt-4o-mini") # Cost-effective baseline + + crew = Crew( + agents=[...], + tasks=[...], + memory=True + ) + ``` + + **Action**: Establish your crew's default LLM before optimizing individual agents. + + + + + **Identify and Upgrade Key Agents:** + ```python + # Manager or coordination agents + manager_agent = Agent( + role="Project Manager", + llm=LLM(model="gemini-2.5-flash-preview-05-20"), # Premium for coordination + # ... rest of config + ) + + # Creative or customer-facing agents + content_agent = Agent( + role="Content Creator", + llm=LLM(model="claude-3-5-sonnet"), # Best for writing + # ... rest of config + ) + ``` + + **Action**: Upgrade 20% of your agents that handle 80% of the complexity. + + + + + **Once you deploy your agents to production:** + - Use [CrewAI AMP platform](https://app.crewai.com) to A/B test your model selections + - Run multiple iterations with real inputs to measure consistency and performance + - Compare cost vs. performance across your optimized setup + - Share results with your team for collaborative decision-making + + **Action**: Replace guesswork with data-driven validation using the testing platform. + + + + +### When to Use Different Model Types + + + + Reasoning models become essential when tasks require genuine multi-step logical thinking, strategic planning, or high-level decision making that benefits from systematic analysis. These models excel when problems need to be broken down into components and analyzed systematically rather than handled through pattern matching or simple instruction following. + + Consider reasoning models for business strategy development, complex data analysis that requires drawing insights from multiple sources, multi-step problem solving where each step depends on previous analysis, and strategic planning tasks that require considering multiple variables and their interactions. + + However, reasoning models often come with higher costs and slower response times, so they're best reserved for tasks where their sophisticated capabilities provide genuine value rather than being used for simple operations that don't require complex reasoning. + + + + + Creative models become valuable when content generation is the primary output and the quality, style, and engagement level of that content directly impact success. These models excel when writing quality and style matter significantly, creative ideation or brainstorming is needed, or brand voice and tone are important considerations. + + Use creative models for blog post writing and article creation, marketing copy that needs to engage and persuade, creative storytelling and narrative development, and brand communications where voice and tone are crucial. These models often understand nuance and context better than general purpose alternatives. + + Creative models may be less suitable for technical or analytical tasks where precision and factual accuracy are more important than engagement and style. They're best used when the creative and communicative aspects of the output are primary success factors. + + + + + Efficient models are ideal for high-frequency, routine operations where speed and cost optimization are priorities. These models work best when tasks have clear, well-defined parameters and don't require sophisticated reasoning or creative capabilities. + + Consider efficient models for data processing and transformation tasks, simple formatting and organization operations, function calling and tool usage where precision matters more than sophistication, and high-volume operations where cost per operation is a significant factor. + + The key with efficient models is ensuring that their capabilities align with task requirements. They can handle many routine operations effectively but may struggle with tasks requiring nuanced understanding, complex reasoning, or sophisticated content generation. + + + + + Open source models become attractive when budget constraints are significant, data privacy requirements exist, customization needs are important, or local deployment is required for operational or compliance reasons. + + Consider open source models for internal company tools where data privacy is paramount, privacy-sensitive applications that can't use external APIs, cost-optimized deployments where per-token pricing is prohibitive, and situations requiring custom model modifications or fine-tuning. + + However, open source models require more technical expertise to deploy and maintain effectively. Consider the total cost of ownership including infrastructure, technical overhead, and ongoing maintenance when evaluating open source options. + + + + +## Common CrewAI Model Selection Pitfalls + + + + **The Problem**: Using the same LLM for all agents in a crew, regardless of their specific roles and responsibilities. This is often the default approach but rarely optimal. + + **Real Example**: Using GPT-4o for both a strategic planning manager and a data extraction agent. The manager needs reasoning capabilities worth the premium cost, but the data extractor could perform just as well with GPT-4o-mini at a fraction of the price. + + **CrewAI Solution**: Leverage agent-specific LLM configuration to match model capabilities with agent roles: + ```python + # Strategic agent gets premium model + manager = Agent(role="Strategy Manager", llm=LLM(model="gpt-4o")) + + # Processing agent gets efficient model + processor = Agent(role="Data Processor", llm=LLM(model="gpt-4o-mini")) + ``` + + + + + **The Problem**: Not understanding how CrewAI's LLM hierarchy works - crew LLM, manager LLM, and agent LLM settings can conflict or be poorly coordinated. + + **Real Example**: Setting a crew to use Claude, but having agents configured with GPT models, creating inconsistent behavior and unnecessary model switching overhead. + + **CrewAI Solution**: Plan your LLM hierarchy strategically: + ```python + crew = Crew( + agents=[agent1, agent2], + tasks=[task1, task2], + manager_llm=LLM(model="gpt-4o"), # For crew coordination + process=Process.hierarchical # When using manager_llm + ) + + # Agents inherit crew LLM unless specifically overridden + agent1 = Agent(llm=LLM(model="claude-3-5-sonnet")) # Override for specific needs + ``` + + + + + **The Problem**: Choosing models based on general capabilities while ignoring function calling performance for tool-heavy CrewAI workflows. + + **Real Example**: Selecting a creative-focused model for an agent that primarily needs to call APIs, search tools, or process structured data. The agent struggles with tool parameter extraction and reliable function calls. + + **CrewAI Solution**: Prioritize function calling capabilities for tool-heavy agents: + ```python + # For agents that use many tools + tool_agent = Agent( + role="API Integration Specialist", + tools=[search_tool, api_tool, data_tool], + llm=LLM(model="gpt-4o"), # Excellent function calling + # OR + llm=LLM(model="claude-3-5-sonnet") # Also strong with tools + ) + ``` + + + + + **The Problem**: Making complex model selection decisions based on theoretical performance without validating with actual CrewAI workflows and tasks. + + **Real Example**: Implementing elaborate model switching logic based on task types without testing if the performance gains justify the operational complexity. + + **CrewAI Solution**: Start simple, then optimize based on real performance data: + ```python + # Start with this + crew = Crew(agents=[...], tasks=[...], llm=LLM(model="gpt-4o-mini")) + + # Test performance, then optimize specific agents as needed + # Use Enterprise platform testing to validate improvements + ``` + + + + + **The Problem**: Not considering how model context windows interact with CrewAI's memory and context sharing between agents. + + **Real Example**: Using a short-context model for agents that need to maintain conversation history across multiple task iterations, or in crews with extensive agent-to-agent communication. + + **CrewAI Solution**: Match context capabilities to crew communication patterns. + + + + +## Testing and Iteration Strategy + + + + Begin with reliable, general-purpose models that are well-understood and + widely supported. This provides a stable foundation for understanding your + specific requirements and performance expectations before optimizing for + specialized needs. + + + Develop metrics that align with your specific use case and business + requirements rather than relying solely on general benchmarks. Focus on + measuring outcomes that directly impact your success rather than theoretical + performance indicators. + + + Make model changes based on observed performance in your specific context + rather than theoretical considerations or general recommendations. + Real-world performance often differs significantly from benchmark results or + general reputation. + + + Evaluate the complete cost of ownership including model costs, development + time, maintenance overhead, and operational complexity. The cheapest model + per token may not be the most cost-effective choice when considering all + factors. + + + + + Focus on understanding your requirements first, then select models that best + match those needs. The best LLM choice is the one that consistently delivers + the results you need within your operational constraints. + + +### Enterprise-Grade Model Validation + +For teams serious about optimizing their LLM selection, the **CrewAI AMP platform** provides sophisticated testing capabilities that go far beyond basic CLI testing. The platform enables comprehensive model evaluation that helps you make data-driven decisions about your LLM strategy. + + + ![Enterprise Testing Interface](/images/enterprise/enterprise-testing.png) + + +**Advanced Testing Features:** + +- **Multi-Model Comparison**: Test multiple LLMs simultaneously across the same tasks and inputs. Compare performance between GPT-4o, Claude, Llama, Groq, Cerebras, and other leading models in parallel to identify the best fit for your specific use case. + +- **Statistical Rigor**: Configure multiple iterations with consistent inputs to measure reliability and performance variance. This helps identify models that not only perform well but do so consistently across runs. + +- **Real-World Validation**: Use your actual crew inputs and scenarios rather than synthetic benchmarks. The platform allows you to test with your specific industry context, company information, and real use cases for more accurate evaluation. + +- **Comprehensive Analytics**: Access detailed performance metrics, execution times, and cost analysis across all tested models. This enables data-driven decision making rather than relying on general model reputation or theoretical capabilities. + +- **Team Collaboration**: Share testing results and model performance data across your team, enabling collaborative decision-making and consistent model selection strategies across projects. + +Go to [app.crewai.com](https://app.crewai.com) to get started! + + + The Enterprise platform transforms model selection from guesswork into a + data-driven process, enabling you to validate the principles in this guide + with your actual use cases and requirements. + + +## Key Principles Summary + + + + Choose models based on what the task actually requires, not theoretical capabilities or general reputation. + + +{" "} + + Align model strengths with agent roles and responsibilities for optimal + performance. + + +{" "} + + Maintain coherent model selection strategy across related components and + workflows. + + +{" "} + + Validate choices through real-world usage rather than benchmarks alone. + + +{" "} + + Start simple and optimize based on actual performance and needs. + + + + Balance performance requirements with cost and complexity constraints. + + + + + Remember: The best LLM choice is the one that consistently delivers the + results you need within your operational constraints. Focus on understanding + your requirements first, then select models that best match those needs. + + +## Current Model Landscape (June 2025) + + + **Snapshot in Time**: The following model rankings represent current + leaderboard standings as of June 2025, compiled from [LMSys + Arena](https://arena.lmsys.org/), [Artificial + Analysis](https://artificialanalysis.ai/), and other leading benchmarks. LLM + performance, availability, and pricing change rapidly. Always conduct your own + evaluations with your specific use cases and data. + + +### Leading Models by Category + +The tables below show a representative sample of current top-performing models across different categories, with guidance on their suitability for CrewAI agents: + + + These tables/metrics showcase selected leading models in each category and are + not exhaustive. Many excellent models exist beyond those listed here. The goal + is to illustrate the types of capabilities to look for rather than provide a + complete catalog. + + + + + **Best for Manager LLMs and Complex Analysis** + + | Model | Intelligence Score | Cost ($/M tokens) | Speed | Best Use in CrewAI | + |:------|:------------------|:------------------|:------|:------------------| + | **o3** | 70 | $17.50 | Fast | Manager LLM for complex multi-agent coordination | + | **Gemini 2.5 Pro** | 69 | $3.44 | Fast | Strategic planning agents, research coordination | + | **DeepSeek R1** | 68 | $0.96 | Moderate | Cost-effective reasoning for budget-conscious crews | + | **Claude 4 Sonnet** | 53 | $6.00 | Fast | Analysis agents requiring nuanced understanding | + | **Qwen3 235B (Reasoning)** | 62 | $2.63 | Moderate | Open-source alternative for reasoning tasks | + + These models excel at multi-step reasoning and are ideal for agents that need to develop strategies, coordinate other agents, or analyze complex information. + + + + + **Best for Development and Tool-Heavy Workflows** + + | Model | Coding Performance | Tool Use Score | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:------------------|:---------------|:------------------|:------------------| + | **Claude 4 Sonnet** | Excellent | 72.7% | $6.00 | Primary coding agent, technical documentation | + | **Claude 4 Opus** | Excellent | 72.5% | $30.00 | Complex software architecture, code review | + | **DeepSeek V3** | Very Good | High | $0.48 | Cost-effective coding for routine development | + | **Qwen2.5 Coder 32B** | Very Good | Medium | $0.15 | Budget-friendly coding agent | + | **Llama 3.1 405B** | Good | 81.1% | $3.50 | Function calling LLM for tool-heavy workflows | + + These models are optimized for code generation, debugging, and technical problem-solving, making them ideal for development-focused crews. + + + + + **Best for High-Throughput and Real-Time Applications** + + | Model | Speed (tokens/s) | Latency (TTFT) | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:-----------------|:---------------|:------------------|:------------------| + | **Llama 4 Scout** | 2,600 | 0.33s | $0.27 | High-volume processing agents | + | **Gemini 2.5 Flash** | 376 | 0.30s | $0.26 | Real-time response agents | + | **DeepSeek R1 Distill** | 383 | Variable | $0.04 | Cost-optimized high-speed processing | + | **Llama 3.3 70B** | 2,500 | 0.52s | $0.60 | Balanced speed and capability | + | **Nova Micro** | High | 0.30s | $0.04 | Simple, fast task execution | + + These models prioritize speed and efficiency, perfect for agents handling routine operations or requiring quick responses. **Pro tip**: Pairing these models with fast inference providers like Groq can achieve even better performance, especially for open-source models like Llama. + + + + + **Best All-Around Models for General Crews** + + | Model | Overall Score | Versatility | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:--------------|:------------|:------------------|:------------------| + | **GPT-4.1** | 53 | Excellent | $3.50 | General-purpose crew LLM | + | **Claude 3.7 Sonnet** | 48 | Very Good | $6.00 | Balanced reasoning and creativity | + | **Gemini 2.0 Flash** | 48 | Good | $0.17 | Cost-effective general use | + | **Llama 4 Maverick** | 51 | Good | $0.37 | Open-source general purpose | + | **Qwen3 32B** | 44 | Good | $1.23 | Budget-friendly versatility | + + These models offer good performance across multiple dimensions, suitable for crews with diverse task requirements. + + + + +### Selection Framework for Current Models + + + + **When performance is the priority**: Use top-tier models like **o3**, **Gemini 2.5 Pro**, or **Claude 4 Sonnet** for manager LLMs and critical agents. These models excel at complex reasoning and coordination but come with higher costs. + + **Strategy**: Implement a multi-model approach where premium models handle strategic thinking while efficient models handle routine operations. + + + + + **When budget is a primary constraint**: Focus on models like **DeepSeek R1**, **Llama 4 Scout**, or **Gemini 2.0 Flash**. These provide strong performance at significantly lower costs. + + **Strategy**: Use cost-effective models for most agents, reserving premium models only for the most critical decision-making roles. + + + + + **For specific domain expertise**: Choose models optimized for your primary use case. **Claude 4** series for coding, **Gemini 2.5 Pro** for research, **Llama 405B** for function calling. + + **Strategy**: Select models based on your crew's primary function, ensuring the core capability aligns with model strengths. + + + + + **For data-sensitive operations**: Consider open-source models like **Llama 4** series, **DeepSeek V3**, or **Qwen3** that can be deployed locally while maintaining competitive performance. + + **Strategy**: Deploy open-source models on private infrastructure, accepting potential performance trade-offs for data control. + + + + +### Key Considerations for Model Selection + +- **Performance Trends**: The current landscape shows strong competition between reasoning-focused models (o3, Gemini 2.5 Pro) and balanced models (Claude 4, GPT-4.1). Specialized models like DeepSeek R1 offer excellent cost-performance ratios. + +- **Speed vs. Intelligence Trade-offs**: Models like Llama 4 Scout prioritize speed (2,600 tokens/s) while maintaining reasonable intelligence, whereas models like o3 maximize reasoning capability at the cost of speed and price. + +- **Open Source Viability**: The gap between open-source and proprietary models continues to narrow, with models like Llama 4 Maverick and DeepSeek V3 offering competitive performance at attractive price points. Fast inference providers particularly shine with open-source models, often delivering better speed-to-cost ratios than proprietary alternatives. + + + **Testing is Essential**: Leaderboard rankings provide general guidance, but + your specific use case, prompting style, and evaluation criteria may produce + different results. Always test candidate models with your actual tasks and + data before making final decisions. + + +### Practical Implementation Strategy + + + + Begin with well-established models like **GPT-4.1**, **Claude 3.7 Sonnet**, or **Gemini 2.0 Flash** that offer good performance across multiple dimensions and have extensive real-world validation. + + + + Determine if your crew has specific requirements (coding, reasoning, speed) + that would benefit from specialized models like **Claude 4 Sonnet** for + development or **o3** for complex analysis. For speed-critical applications, + consider fast inference providers like **Groq** alongside model selection. + + + + Use different models for different agents based on their roles. + High-capability models for managers and complex tasks, efficient models for + routine operations. + + + + Track performance metrics relevant to your use case and be prepared to adjust model selections as new models are released or pricing changes. + + diff --git a/docs/v1.15.13/ar/learn/multimodal-agents.mdx b/docs/v1.15.13/ar/learn/multimodal-agents.mdx new file mode 100644 index 0000000000..9c80f969cf --- /dev/null +++ b/docs/v1.15.13/ar/learn/multimodal-agents.mdx @@ -0,0 +1,141 @@ +--- +title: استخدام الوكلاء متعددي الوسائط +description: تعلم كيفية تفعيل واستخدام القدرات متعددة الوسائط في وكلائك لمعالجة الصور والمحتوى غير النصي ضمن إطار عمل CrewAI. +icon: video +mode: "wide" +--- + +## استخدام الوكلاء متعددي الوسائط + +يدعم CrewAI الوكلاء متعددي الوسائط القادرين على معالجة المحتوى النصي وغير النصي مثل الصور. سيوضح لك هذا الدليل كيفية تفعيل واستخدام القدرات متعددة الوسائط في وكلائك. + +### تفعيل القدرات متعددة الوسائط + +لإنشاء وكيل متعدد الوسائط، ما عليك سوى تعيين معامل `multimodal` إلى `True` عند تهيئة وكيلك: + +```python +from crewai import Agent + +agent = Agent( + role="Image Analyst", + goal="Analyze and extract insights from images", + backstory="An expert in visual content interpretation with years of experience in image analysis", + multimodal=True # This enables multimodal capabilities +) +``` + +عند تعيين `multimodal=True`، يتم إعداد الوكيل تلقائياً بالأدوات اللازمة للتعامل مع المحتوى غير النصي، بما في ذلك `AddImageTool`. + +### العمل مع الصور + +يأتي الوكيل متعدد الوسائط مُعداً مسبقاً بأداة `AddImageTool`، التي تتيح له معالجة الصور. لا تحتاج إلى إضافة هذه الأداة يدوياً — فهي مضمنة تلقائياً عند تفعيل القدرات متعددة الوسائط. + +إليك مثالاً كاملاً يوضح كيفية استخدام وكيل متعدد الوسائط لتحليل صورة: + +```python +from crewai import Agent, Task, Crew + +# Create a multimodal agent +image_analyst = Agent( + role="Product Analyst", + goal="Analyze product images and provide detailed descriptions", + backstory="Expert in visual product analysis with deep knowledge of design and features", + multimodal=True +) + +# Create a task for image analysis +task = Task( + description="Analyze the product image at https://example.com/product.jpg and provide a detailed description", + expected_output="A detailed description of the product image", + agent=image_analyst +) + +# Create and run the crew +crew = Crew( + agents=[image_analyst], + tasks=[task] +) + +result = crew.kickoff() +``` + +### الاستخدام المتقدم مع السياق + +يمكنك تقديم سياق إضافي أو أسئلة محددة حول الصورة عند إنشاء مهام للوكلاء متعددي الوسائط. يمكن أن يتضمن وصف المهمة جوانب محددة تريد أن يركز عليها الوكيل: + +```python +from crewai import Agent, Task, Crew + +# Create a multimodal agent for detailed analysis +expert_analyst = Agent( + role="Visual Quality Inspector", + goal="Perform detailed quality analysis of product images", + backstory="Senior quality control expert with expertise in visual inspection", + multimodal=True # AddImageTool is automatically included +) + +# Create a task with specific analysis requirements +inspection_task = Task( + description=""" + Analyze the product image at https://example.com/product.jpg with focus on: + 1. Quality of materials + 2. Manufacturing defects + 3. Compliance with standards + Provide a detailed report highlighting any issues found. + """, + expected_output="A detailed report highlighting any issues found", + agent=expert_analyst +) + +# Create and run the crew +crew = Crew( + agents=[expert_analyst], + tasks=[inspection_task] +) + +result = crew.kickoff() +``` + +### تفاصيل الأداة + +عند العمل مع الوكلاء متعددي الوسائط، يتم إعداد `AddImageTool` تلقائياً بالمخطط التالي: + +```python +class AddImageToolSchema: + image_url: str # Required: The URL or path of the image to process + action: Optional[str] = None # Optional: Additional context or specific questions about the image +``` + +سيتعامل الوكيل متعدد الوسائط تلقائياً مع معالجة الصور من خلال أدواته المدمجة، مما يتيح له: +- الوصول إلى الصور عبر عناوين URL أو مسارات الملفات المحلية +- معالجة محتوى الصورة مع سياق اختياري أو أسئلة محددة +- تقديم تحليلات ورؤى بناءً على المعلومات البصرية ومتطلبات المهمة + +### أفضل الممارسات + +عند العمل مع الوكلاء متعددي الوسائط، ضع هذه الممارسات في الاعتبار: + +1. **الوصول إلى الصور** + - تأكد من أن صورك قابلة للوصول عبر عناوين URL التي يمكن للوكيل الوصول إليها + - للصور المحلية، فكر في استضافتها مؤقتاً أو استخدام مسارات ملفات مطلقة + - تحقق من أن عناوين URL للصور صالحة وقابلة للوصول قبل تشغيل المهام + +2. **وصف المهمة** + - كن محدداً حول الجوانب التي تريد من الوكيل تحليلها في الصورة + - قم بتضمين أسئلة أو متطلبات واضحة في وصف المهمة + - فكر في استخدام معامل `action` الاختياري للتحليل المركز + +3. **إدارة الموارد** + - قد تتطلب معالجة الصور موارد حسابية أكثر من المهام النصية فقط + - قد تتطلب بعض نماذج اللغة ترميز base64 لبيانات الصورة + - فكر في المعالجة الدفعية لصور متعددة لتحسين الأداء + +4. **إعداد البيئة** + - تحقق من أن بيئتك تحتوي على الاعتماديات اللازمة لمعالجة الصور + - تأكد من أن نموذج اللغة الخاص بك يدعم القدرات متعددة الوسائط + - اختبر بصور صغيرة أولاً للتحقق من إعدادك + +5. **معالجة الأخطاء** + - نفّذ معالجة أخطاء مناسبة لحالات فشل تحميل الصور + - ضع استراتيجيات احتياطية لحالات فشل معالجة الصور + - راقب وسجل عمليات معالجة الصور لأغراض التصحيح diff --git a/docs/v1.15.13/ar/learn/overview.mdx b/docs/v1.15.13/ar/learn/overview.mdx new file mode 100644 index 0000000000..b09a944fd7 --- /dev/null +++ b/docs/v1.15.13/ar/learn/overview.mdx @@ -0,0 +1,159 @@ +--- +title: "نظرة عامة" +description: "تعلم كيفية بناء وتخصيص وتحسين تطبيقات CrewAI الخاصة بك مع أدلة وبرامج تعليمية شاملة" +icon: "face-smile" +mode: "wide" +--- + +## تعلم CrewAI + +يوفر هذا القسم أدلة وبرامج تعليمية شاملة لمساعدتك في إتقان CrewAI، من المفاهيم الأساسية إلى التقنيات المتقدمة. سواء كنت قد بدأت للتو أو تبحث عن تحسين تطبيقاتك الحالية، ستوجهك هذه الموارد عبر كل جانب من جوانب بناء سير عمل وكلاء الذكاء الاصطناعي القوية. + +## أدلة البدء + +### المفاهيم الأساسية + + + تعلم كيفية تنفيذ المهام بترتيب تسلسلي لسير عمل منظم. + + + + تنفيذ تنفيذ المهام الهرمي مع وكلاء مديرين يشرفون على سير العمل. + + + + إنشاء سير عمل ديناميكي مع تنفيذ مهام شرطي بناءً على النتائج. + + + + تنفيذ الأطقم بشكل غير متزامن لأداء وتزامن محسّن. + + + +### تطوير الوكلاء + + + تعلم كيفية تخصيص سلوك الوكلاء وأدوارهم وقدراتهم. + + + + بناء وكلاء يمكنهم كتابة وتنفيذ وتصحيح الكود تلقائياً. + + + + إنشاء وكلاء يمكنهم معالجة النصوص والصور وأنواع الوسائط الأخرى. + + + + تنفيذ وكلاء مديرين مخصصين لسير العمل الهرمي المعقد. + + + +## الميزات المتقدمة + +### التحكم في سير العمل + + + دمج الإشراف البشري والتدخل في سير عمل الوكلاء. + + + + السماح بالإدخال البشري أثناء تنفيذ المهام لاتخاذ قرارات ديناميكية. + + + + إعادة تشغيل واستئناف المهام من عمليات تنفيذ الطاقم السابقة. + + + + تنفيذ الأطقم عدة مرات بمدخلات مختلفة بكفاءة. + + + +### التخصيص والتكامل + + + دمج نماذج لغة ومزودين مخصصين مع CrewAI. + + + + إعداد وإدارة الاتصالات بمزودي LLM المختلفين. + + + + بناء أدوات مخصصة لتوسيع قدرات الوكلاء. + + + + استخدام تعليقات Python التوضيحية لكود أنظف وأسهل في الصيانة. + + + +## التطبيقات المتخصصة + +### المحتوى والوسائط + + + توليد الصور باستخدام تكامل DALL-E مع وكلائك. + + + + دمج الوكلاء والنماذج الموجودة في سير عمل CrewAI. + + + +### إدارة الأدوات + + + إعداد الأدوات لإرجاع مخرجاتها مباشرة كنتائج للمهام. + + + +## توصيات مسار التعلم + +### للمبتدئين +1. ابدأ بـ **العملية التسلسلية** لفهم تنفيذ سير العمل الأساسي +2. تعلم **تخصيص الوكلاء** لإنشاء إعدادات وكلاء فعالة +3. استكشف **إنشاء أدوات مخصصة** لتوسيع الوظائف +4. جرب **الإنسان في الحلقة** لسير العمل التفاعلي + +### للمستخدمين المتوسطين +1. أتقن **العملية الهرمية** لأنظمة الوكلاء المتعددة المعقدة +2. نفّذ **المهام الشرطية** لسير العمل الديناميكي +3. استخدم **التشغيل غير المتزامن** لتحسين الأداء +4. ادمج **LLM مخصص** للنماذج المتخصصة + +### للمستخدمين المتقدمين +1. ابنِ **وكلاء متعددي الوسائط** لمعالجة الوسائط المعقدة +2. أنشئ **وكلاء مديرين مخصصين** للتنسيق المتطور +3. نفّذ **أحضر وكيلك الخاص** للأنظمة الهجينة +4. استخدم **إعادة تشغيل المهام** لاسترداد الأخطاء بشكل متين + +## أفضل الممارسات + +### التطوير +- **ابدأ بالبساطة**: ابدأ بسير العمل التسلسلي الأساسي قبل إضافة التعقيد +- **اختبر تدريجياً**: اختبر كل مكون قبل دمجه في أنظمة أكبر +- **استخدم التعليقات التوضيحية**: استفد من تعليقات Python التوضيحية لكود أنظف وأسهل في الصيانة +- **أدوات مخصصة**: ابنِ أدوات قابلة لإعادة الاستخدام يمكن مشاركتها عبر وكلاء مختلفين + +### الإنتاج +- **معالجة الأخطاء**: نفّذ معالجة أخطاء وآليات استرداد قوية +- **الأداء**: استخدم التنفيذ غير المتزامن وحسّن استدعاءات LLM لأداء أفضل +- **المراقبة**: ادمج أدوات المراقبة لتتبع أداء الوكلاء +- **الإشراف البشري**: ضمّن نقاط تفتيش بشرية للقرارات الحرجة + +### التحسين +- **إدارة الموارد**: راقب وحسّن استخدام الرموز وتكاليف API +- **تصميم سير العمل**: صمم سير عمل يقلل من استدعاءات LLM غير الضرورية +- **كفاءة الأدوات**: أنشئ أدوات فعالة توفر أقصى قيمة بأقل حمل +- **التحسين التكراري**: استخدم التغذية الراجعة والمقاييس لتحسين أداء الوكلاء باستمرار + +## الحصول على المساعدة + +- **التوثيق**: يتضمن كل دليل أمثلة وشروحات مفصلة +- **المجتمع**: انضم إلى [منتدى CrewAI](https://community.crewai.com) للمناقشات والدعم +- **الأمثلة**: تحقق من قسم الأمثلة للتطبيقات العاملة الكاملة +- **الدعم**: تواصل مع [support@crewai.com](mailto:support@crewai.com) للمساعدة التقنية + +ابدأ بالأدلة التي تتوافق مع احتياجاتك الحالية واستكشف تدريجياً المواضيع الأكثر تقدماً مع إتقانك للأساسيات. diff --git a/docs/v1.15.13/ar/learn/replay-tasks-from-latest-crew-kickoff.mdx b/docs/v1.15.13/ar/learn/replay-tasks-from-latest-crew-kickoff.mdx new file mode 100644 index 0000000000..069e25c319 --- /dev/null +++ b/docs/v1.15.13/ar/learn/replay-tasks-from-latest-crew-kickoff.mdx @@ -0,0 +1,79 @@ +--- +title: إعادة تشغيل المهام من آخر تنفيذ للطاقم +description: إعادة تشغيل المهام من آخر crew.kickoff(...) +icon: arrow-right +mode: "wide" +--- + +## مقدمة + +يوفر CrewAI القدرة على إعادة التشغيل من مهمة محددة من آخر تشغيل للطاقم. هذه الميزة مفيدة بشكل خاص عندما تكون قد أنهيت تشغيلاً وقد ترغب في إعادة محاولة مهام معينة أو لا تحتاج إلى إعادة جلب البيانات ووكلاؤك لديهم بالفعل السياق المحفوظ من تنفيذ التشغيل، لذا تحتاج فقط إلى إعادة تشغيل المهام التي تريدها. + + + يجب عليك تشغيل `crew.kickoff()` قبل أن تتمكن من إعادة تشغيل مهمة. + حالياً، يُدعم فقط آخر تشغيل، لذا إذا استخدمت `kickoff_for_each`، فسيسمح لك فقط بإعادة التشغيل من أحدث تشغيل للطاقم. + + +إليك مثالاً على كيفية إعادة التشغيل من مهمة: + +### إعادة التشغيل من مهمة محددة باستخدام CLI + +لاستخدام ميزة إعادة التشغيل، اتبع هذه الخطوات: + + + + + + لعرض معرفات المهام من آخر تشغيل، استخدم: + + ```shell + crewai log-tasks-outputs + ``` + + بمجرد حصولك على `task_id` لإعادة التشغيل، استخدم: + + ```shell + crewai replay -t + ``` + + + + + تأكد من أن `crewai` مثبت ومُعد بشكل صحيح في بيئة التطوير الخاصة بك. + + +### إعادة التشغيل من مهمة برمجياً + +لإعادة التشغيل من مهمة برمجياً، استخدم الخطوات التالية: + + + + حدد `task_id` ومعاملات الإدخال لعملية إعادة التشغيل. + + + نفّذ أمر إعادة التشغيل ضمن كتلة try-except للتعامل مع الأخطاء المحتملة. + + ```python Code + def replay(): + """ + Replay the crew execution from a specific task. + """ + task_id = '' + inputs = {"topic": "CrewAI Training"} # This is optional; you can pass in the inputs you want to replay; otherwise, it uses the previous kickoff's inputs. + try: + YourCrewName_Crew().crew().replay(task_id=task_id, inputs=inputs) + + except subprocess.CalledProcessError as e: + raise Exception(f"An error occurred while replaying the crew: {e}") + + except Exception as e: + raise Exception(f"An unexpected error occurred: {e}") + ``` + + + + +## الخاتمة + +مع التحسينات المذكورة أعلاه والوظائف المفصلة، أصبحت إعادة تشغيل مهام محددة في CrewAI أكثر كفاءة ومتانة. +تأكد من اتباع الأوامر والخطوات بدقة لتحقيق أقصى استفادة من هذه الميزات. diff --git a/docs/v1.15.13/ar/learn/sequential-process.mdx b/docs/v1.15.13/ar/learn/sequential-process.mdx new file mode 100644 index 0000000000..7ef2d66bfb --- /dev/null +++ b/docs/v1.15.13/ar/learn/sequential-process.mdx @@ -0,0 +1,128 @@ +--- +title: العمليات التسلسلية +description: دليل شامل لاستخدام العمليات التسلسلية لتنفيذ المهام في مشاريع CrewAI. +icon: forward +mode: "wide" +--- + +## مقدمة + +يقدم CrewAI إطار عمل مرن لتنفيذ المهام بطريقة منظمة، يدعم كلاً من العمليات التسلسلية والهرمية. +يوضح هذا الدليل كيفية تنفيذ هذه العمليات بفعالية لضمان تنفيذ المهام بكفاءة وإكمال المشروع. + +## نظرة عامة على العملية التسلسلية + +تضمن العملية التسلسلية تنفيذ المهام واحدة تلو الأخرى، باتباع تقدم خطي. +هذا النهج مثالي للمشاريع التي تتطلب إكمال المهام بترتيب محدد. + +### الميزات الرئيسية + +- **تدفق مهام خطي**: يضمن تقدماً منظماً من خلال التعامل مع المهام بتسلسل محدد مسبقاً. +- **البساطة**: الأنسب للمشاريع ذات المهام الواضحة خطوة بخطوة. +- **سهولة المراقبة**: يسهل التتبع السهل لإكمال المهام وتقدم المشروع. + +## تنفيذ العملية التسلسلية + +لاستخدام العملية التسلسلية، قم بتجميع طاقمك وتعريف المهام بالترتيب الذي تحتاج إلى تنفيذها به. + +```python Code +from crewai import Crew, Process, Agent, Task, TaskOutput, CrewOutput + +# Define your agents +researcher = Agent( + role='Researcher', + goal='Conduct foundational research', + backstory='An experienced researcher with a passion for uncovering insights' +) +analyst = Agent( + role='Data Analyst', + goal='Analyze research findings', + backstory='A meticulous analyst with a knack for uncovering patterns' +) +writer = Agent( + role='Writer', + goal='Draft the final report', + backstory='A skilled writer with a talent for crafting compelling narratives' +) + +# Define your tasks +research_task = Task( + description='Gather relevant data...', + agent=researcher, + expected_output='Raw Data' +) +analysis_task = Task( + description='Analyze the data...', + agent=analyst, + expected_output='Data Insights' +) +writing_task = Task( + description='Compose the report...', + agent=writer, + expected_output='Final Report' +) + +# Form the crew with a sequential process +report_crew = Crew( + agents=[researcher, analyst, writer], + tasks=[research_task, analysis_task, writing_task], + process=Process.sequential +) + +# Execute the crew +result = report_crew.kickoff() + +# Accessing the type-safe output +task_output: TaskOutput = result.tasks[0].output +crew_output: CrewOutput = result.output +``` + +### ملاحظة: + +يجب أن يكون لكل مهمة في عملية تسلسلية وكيل مُعيّن. تأكد من أن كل `Task` تتضمن معامل `agent`. + +### سير العمل أثناء التنفيذ + +1. **المهمة الأولى**: في العملية التسلسلية، يكمل الوكيل الأول مهمته ويشير إلى الإكمال. +2. **المهام اللاحقة**: يلتقط الوكلاء مهامهم بناءً على نوع العملية، مع نتائج المهام السابقة أو التوجيهات التي تقود تنفيذهم. +3. **الإكمال**: تنتهي العملية بمجرد تنفيذ المهمة النهائية، مما يؤدي إلى إكمال المشروع. + +## الميزات المتقدمة + +### تفويض المهام + +في العمليات التسلسلية، إذا كان الوكيل لديه `allow_delegation` مُعيّن إلى `True`، يمكنه تفويض المهام إلى وكلاء آخرين في الطاقم. +يتم إعداد هذه الميزة تلقائياً عندما يكون هناك عدة وكلاء في الطاقم. + +### التنفيذ غير المتزامن + +يمكن تنفيذ المهام بشكل غير متزامن، مما يسمح بالمعالجة المتوازية عند الاقتضاء. +لإنشاء مهمة غير متزامنة، عيّن `async_execution=True` عند تعريف المهمة. + +### الذاكرة والتخزين المؤقت + +يدعم CrewAI كلاً من ميزتي الذاكرة والتخزين المؤقت: + +- **الذاكرة**: فعّلها بتعيين `memory=True` عند إنشاء الطاقم. يتيح هذا للوكلاء الاحتفاظ بالمعلومات عبر المهام. +- **التخزين المؤقت**: افتراضياً، التخزين المؤقت مفعّل. عيّن `cache=False` لتعطيله. + +### دوال الاستدعاء الراجع + +يمكنك تعيين دوال استدعاء راجع على مستوى المهمة والخطوة: + +- `task_callback`: يُنفذ بعد إكمال كل مهمة. +- `step_callback`: يُنفذ بعد كل خطوة في تنفيذ الوكيل. + +### مقاييس الاستخدام + +يتتبع CrewAI استخدام الرموز عبر جميع المهام والوكلاء. يمكنك الوصول إلى هذه المقاييس بعد التنفيذ. + +## أفضل الممارسات للعمليات التسلسلية + +1. **الترتيب مهم**: رتّب المهام بتسلسل منطقي حيث تبني كل مهمة على سابقتها. +2. **أوصاف مهام واضحة**: قدم أوصافاً مفصلة لكل مهمة لتوجيه الوكلاء بفعالية. +3. **اختيار الوكيل المناسب**: طابق مهارات وأدوار الوكلاء مع متطلبات كل مهمة. +4. **استخدم السياق**: استفد من سياق المهام السابقة لإبلاغ المهام اللاحقة. + +يضمن هذا التوثيق المحدث أن التفاصيل تعكس بدقة أحدث التغييرات في قاعدة الكود وتصف بوضوح كيفية الاستفادة من الميزات والإعدادات الجديدة. +تم الحفاظ على بساطة المحتوى ومباشرته لضمان سهولة الفهم. diff --git a/docs/v1.15.13/ar/learn/streaming-crew-execution.mdx b/docs/v1.15.13/ar/learn/streaming-crew-execution.mdx new file mode 100644 index 0000000000..4dfe1859f9 --- /dev/null +++ b/docs/v1.15.13/ar/learn/streaming-crew-execution.mdx @@ -0,0 +1,384 @@ +--- +title: بث تنفيذ الطاقم +description: بث المخرجات في الوقت الفعلي من تنفيذ طاقم CrewAI الخاص بك +icon: wave-pulse +mode: "wide" +--- + +## مقدمة + +يوفر CrewAI القدرة على بث المخرجات في الوقت الفعلي أثناء تنفيذ الطاقم، مما يتيح لك عرض النتائج فور توليدها بدلاً من انتظار اكتمال العملية بالكامل. هذه الميزة مفيدة بشكل خاص لبناء التطبيقات التفاعلية وتقديم تغذية راجعة للمستخدم ومراقبة العمليات طويلة التشغيل. + +## كيف يعمل البث + +عند تفعيل البث، يلتقط CrewAI استجابات LLM واستدعاءات الأدوات فور حدوثها، ويحزمها في أجزاء منظمة تتضمن سياقاً حول المهمة والوكيل المنفذ. يمكنك التكرار على هذه الأجزاء في الوقت الفعلي والوصول إلى النتيجة النهائية بمجرد اكتمال التنفيذ. + +## تفعيل البث + +لتفعيل البث، عيّن معامل `stream` إلى `True` عند إنشاء طاقمك: + +```python Code +from crewai import Agent, Crew, Task + +# Create your agents and tasks +researcher = Agent( + role="Research Analyst", + goal="Gather comprehensive information on topics", + backstory="You are an experienced researcher with excellent analytical skills.", +) + +task = Task( + description="Research the latest developments in AI", + expected_output="A detailed report on recent AI advancements", + agent=researcher, +) + +# Enable streaming +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True # Enable streaming output +) +``` + +## البث المتزامن + +عند استدعاء `kickoff()` على طاقم مع تفعيل البث، يُرجع كائن `CrewStreamingOutput` يمكنك التكرار عليه لاستلام الأجزاء فور وصولها: + +```python Code +# Start streaming execution +streaming = crew.kickoff(inputs={"topic": "artificial intelligence"}) + +# Iterate over chunks as they arrive +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# Access the final result after streaming completes +result = streaming.result +print(f"\n\nFinal output: {result.raw}") +``` + +### معلومات جزء البث + +يوفر كل جزء سياقاً غنياً حول التنفيذ: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +for chunk in streaming: + print(f"Task: {chunk.task_name} (index {chunk.task_index})") + print(f"Agent: {chunk.agent_role}") + print(f"Content: {chunk.content}") + print(f"Type: {chunk.chunk_type}") # TEXT or TOOL_CALL + if chunk.tool_call: + print(f"Tool: {chunk.tool_call.tool_name}") + print(f"Arguments: {chunk.tool_call.arguments}") +``` + +### الوصول إلى نتائج البث + +يوفر كائن `CrewStreamingOutput` عدة خصائص مفيدة: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +# Iterate and collect chunks +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# After iteration completes +print(f"\nCompleted: {streaming.is_completed}") +print(f"Full text: {streaming.get_full_text()}") +print(f"All chunks: {len(streaming.chunks)}") +print(f"Final result: {streaming.result.raw}") +``` + +## البث غير المتزامن + +للتطبيقات غير المتزامنة، يمكنك استخدام إما `akickoff()` (async أصلي) أو `kickoff_async()` (قائم على الخيوط) مع التكرار غير المتزامن: + +### async أصلي مع `akickoff()` + +توفر طريقة `akickoff()` تنفيذاً غير متزامن أصلياً حقيقياً عبر السلسلة بالكامل: + +```python Code +import asyncio + +async def stream_crew(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + # Start native async streaming + streaming = await crew.akickoff(inputs={"topic": "AI"}) + + # Async iteration over chunks + async for chunk in streaming: + print(chunk.content, end="", flush=True) + + # Access final result + result = streaming.result + print(f"\n\nFinal output: {result.raw}") + +asyncio.run(stream_crew()) +``` + +### async قائم على الخيوط مع `kickoff_async()` + +للتكامل البسيط مع async أو التوافق مع الإصدارات السابقة: + +```python Code +import asyncio + +async def stream_crew(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + # Start thread-based async streaming + streaming = await crew.kickoff_async(inputs={"topic": "AI"}) + + # Async iteration over chunks + async for chunk in streaming: + print(chunk.content, end="", flush=True) + + # Access final result + result = streaming.result + print(f"\n\nFinal output: {result.raw}") + +asyncio.run(stream_crew()) +``` + + +لأحمال العمل عالية التزامن، يُوصى باستخدام `akickoff()` لأنه يستخدم async أصلي لتنفيذ المهام وعمليات الذاكرة واسترجاع المعرفة. راجع دليل [تشغيل الطاقم بشكل غير متزامن](/ar/learn/kickoff-async) لمزيد من التفاصيل. + + +## البث مع kickoff_for_each + +عند تنفيذ طاقم لمدخلات متعددة مع `kickoff_for_each()`، يعمل البث بشكل مختلف حسب ما إذا كنت تستخدم المتزامن أو غير المتزامن: + +### kickoff_for_each المتزامن + +مع `kickoff_for_each()` المتزامن، تحصل على قائمة كائنات `CrewStreamingOutput`، واحد لكل مدخل: + +```python Code +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True +) + +inputs_list = [ + {"topic": "AI in healthcare"}, + {"topic": "AI in finance"} +] + +# Returns list of streaming outputs +streaming_outputs = crew.kickoff_for_each(inputs=inputs_list) + +# Iterate over each streaming output +for i, streaming in enumerate(streaming_outputs): + print(f"\n=== Input {i + 1} ===") + for chunk in streaming: + print(chunk.content, end="", flush=True) + + result = streaming.result + print(f"\n\nResult {i + 1}: {result.raw}") +``` + +### kickoff_for_each_async غير المتزامن + +مع `kickoff_for_each_async()` غير المتزامن، تحصل على `CrewStreamingOutput` واحد يُخرج أجزاء من جميع الأطقم فور وصولها بشكل متزامن: + +```python Code +import asyncio + +async def stream_multiple_crews(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + inputs_list = [ + {"topic": "AI in healthcare"}, + {"topic": "AI in finance"} + ] + + # Returns single streaming output for all crews + streaming = await crew.kickoff_for_each_async(inputs=inputs_list) + + # Chunks from all crews arrive as they're generated + async for chunk in streaming: + print(f"[{chunk.task_name}] {chunk.content}", end="", flush=True) + + # Access all results + results = streaming.results # List of CrewOutput objects + for i, result in enumerate(results): + print(f"\n\nResult {i + 1}: {result.raw}") + +asyncio.run(stream_multiple_crews()) +``` + +## أنواع أجزاء البث + +يمكن أن تكون الأجزاء من أنواع مختلفة، يُشار إليها بحقل `chunk_type`: + +### أجزاء TEXT + +محتوى نصي قياسي من استجابات LLM: + +```python Code +for chunk in streaming: + if chunk.chunk_type == StreamChunkType.TEXT: + print(chunk.content, end="", flush=True) +``` + +### أجزاء TOOL_CALL + +معلومات حول استدعاءات الأدوات الجارية: + +```python Code +for chunk in streaming: + if chunk.chunk_type == StreamChunkType.TOOL_CALL: + print(f"\nCalling tool: {chunk.tool_call.tool_name}") + print(f"Arguments: {chunk.tool_call.arguments}") +``` + +## مثال عملي: بناء واجهة مستخدم مع البث + +إليك مثالاً كاملاً يوضح كيفية بناء تطبيق تفاعلي مع البث: + +```python Code +import asyncio +from crewai import Agent, Crew, Task +from crewai.types.streaming import StreamChunkType + +async def interactive_research(): + # Create crew with streaming enabled + researcher = Agent( + role="Research Analyst", + goal="Provide detailed analysis on any topic", + backstory="You are an expert researcher with broad knowledge.", + ) + + task = Task( + description="Research and analyze: {topic}", + expected_output="A comprehensive analysis with key insights", + agent=researcher, + ) + + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True, + verbose=False + ) + + # Get user input + topic = input("Enter a topic to research: ") + + print(f"\n{'='*60}") + print(f"Researching: {topic}") + print(f"{'='*60}\n") + + # Start streaming execution + streaming = await crew.kickoff_async(inputs={"topic": topic}) + + current_task = "" + async for chunk in streaming: + # Show task transitions + if chunk.task_name != current_task: + current_task = chunk.task_name + print(f"\n[{chunk.agent_role}] Working on: {chunk.task_name}") + print("-" * 60) + + # Display text chunks + if chunk.chunk_type == StreamChunkType.TEXT: + print(chunk.content, end="", flush=True) + + # Display tool calls + elif chunk.chunk_type == StreamChunkType.TOOL_CALL and chunk.tool_call: + print(f"\n🔧 Using tool: {chunk.tool_call.tool_name}") + + # Show final result + result = streaming.result + print(f"\n\n{'='*60}") + print("Analysis Complete!") + print(f"{'='*60}") + print(f"\nToken Usage: {result.token_usage}") + +asyncio.run(interactive_research()) +``` + +## حالات الاستخدام + +البث ذو قيمة خاصة لـ: + +- **التطبيقات التفاعلية**: تقديم تغذية راجعة فورية للمستخدمين أثناء عمل الوكلاء +- **المهام طويلة التشغيل**: عرض التقدم للبحث والتحليل أو توليد المحتوى +- **التصحيح والمراقبة**: مراقبة سلوك الوكلاء واتخاذ القرارات في الوقت الفعلي +- **تجربة المستخدم**: تقليل زمن الاستجابة المتصور بعرض نتائج تدريجية +- **لوحات المعلومات الحية**: بناء واجهات مراقبة تعرض حالة تنفيذ الطاقم + +## الإلغاء وتنظيف الموارد + +يدعم `CrewStreamingOutput` الإلغاء السلس بحيث يتوقف العمل الجاري فوراً عند انقطاع اتصال المستهلك. + +### مدير السياق غير المتزامن + +```python Code +streaming = await crew.akickoff(inputs={"topic": "AI"}) + +async with streaming: + async for chunk in streaming: + print(chunk.content, end="", flush=True) +``` + +### الإلغاء الصريح + +```python Code +streaming = await crew.akickoff(inputs={"topic": "AI"}) +try: + async for chunk in streaming: + print(chunk.content, end="", flush=True) +finally: + await streaming.aclose() # غير متزامن + # streaming.close() # المكافئ المتزامن +``` + +بعد الإلغاء، يكون كل من `streaming.is_cancelled` و `streaming.is_completed` بقيمة `True`. كل من `aclose()` و `close()` متساويان القوة. + +## ملاحظات مهمة + +- يفعّل البث تلقائياً بث LLM لجميع الوكلاء في الطاقم +- يجب التكرار عبر جميع الأجزاء قبل الوصول إلى خاصية `.result` +- لـ `kickoff_for_each_async()` مع البث، استخدم `.results` (بصيغة الجمع) للحصول على جميع المخرجات +- يضيف البث حملاً ضئيلاً ويمكن أن يحسن الأداء المتصور فعلياً +- يتضمن كل جزء سياقاً كاملاً (المهمة، الوكيل، نوع الجزء) لواجهات مستخدم غنية + +## معالجة الأخطاء + +التعامل مع الأخطاء أثناء تنفيذ البث: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +try: + for chunk in streaming: + print(chunk.content, end="", flush=True) + + result = streaming.result + print(f"\nSuccess: {result.raw}") + +except Exception as e: + print(f"\nError during streaming: {e}") + if streaming.is_completed: + print("Streaming completed but an error occurred") +``` + +من خلال الاستفادة من البث، يمكنك بناء تطبيقات أكثر استجابة وتفاعلية مع CrewAI، مما يوفر للمستخدمين رؤية فورية لتنفيذ الوكلاء والنتائج. diff --git a/docs/v1.15.13/ar/learn/streaming-flow-execution.mdx b/docs/v1.15.13/ar/learn/streaming-flow-execution.mdx new file mode 100644 index 0000000000..4341ec932b --- /dev/null +++ b/docs/v1.15.13/ar/learn/streaming-flow-execution.mdx @@ -0,0 +1,479 @@ +--- +title: بث تنفيذ التدفق +description: بث المخرجات في الوقت الفعلي من تنفيذ تدفق CrewAI الخاص بك +icon: wave-pulse +mode: "wide" +--- + +## مقدمة + +تدعم تدفقات CrewAI بث المخرجات، مما يتيح لك استلام تحديثات فورية أثناء تنفيذ تدفقك. تمكّنك هذه الميزة من بناء تطبيقات متجاوبة تعرض النتائج تدريجياً وتوفر تحديثات تقدم حية وتخلق تجربة مستخدم أفضل لسير العمل طويلة التشغيل. + +## كيف يعمل بث التدفق + +عند تفعيل البث في تدفق، يلتقط CrewAI ويبث المخرجات من أي أطقم أو استدعاءات LLM أو أدوات أو أحداث دورة حياة داخل التدفق. يقدم البث عناصر `StreamFrame` مرتبة تحتوي على محتوى قابل للطباعة وبيانات حدث مهيكلة مع تقدم التنفيذ. + +## تفعيل البث + +لتفعيل البث، عيّن خاصية `stream` إلى `True` في فئة التدفق الخاصة بك: + +```python Code +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Task + +class ResearchFlow(Flow): + stream = True # Enable streaming for the entire flow + + @start() + def initialize(self): + return {"topic": "AI trends"} + + @listen(initialize) + def research_topic(self, data): + researcher = Agent( + role="Research Analyst", + goal="Research topics thoroughly", + backstory="Expert researcher with analytical skills", + ) + + task = Task( + description="Research {topic} and provide insights", + expected_output="Detailed research findings", + agent=researcher, + ) + + crew = Crew( + agents=[researcher], + tasks=[task], + ) + + return crew.kickoff(inputs=data) +``` + +## البث المتزامن + +عند استدعاء `kickoff()` على تدفق مع تفعيل البث، يُرجع جلسة stream تنتج عناصر `StreamFrame` مرتبة: + +```python Code +flow = ResearchFlow() + +# Start streaming execution +streaming = flow.kickoff() + +# Iterate over stream items as they arrive +for item in streaming: + print(item.content, end="", flush=True) + +# Access the final result after streaming completes +result = streaming.result +print(f"\n\nFinal output: {result}") +``` + +### معلومات عنصر البث + +يوفر كل عنصر محتوى قابلاً للطباعة وبيانات حدث مهيكلة: + +```python Code +streaming = flow.kickoff() + +for item in streaming: + print(f"Channel: {item.channel}") + print(f"Type: {item.type}") + print(f"Content: {item.content}") + print(f"Event payload: {item.event}") +``` + +### الوصول إلى خصائص البث + +توفر جلسة stream خصائص وطرق مفيدة: + +```python Code +streaming = flow.kickoff() + +# Iterate and collect items +for item in streaming: + print(item.content, end="", flush=True) + +# After iteration completes +print(f"\nCompleted: {streaming.is_completed}") +print(f"Total frames: {len(streaming.frames)}") +print(f"Final result: {streaming.result}") +``` + +## البث غير المتزامن + +للتطبيقات غير المتزامنة، استخدم `kickoff_async()` مع التكرار غير المتزامن: + +```python Code +import asyncio + +async def stream_flow(): + flow = ResearchFlow() + + # Start async streaming + streaming = await flow.kickoff_async() + + # Async iteration over stream items + async for item in streaming: + print(item.content, end="", flush=True) + + # Access final result + result = streaming.result + print(f"\n\nFinal output: {result}") + +asyncio.run(stream_flow()) +``` + +## البث مع التدفقات متعددة الخطوات + +يعمل البث بسلاسة عبر خطوات تدفق متعددة، بما في ذلك التدفقات التي تنفذ أطقم متعددة: + +```python Code +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Task + +class MultiStepFlow(Flow): + stream = True + + @start() + def research_phase(self): + """First crew: Research the topic.""" + researcher = Agent( + role="Research Analyst", + goal="Gather comprehensive information", + backstory="Expert at finding relevant information", + ) + + task = Task( + description="Research AI developments in healthcare", + expected_output="Research findings on AI in healthcare", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[task]) + result = crew.kickoff() + + self.state["research"] = result.raw + return result.raw + + @listen(research_phase) + def analysis_phase(self, research_data): + """Second crew: Analyze the research.""" + analyst = Agent( + role="Data Analyst", + goal="Analyze information and extract insights", + backstory="Expert at identifying patterns and trends", + ) + + task = Task( + description="Analyze this research: {research}", + expected_output="Key insights and trends", + agent=analyst, + ) + + crew = Crew(agents=[analyst], tasks=[task]) + return crew.kickoff(inputs={"research": research_data}) + + +# Stream across both phases +flow = MultiStepFlow() +streaming = flow.kickoff() + +current_step = "" +for item in streaming: + # Track which flow step is executing + step_name = item.event.get("method_name") or item.event.get("task_name") + if step_name and step_name != current_step: + current_step = step_name + print(f"\n\n=== {step_name} ===\n") + + print(item.content, end="", flush=True) + +result = streaming.result +print(f"\n\nFinal analysis: {result}") +``` + +## مثال عملي: لوحة معلومات التقدم + +إليك مثالاً كاملاً يوضح كيفية بناء لوحة معلومات تقدم مع البث: + +```python Code +import asyncio +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Task + +class ResearchPipeline(Flow): + stream = True + + @start() + def gather_data(self): + researcher = Agent( + role="Data Gatherer", + goal="Collect relevant information", + backstory="Skilled at finding quality sources", + ) + + task = Task( + description="Gather data on renewable energy trends", + expected_output="Collection of relevant data points", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[task]) + result = crew.kickoff() + self.state["data"] = result.raw + return result.raw + + @listen(gather_data) + def analyze_data(self, data): + analyst = Agent( + role="Data Analyst", + goal="Extract meaningful insights", + backstory="Expert at data analysis", + ) + + task = Task( + description="Analyze: {data}", + expected_output="Key insights and trends", + agent=analyst, + ) + + crew = Crew(agents=[analyst], tasks=[task]) + return crew.kickoff(inputs={"data": data}) + + +async def run_with_dashboard(): + flow = ResearchPipeline() + + print("="*60) + print("RESEARCH PIPELINE DASHBOARD") + print("="*60) + + streaming = await flow.kickoff_async() + + current_agent = "" + current_task = "" + frame_count = 0 + + async for item in streaming: + frame_count += 1 + + # Display phase transitions + task_name = item.event.get("task_name", "") + agent_role = item.event.get("agent_role", "") + if task_name and task_name != current_task: + current_task = task_name + current_agent = agent_role + print(f"\n\n📋 Phase: {current_task}") + print(f"👤 Agent: {current_agent}") + print("-" * 60) + + # Display text output + if item.content: + print(item.content, end="", flush=True) + + # Display tool usage + elif item.channel == "tools": + print(f"\n🔧 Tool event: {item.type}") + + # Show completion summary + result = streaming.result + print(f"\n\n{'='*60}") + print("PIPELINE COMPLETE") + print(f"{'='*60}") + print(f"Total frames: {frame_count}") + print(f"Final output length: {len(str(result))} characters") + +asyncio.run(run_with_dashboard()) +``` + +## البث مع إدارة الحالة + +يعمل البث بشكل طبيعي مع إدارة حالة التدفق: + +```python Code +from pydantic import BaseModel + +class AnalysisState(BaseModel): + topic: str = "" + research: str = "" + insights: str = "" + +class StatefulStreamingFlow(Flow[AnalysisState]): + stream = True + + @start() + def research(self): + # State is available during streaming + topic = self.state.topic + print(f"Researching: {topic}") + + researcher = Agent( + role="Researcher", + goal="Research topics thoroughly", + backstory="Expert researcher", + ) + + task = Task( + description=f"Research {topic}", + expected_output="Research findings", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[task]) + result = crew.kickoff() + + self.state.research = result.raw + return result.raw + + @listen(research) + def analyze(self, research): + # Access updated state + print(f"Analyzing {len(self.state.research)} chars of research") + + analyst = Agent( + role="Analyst", + goal="Extract insights", + backstory="Expert analyst", + ) + + task = Task( + description="Analyze: {research}", + expected_output="Key insights", + agent=analyst, + ) + + crew = Crew(agents=[analyst], tasks=[task]) + result = crew.kickoff(inputs={"research": research}) + + self.state.insights = result.raw + return result.raw + + +# Run with streaming +flow = StatefulStreamingFlow() +streaming = flow.kickoff(inputs={"topic": "quantum computing"}) + +for item in streaming: + print(item.content, end="", flush=True) + +result = streaming.result +print(f"\n\nFinal state:") +print(f"Topic: {flow.state.topic}") +print(f"Research length: {len(flow.state.research)}") +print(f"Insights length: {len(flow.state.insights)}") +``` + +## حالات الاستخدام + +بث التدفق ذو قيمة خاصة لـ: + +- **سير العمل متعددة المراحل**: عرض التقدم عبر مراحل البحث والتحليل والتوليف +- **خطوط الأنابيب المعقدة**: توفير رؤية لتدفقات معالجة البيانات طويلة التشغيل +- **التطبيقات التفاعلية**: بناء واجهات مستخدم متجاوبة تعرض النتائج الوسيطة +- **المراقبة والتصحيح**: مراقبة تنفيذ التدفق وتفاعلات الأطقم في الوقت الفعلي +- **تتبع التقدم**: إظهار المرحلة الحالية من سير العمل للمستخدمين +- **لوحات المعلومات الحية**: إنشاء واجهات مراقبة لتدفقات الإنتاج + +## قنوات إطارات البث + +ينتج بث التدفق عناصر `StreamFrame` عبر عدة قنوات: + +### إطارات LLM + +محتوى نصي قياسي من استجابات LLM: + +```python Code +for item in streaming: + if item.channel == "llm" and item.content: + print(item.content, end="", flush=True) +``` + +### إطارات الأدوات + +معلومات حول استدعاءات الأدوات داخل التدفق: + +```python Code +for item in streaming: + if item.channel == "tools": + print(f"\nTool event: {item.type}") + print(f"Payload: {item.event}") +``` + +## معالجة الأخطاء + +التعامل مع الأخطاء بأناقة أثناء البث: + +```python Code +flow = ResearchFlow() +streaming = flow.kickoff() + +try: + for item in streaming: + print(item.content, end="", flush=True) + + result = streaming.result + print(f"\nSuccess! Result: {result}") + +except Exception as e: + print(f"\nError during flow execution: {e}") + if streaming.is_completed: + print("Streaming completed but flow encountered an error") +``` + +## الإلغاء وتنظيف الموارد + +تدعم جلسة stream الإلغاء السلس بحيث يتوقف العمل الجاري فوراً عند انقطاع اتصال المستهلك. + +### مدير السياق غير المتزامن + +```python Code +streaming = await flow.kickoff_async() + +async with streaming: + async for item in streaming: + print(item.content, end="", flush=True) +``` + +### الإلغاء الصريح + +```python Code +streaming = await flow.kickoff_async() +try: + async for item in streaming: + print(item.content, end="", flush=True) +finally: + await streaming.aclose() # غير متزامن + # streaming.close() # المكافئ المتزامن +``` + +بعد الإلغاء، يكون كل من `streaming.is_cancelled` و `streaming.is_completed` بقيمة `True`. كل من `aclose()` و `close()` متساويان القوة. + +## ملاحظات مهمة + +- يفعّل البث تلقائياً بث LLM لأي أطقم مستخدمة داخل التدفق +- يجب التكرار عبر جميع عناصر stream قبل الوصول إلى خاصية `.result` +- يعمل البث مع كل من حالة التدفق المنظمة وغير المنظمة +- يلتقط بث التدفق المخرجات من جميع الأطقم واستدعاءات LLM في التدفق +- يتضمن كل إطار سياق حدث مهيكلاً مثل القناة والنوع والنطاق والحمولة +- يضيف البث حملاً ضئيلاً لتنفيذ التدفق + +## الدمج مع تصور التدفق + +يمكنك دمج البث مع تصور التدفق لتوفير صورة كاملة: + +```python Code +# Generate flow visualization +flow = ResearchFlow() +flow.plot("research_flow") # Creates HTML visualization + +# Run with streaming +streaming = flow.kickoff() +for item in streaming: + print(item.content, end="", flush=True) + +result = streaming.result +print(f"\nFlow complete! View structure at: research_flow.html") +``` + +من خلال الاستفادة من بث التدفق، يمكنك بناء تطبيقات متطورة ومتجاوبة توفر للمستخدمين رؤية فورية لسير العمل المعقدة متعددة المراحل، مما يجعل أتمتة الذكاء الاصطناعي الخاصة بك أكثر شفافية وجاذبية. diff --git a/docs/v1.15.13/ar/learn/streaming-runtime-contract.mdx b/docs/v1.15.13/ar/learn/streaming-runtime-contract.mdx new file mode 100644 index 0000000000..1107c1590a --- /dev/null +++ b/docs/v1.15.13/ar/learn/streaming-runtime-contract.mdx @@ -0,0 +1,194 @@ +--- +title: عقد بث وقت التشغيل +description: بث إطارات وقت تشغيل مرتبة من التدفقات واستدعاءات LLM المباشرة ودورات المحادثة. +icon: tower-broadcast +mode: "wide" +--- + +## نظرة عامة + +يوفر CrewAI عقد بث قائمًا على الإطارات للأنظمة التي تحتاج إلى أكثر من أجزاء نصية بسيطة. يصدر العقد كائنات `StreamFrame` مرتبة لأحداث دورة حياة Flow، وتوكنات LLM المباشرة، ونشاط الأدوات، ورسائل المحادثة، والأحداث المخصصة. + +استخدم هذه الواجهة عندما تبني واجهة مستخدم، أو جسر خدمة، أو تطبيق طرفية، أو وقت تشغيل نشر يحتاج إلى تدفق ثابت من الأحداث المهيكلة أثناء تشغيل Flow أو دورة محادثة أو استدعاء LLM مباشر. + +## StreamFrame + +لكل إطار نفس الغلاف: + +```python +from crewai.types.streaming import StreamFrame + +frame.id # معرف إطار فريد +frame.seq # ترتيب محلي للتنفيذ، عند توفره +frame.type # نوع الحدث المصدر، مثل "flow_started" +frame.channel # "llm", "flow", "tools", "messages", "lifecycle", or "custom" +frame.namespace # نطاق المصدر/وقت التشغيل +frame.timestamp # طابع وقت الحدث +frame.parent_id # معرف الحدث الأب، عند توفره +frame.previous_id # معرف الحدث السابق، عند توفره +frame.data # حمولة الحدث +frame.event # اسم بديل لـ frame.data +frame.content # نص قابل للطباعة لإطارات التوكن، وإلا "" +``` + +حقل `channel` هو أسرع طريقة لتوجيه الإطارات في المستهلكين: + +| القناة | تحتوي على | +|--------|-----------| +| `llm` | توكنات وأجزاء التفكير من أحداث بث LLM | +| `flow` | دورة حياة Flow، وتنفيذ الدوال، والتوجيه، وأحداث الإيقاف/الاستئناف | +| `tools` | أحداث استخدام الأدوات | +| `messages` | أحداث سجل المحادثة | +| `lifecycle` | أحداث دورة حياة وقت التشغيل التي لا تخص قناة أخرى | +| `custom` | أحداث لا تُطابق قناة مدمجة | + +يحافظ `frame.type` على نوع الحدث المصدر، حتى يتمكن المستهلكون من التعامل مع أحداث محددة داخل القناة. + +## بث Flow + +عيّن `stream=True` على Flow لجعل `kickoff()` يعيد جلسة stream: + +```python +from crewai.flow import Flow, start + + +class ReportFlow(Flow): + @start() + def generate(self): + return "done" + + +flow = ReportFlow(stream=True) +stream = flow.kickoff() + +with stream: + for chunk in stream: + print(chunk.content, end="", flush=True) + if chunk.type == "tool_usage_started": + print(chunk.event["tool_name"]) + +result = stream.result +``` + +يجب استهلاك stream قبل قراءة `stream.result`. يؤدي الوصول إلى النتيجة مبكرًا إلى رفع `RuntimeError` حتى لا يتعامل المستهلكون بالخطأ مع تشغيل جزئي على أنه مكتمل. + +يمكنك أيضًا استدعاء `flow.stream_events(...)` مباشرة عندما تريد البث لاستدعاء واحد بدون تعيين `stream=True` على مثيل Flow. + +## التصفية حسب القناة + +يوفر `StreamSession` إسقاطات حسب القناة تحافظ على ترتيب الإطارات العالمي داخل القناة المحددة: + +```python +stream = flow.stream_events() + +with stream: + for frame in stream.llm: + print(frame.content, end="", flush=True) + +result = stream.result +``` + +الإسقاطات المتاحة هي: + +| الإسقاط | الإطارات | +|---------|----------| +| `stream.events` | كل الإطارات | +| `stream.llm` | إطارات LLM | +| `stream.messages` | إطارات رسائل المحادثة | +| `stream.flow` | إطارات Flow | +| `stream.tools` | إطارات الأدوات | +| `stream.interleave([...])` | مجموعة مختارة من القنوات | + +استخدم `stream.interleave(["flow", "llm", "messages"])` عندما يريد المستهلك بعض القنوات فقط لكنه ما زال يحتاج إلى ترتيبها النسبي. + +## البث غير المتزامن + +استخدم `astream()` للمستهلكين غير المتزامنين: + +```python +flow = ReportFlow() +stream = flow.astream() + +async with stream: + async for chunk in stream.events: + print(chunk.channel, chunk.type, chunk.content) + +result = stream.result +``` + +تملك الجلسة غير المتزامنة نفس إسقاطات الجلسة المتزامنة. + +## بث استدعاء LLM مباشر + +ما زال `llm.call(...)` يعيد النتيجة النهائية المجمعة. استخدم `llm.stream_events(...)` عندما تريد التكرار على الأجزاء فور وصولها مع الحفاظ على حمولة الحدث المهيكلة: + +```python +from crewai import LLM + + +llm = LLM(model="gpt-4o-mini") +stream = llm.stream_events( + messages=[ + { + "role": "user", + "content": "Explain CrewAI streaming in two short sentences.", + } + ] +) + +with stream: + for chunk in stream: + print(chunk.content, end="", flush=True) + +result = stream.result +``` + +يفعل `llm.stream_events(...)` البث مؤقتًا للاستدعاء المغلف ثم يستعيد إعداد `stream` السابق في LLM بعد ذلك. تستمر تكاملات المزودين في إصدار أحداث بث LLM الأساسية؛ يوفر هذا المساعد واجهة مكرر مشتركة فوق تلك الأحداث لكل مزودي LLM. + +## دورات المحادثة + +يمكن للتدفقات المحادثية بث دورة مستخدم واحدة باستخدام `stream_turn()`: + +```python +from crewai import Flow +from crewai.experimental.conversational import ConversationConfig, ConversationState + + +@ConversationConfig(llm="gpt-4o-mini", defer_trace_finalization=True) +class ChatFlow(Flow[ConversationState]): + conversational = True + + +flow = ChatFlow() +stream = flow.stream_turn("What can you help me with?", session_id="session-1") + +with stream: + for frame in stream.events: + if frame.channel == "llm" and frame.type == "llm_stream_chunk": + print(frame.content, end="", flush=True) + +reply = stream.result +``` + +أثناء `stream_turn()`، يفعّل مسار الإجابة المحادثية المدمج بث توكنات LLM لذلك الدور ثم يستعيد إعداد `stream` السابق في LLM بعد ذلك. يجب على معالجات المسارات المخصصة التي تنشئ Agents أو مثيلات LLM خاصة بها تهيئة تلك النماذج للبث إذا احتاجت إلى إخراج على مستوى التوكن. + +## التنظيف + +استخدم الجلسة كمدير سياق عندما يكون ذلك ممكنًا. إذا انقطع اتصال العميل قبل استهلاك stream بالكامل، فأغلق الجلسة صراحة: + +```python +stream = flow.stream_events() + +try: + for frame in stream.events: + print(frame.type) +finally: + if not stream.is_exhausted: + stream.close() +``` + +للتدفقات غير المتزامنة، استخدم `await stream.aclose()`. + +## بث الأجزاء القديم + +ما زال بث Crew مع `stream=True` يعيد واجهة `CrewStreamingOutput` المعتمدة على الأجزاء والموضحة في [بث تنفيذ Crew](/ar/learn/streaming-crew-execution). وما زالت استدعاءات `llm.call(...)` المباشرة تعيد نتيجة LLM النهائية. عقد الإطارات مخصص لأوقات التشغيل التي تحتاج إلى غلاف حدث ثابت عبر Flows، واستدعاءات LLM المباشرة، ودورات المحادثة، والأدوات، والرسائل. diff --git a/docs/v1.15.13/ar/learn/tool-hooks.mdx b/docs/v1.15.13/ar/learn/tool-hooks.mdx new file mode 100644 index 0000000000..372db59242 --- /dev/null +++ b/docs/v1.15.13/ar/learn/tool-hooks.mdx @@ -0,0 +1,480 @@ +--- +title: خطافات استدعاء الأدوات +description: تعلم كيفية استخدام خطافات استدعاء الأدوات لاعتراض وتعديل والتحكم في تنفيذ الأدوات في CrewAI +mode: "wide" +--- + +توفر خطافات استدعاء الأدوات تحكماً دقيقاً في تنفيذ الأدوات أثناء عمليات الوكيل. تتيح لك هذه الخطافات اعتراض استدعاءات الأدوات وتعديل المدخلات وتحويل المخرجات وتنفيذ فحوصات السلامة وإضافة تسجيل أو مراقبة شاملة. + +## نظرة عامة + +تُنفذ خطافات الأدوات في نقطتين حرجتين: +- **قبل استدعاء الأداة**: تعديل المدخلات، التحقق من المعاملات، أو حظر التنفيذ +- **بعد استدعاء الأداة**: تحويل النتائج، تنقية المخرجات، أو تسجيل تفاصيل التنفيذ + +## أنواع الخطافات + +### خطافات ما قبل استدعاء الأداة + +تُنفذ قبل كل تنفيذ أداة، ويمكن لهذه الخطافات: +- فحص وتعديل مدخلات الأداة +- حظر تنفيذ الأداة بناءً على شروط +- تنفيذ بوابات موافقة للعمليات الخطرة +- التحقق من المعاملات +- تسجيل استدعاءات الأدوات + +**التوقيع:** +```python +def before_hook(context: ToolCallHookContext) -> bool | None: + # Return False to block execution + # Return True or None to allow execution + ... +``` + +### خطافات ما بعد استدعاء الأداة + +تُنفذ بعد كل تنفيذ أداة، ويمكن لهذه الخطافات: +- تعديل أو تنقية نتائج الأداة +- إضافة بيانات وصفية أو تنسيق +- تسجيل نتائج التنفيذ +- تنفيذ التحقق من النتائج +- تحويل تنسيقات المخرجات + +**التوقيع:** +```python +def after_hook(context: ToolCallHookContext) -> str | None: + # Return modified result string + # Return None to keep original result + ... +``` + +## سياق خطاف الأداة + +يوفر كائن `ToolCallHookContext` وصولاً شاملاً لحالة تنفيذ الأداة: + +```python +class ToolCallHookContext: + tool_name: str # Name of the tool being called + tool_input: dict[str, Any] # Mutable tool input parameters + tool: CrewStructuredTool # Tool instance reference + agent: Agent | BaseAgent | None # Agent executing the tool + task: Task | None # Current task + crew: Crew | None # Crew instance + tool_result: str | None # Tool result (after hooks only) +``` + +### تعديل مدخلات الأداة + +**مهم:** قم دائماً بتعديل مدخلات الأداة في مكانها: + +```python +# ✅ Correct - modify in-place +def sanitize_input(context: ToolCallHookContext) -> None: + context.tool_input['query'] = context.tool_input['query'].lower() + +# ❌ Wrong - replaces dict reference +def wrong_approach(context: ToolCallHookContext) -> None: + context.tool_input = {'query': 'new query'} +``` + +## طرق التسجيل + +### 1. تسجيل الخطافات العامة + +تسجيل خطافات تنطبق على جميع استدعاءات الأدوات عبر جميع الأطقم: + +```python +from crewai.hooks import register_before_tool_call_hook, register_after_tool_call_hook + +def log_tool_call(context): + print(f"Tool: {context.tool_name}") + print(f"Input: {context.tool_input}") + return None # Allow execution + +register_before_tool_call_hook(log_tool_call) +``` + +### 2. التسجيل باستخدام المزخرفات + +استخدم المزخرفات لصياغة أنظف: + +```python +from crewai.hooks import before_tool_call, after_tool_call + +@before_tool_call +def block_dangerous_tools(context): + dangerous_tools = ['delete_database', 'drop_table', 'rm_rf'] + if context.tool_name in dangerous_tools: + print(f"⛔ Blocked dangerous tool: {context.tool_name}") + return False # Block execution + return None + +@after_tool_call +def sanitize_results(context): + if context.tool_result and "password" in context.tool_result.lower(): + return context.tool_result.replace("password", "[REDACTED]") + return None +``` + +### 3. خطافات نطاق الطاقم + +تسجيل خطافات لمثيل طاقم محدد: + +```python +@CrewBase +class MyProjCrew: + @before_tool_call_crew + def validate_tool_inputs(self, context): + # Only applies to this crew + if context.tool_name == "web_search": + if not context.tool_input.get('query'): + print("❌ Invalid search query") + return False + return None + + @after_tool_call_crew + def log_tool_results(self, context): + # Crew-specific tool logging + print(f"✅ {context.tool_name} completed") + return None + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +## حالات الاستخدام الشائعة + +### 1. حواجز السلامة + +```python +@before_tool_call +def safety_check(context: ToolCallHookContext) -> bool | None: + destructive_tools = [ + 'delete_file', + 'drop_table', + 'remove_user', + 'system_shutdown' + ] + + if context.tool_name in destructive_tools: + print(f"🛑 Blocked destructive tool: {context.tool_name}") + return False + + sensitive_tools = ['send_email', 'post_to_social_media', 'charge_payment'] + if context.tool_name in sensitive_tools: + print(f"⚠️ Executing sensitive tool: {context.tool_name}") + + return None +``` + +### 2. بوابة الموافقة البشرية + +```python +@before_tool_call +def require_approval_for_actions(context: ToolCallHookContext) -> bool | None: + approval_required = [ + 'send_email', + 'make_purchase', + 'delete_file', + 'post_message' + ] + + if context.tool_name in approval_required: + response = context.request_human_input( + prompt=f"Approve {context.tool_name}?", + default_message=f"Input: {context.tool_input}\nType 'yes' to approve:" + ) + + if response.lower() != 'yes': + print(f"❌ Tool execution denied: {context.tool_name}") + return False + + return None +``` + +### 3. التحقق من المدخلات وتنقيتها + +```python +@before_tool_call +def validate_and_sanitize_inputs(context: ToolCallHookContext) -> bool | None: + if context.tool_name == 'web_search': + query = context.tool_input.get('query', '') + if len(query) < 3: + print("❌ Search query too short") + return False + context.tool_input['query'] = query.strip().lower() + + if context.tool_name == 'read_file': + path = context.tool_input.get('path', '') + if '..' in path or path.startswith('/'): + print("❌ Invalid file path") + return False + + return None +``` + +### 4. تنقية النتائج + +```python +@after_tool_call +def sanitize_sensitive_data(context: ToolCallHookContext) -> str | None: + if not context.tool_result: + return None + + import re + result = context.tool_result + + result = re.sub( + r'(api[_-]?key|token)["\']?\s*[:=]\s*["\']?[\w-]+', + r'\1: [REDACTED]', + result, + flags=re.IGNORECASE + ) + + result = re.sub( + r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', + '[EMAIL-REDACTED]', + result + ) + + result = re.sub( + r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', + '[CARD-REDACTED]', + result + ) + + return result +``` + +### 5. تحليلات استخدام الأدوات + +```python +import time +from collections import defaultdict + +tool_stats = defaultdict(lambda: {'count': 0, 'total_time': 0, 'failures': 0}) + +@before_tool_call +def start_timer(context: ToolCallHookContext) -> None: + context.tool_input['_start_time'] = time.time() + return None + +@after_tool_call +def track_tool_usage(context: ToolCallHookContext) -> None: + start_time = context.tool_input.get('_start_time', time.time()) + duration = time.time() - start_time + + tool_stats[context.tool_name]['count'] += 1 + tool_stats[context.tool_name]['total_time'] += duration + + if not context.tool_result or 'error' in context.tool_result.lower(): + tool_stats[context.tool_name]['failures'] += 1 + + print(f""" + 📊 Tool Stats for {context.tool_name}: + - Executions: {tool_stats[context.tool_name]['count']} + - Avg Time: {tool_stats[context.tool_name]['total_time'] / tool_stats[context.tool_name]['count']:.2f}s + - Failures: {tool_stats[context.tool_name]['failures']} + """) + + return None +``` + +### 6. تحديد المعدل + +```python +from collections import defaultdict +from datetime import datetime, timedelta + +tool_call_history = defaultdict(list) + +@before_tool_call +def rate_limit_tools(context: ToolCallHookContext) -> bool | None: + tool_name = context.tool_name + now = datetime.now() + + tool_call_history[tool_name] = [ + call_time for call_time in tool_call_history[tool_name] + if now - call_time < timedelta(minutes=1) + ] + + if len(tool_call_history[tool_name]) >= 10: + print(f"🚫 Rate limit exceeded for {tool_name}") + return False + + tool_call_history[tool_name].append(now) + return None +``` + +### 7. تخزين نتائج الأدوات مؤقتاً + +```python +import hashlib +import json + +tool_cache = {} + +def cache_key(tool_name: str, tool_input: dict) -> str: + """Generate cache key from tool name and input.""" + input_str = json.dumps(tool_input, sort_keys=True) + return hashlib.md5(f"{tool_name}:{input_str}".encode()).hexdigest() + +@before_tool_call +def check_cache(context: ToolCallHookContext) -> bool | None: + key = cache_key(context.tool_name, context.tool_input) + if key in tool_cache: + print(f"💾 Cache hit for {context.tool_name}") + return None + +@after_tool_call +def cache_result(context: ToolCallHookContext) -> None: + if context.tool_result: + key = cache_key(context.tool_name, context.tool_input) + tool_cache[key] = context.tool_result + print(f"💾 Cached result for {context.tool_name}") + return None +``` + +### 8. تسجيل التصحيح + +```python +@before_tool_call +def debug_tool_call(context: ToolCallHookContext) -> None: + print(f""" + 🔍 Tool Call Debug: + - Tool: {context.tool_name} + - Agent: {context.agent.role if context.agent else 'Unknown'} + - Task: {context.task.description[:50] if context.task else 'Unknown'}... + - Input: {context.tool_input} + """) + return None + +@after_tool_call +def debug_tool_result(context: ToolCallHookContext) -> None: + if context.tool_result: + result_preview = context.tool_result[:200] + print(f"✅ Result Preview: {result_preview}...") + else: + print("⚠️ No result returned") + return None +``` + +## إدارة الخطافات + +### إلغاء تسجيل الخطافات + +```python +from crewai.hooks import ( + unregister_before_tool_call_hook, + unregister_after_tool_call_hook +) + +def my_hook(context): + ... + +register_before_tool_call_hook(my_hook) +success = unregister_before_tool_call_hook(my_hook) +print(f"Unregistered: {success}") +``` + +### مسح الخطافات + +```python +from crewai.hooks import ( + clear_before_tool_call_hooks, + clear_after_tool_call_hooks, + clear_all_tool_call_hooks +) + +count = clear_before_tool_call_hooks() +print(f"Cleared {count} before hooks") + +before_count, after_count = clear_all_tool_call_hooks() +print(f"Cleared {before_count} before and {after_count} after hooks") +``` + +### عرض الخطافات المسجلة + +```python +from crewai.hooks import ( + get_before_tool_call_hooks, + get_after_tool_call_hooks +) + +before_hooks = get_before_tool_call_hooks() +after_hooks = get_after_tool_call_hooks() + +print(f"Registered: {len(before_hooks)} before, {len(after_hooks)} after") +``` + +## أفضل الممارسات + +1. **اجعل الخطافات مركزة**: يجب أن يكون لكل خطاف مسؤولية واحدة +2. **تجنب الحسابات الثقيلة**: تُنفذ الخطافات في كل استدعاء أداة +3. **تعامل مع الأخطاء بأناقة**: استخدم try-except لمنع فشل الخطافات +4. **استخدم تلميحات الأنواع**: استفد من `ToolCallHookContext` لدعم أفضل في بيئة التطوير +5. **وثّق شروط الحظر**: وضّح متى ولماذا تُحظر الأدوات +6. **اختبر الخطافات بشكل مستقل**: اختبر الخطافات وحدوياً قبل الاستخدام في الإنتاج +7. **امسح الخطافات في الاختبارات**: استخدم `clear_all_tool_call_hooks()` بين تشغيلات الاختبار +8. **عدّل في المكان**: قم دائماً بتعديل `context.tool_input` في مكانه، ولا تستبدله +9. **سجّل القرارات المهمة**: خاصة عند حظر تنفيذ الأدوات +10. **راعِ الأداء**: خزّن عمليات التحقق المكلفة مؤقتاً عند الإمكان + +## معالجة الأخطاء + +```python +@before_tool_call +def safe_validation(context: ToolCallHookContext) -> bool | None: + try: + if not validate_input(context.tool_input): + return False + except Exception as e: + print(f"⚠️ Hook error: {e}") + return None # Allow execution despite error +``` + +## أمان الأنواع + +```python +from crewai.hooks import ToolCallHookContext, BeforeToolCallHookType, AfterToolCallHookType + +def my_before_hook(context: ToolCallHookContext) -> bool | None: + return None + +def my_after_hook(context: ToolCallHookContext) -> str | None: + return None + +register_before_tool_call_hook(my_before_hook) +register_after_tool_call_hook(my_after_hook) +``` + +## استكشاف الأخطاء وإصلاحها + +### الخطاف لا يُنفذ +- تحقق من أن الخطاف مسجل قبل تنفيذ الطاقم +- تحقق مما إذا كان خطاف سابق أرجع `False` (يحظر التنفيذ والخطافات اللاحقة) +- تأكد من أن توقيع الخطاف يطابق النوع المتوقع + +### تعديلات المدخلات لا تعمل +- استخدم التعديلات في المكان: `context.tool_input['key'] = value` +- لا تستبدل القاموس: `context.tool_input = {}` + +### تعديلات النتائج لا تعمل +- أرجع السلسلة النصية المعدلة من خطافات ما بعد +- إرجاع `None` يحتفظ بالنتيجة الأصلية +- تأكد من أن الأداة أرجعت نتيجة فعلاً + +### أداة محظورة بشكل غير متوقع +- تحقق من جميع خطافات ما قبل بحثاً عن شروط حظر +- تحقق من ترتيب تنفيذ الخطافات +- أضف تسجيل تصحيح لتحديد الخطاف الذي يحظر + +## الخاتمة + +توفر خطافات استدعاء الأدوات إمكانيات قوية للتحكم في تنفيذ الأدوات ومراقبتها في CrewAI. استخدمها لتنفيذ حواجز السلامة وبوابات الموافقة والتحقق من المدخلات وتنقية النتائج والتسجيل والتحليلات. مع معالجة الأخطاء المناسبة وأمان الأنواع، تُمكّن الخطافات أنظمة وكلاء آمنة وجاهزة للإنتاج مع مراقبة شاملة. diff --git a/docs/v1.15.13/ar/learn/using-annotations.mdx b/docs/v1.15.13/ar/learn/using-annotations.mdx new file mode 100644 index 0000000000..4bea3eb9f1 --- /dev/null +++ b/docs/v1.15.13/ar/learn/using-annotations.mdx @@ -0,0 +1,155 @@ +--- +title: "استخدام التعليقات التوضيحية في crew.py" +description: "تعلم كيفية استخدام التعليقات التوضيحية لتنظيم الوكلاء والمهام والمكونات بشكل صحيح في CrewAI" +icon: "at" +mode: "wide" +--- + +يشرح هذا الدليل كيفية استخدام التعليقات التوضيحية للإشارة بشكل صحيح إلى **الوكلاء** و**المهام** والمكونات الأخرى في ملف `crew.py` كلاسيكي. + + +المشاريع الجديدة التي تُنشأ عبر `crewai create crew ` هي JSON-first وتستخدم `crew.jsonc` مع `agents/*.jsonc`. استخدم هذا الدليل عند العمل في مشروع كلاسيكي أُنشئ عبر `crewai create crew --classic`، أو عند ترحيل مشروع Python/YAML موجود، أو عندما تحتاج تحكمًا عبر decorators في Python. + + +## مقدمة + +تُستخدم التعليقات التوضيحية في إطار عمل CrewAI لتزيين الفئات والطرق، مما يوفر بيانات وصفية ووظائف للمكونات المختلفة في طاقمك. في مشاريع Python/YAML الكلاسيكية، تنظم الكود الذي يحمّل `config/agents.yaml` و `config/tasks.yaml` ويعيد كائن `Crew`. + +## التعليقات التوضيحية المتاحة + +يوفر إطار عمل CrewAI التعليقات التوضيحية التالية: + +- `@CrewBase`: تُستخدم لتزيين فئة الطاقم الرئيسية. +- `@agent`: تزين الطرق التي تعرّف وتُرجع كائنات Agent. +- `@task`: تزين الطرق التي تعرّف وتُرجع كائنات Task. +- `@crew`: تزين الطريقة التي تنشئ وتُرجع كائن Crew. +- `@llm`: تزين الطرق التي تهيئ وتُرجع كائنات نماذج اللغة. +- `@tool`: تزين الطرق التي تهيئ وتُرجع كائنات الأدوات. +- `@callback`: تُستخدم لتعريف طرق الاستدعاء الراجع. +- `@output_json`: تُستخدم للطرق التي تُخرج بيانات JSON. +- `@output_pydantic`: تُستخدم للطرق التي تُخرج نماذج Pydantic. +- `@cache_handler`: تُستخدم لتعريف طرق معالجة التخزين المؤقت. + +## أمثلة الاستخدام + +لنمر عبر أمثلة لكيفية استخدام هذه التعليقات التوضيحية: + +### 1. فئة الطاقم الأساسية + +```python +@CrewBase +class LinkedinProfileCrew(): + """LinkedinProfile crew""" + agents_config = 'config/agents.yaml' + tasks_config = 'config/tasks.yaml' +``` + +تُستخدم التعليقة التوضيحية `@CrewBase` لتزيين فئة الطاقم الرئيسية. تحتوي هذه الفئة عادةً على الإعدادات والطرق لإنشاء الوكلاء والمهام والطاقم نفسه. + + +`@CrewBase` تفعل أكثر من مجرد تسجيل الفئة: + +- **تمهيد الإعدادات:** تبحث عن `agents_config` و `tasks_config` (القيمة الافتراضية `config/agents.yaml` و `config/tasks.yaml`) بجانب ملف الفئة، وتحملها عند الإنشاء، وتتراجع بأمان إلى قواميس فارغة إذا كانت الملفات مفقودة. +- **تنسيق المزخرفات:** تحتفظ بمراجع محفوظة لكل طريقة مُعلّمة بـ `@agent` أو `@task` أو `@before_kickoff` أو `@after_kickoff` بحيث يتم إنشاؤها مرة واحدة لكل طاقم وتُنفذ بترتيب الإعلان. +- **ربط الخطافات:** تربط تلقائياً خطافات التشغيل المحفوظة بكائن `Crew` المُرجع من طريقة `@crew`، مما يجعلها تعمل قبل وبعد `.kickoff()`. +- **تكامل MCP:** عندما تعرّف الفئة `mcp_server_params`، ينشئ `get_mcp_tools()` بكسل محول MCP server، ويملأ الأدوات المُعلنة، ويوقف خطاف ما بعد التشغيل الداخلي المحول. راجع [نظرة عامة على MCP](/ar/mcp/overview) لتفاصيل إعداد المحول. + + +### 2. تعريف الأداة + +```python +@tool +def myLinkedInProfileTool(self): + return LinkedInProfileTool() +``` + +تُستخدم التعليقة التوضيحية `@tool` لتزيين الطرق التي تُرجع كائنات أدوات. يمكن للوكلاء استخدام هذه الأدوات لأداء مهام محددة. + +### 3. تعريف LLM + +```python +@llm +def groq_llm(self): + api_key = os.getenv('api_key') + return ChatGroq(api_key=api_key, temperature=0, model_name="mixtral-8x7b-32768") +``` + +تُستخدم التعليقة التوضيحية `@llm` لتزيين الطرق التي تهيئ وتُرجع كائنات نماذج اللغة. تستخدم هذه النماذج من قبل الوكلاء لمهام معالجة اللغة الطبيعية. + +### 4. تعريف الوكيل + +```python +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'] + ) +``` + +تُستخدم التعليقة التوضيحية `@agent` لتزيين الطرق التي تعرّف وتُرجع كائنات Agent. + +### 5. تعريف المهمة + +```python +@task +def research_task(self) -> Task: + return Task( + config=self.tasks_config['research_linkedin_task'], + agent=self.researcher() + ) +``` + +تُستخدم التعليقة التوضيحية `@task` لتزيين الطرق التي تعرّف وتُرجع كائنات Task. تحدد هذه الطرق إعداد المهمة والوكيل المسؤول عنها. + +### 6. إنشاء الطاقم + +```python +@crew +def crew(self) -> Crew: + """Creates the LinkedinProfile crew""" + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +تُستخدم التعليقة التوضيحية `@crew` لتزيين الطريقة التي تنشئ وتُرجع كائن `Crew`. تجمع هذه الطريقة جميع المكونات (الوكلاء والمهام) في طاقم وظيفي. + +## إعداد YAML الكلاسيكي + +في المشاريع الكلاسيكية، تُخزن إعدادات الوكلاء عادةً في ملف YAML. إليك مثالاً على كيفية ظهور ملف `agents.yaml` لوكيل الباحث: + +```yaml +researcher: + role: > + LinkedIn Profile Senior Data Researcher + goal: > + Uncover detailed LinkedIn profiles based on provided name {name} and domain {domain} + Generate a Dall-E image based on domain {domain} + backstory: > + You're a seasoned researcher with a knack for uncovering the most relevant LinkedIn profiles. + Known for your ability to navigate LinkedIn efficiently, you excel at gathering and presenting + professional information clearly and concisely. + allow_delegation: False + verbose: True + llm: groq_llm + tools: + - myLinkedInProfileTool + - mySerperDevTool + - myDallETool +``` + +يتوافق إعداد YAML هذا مع وكيل الباحث المُعرّف في فئة `LinkedinProfileCrew`. يحدد الإعداد دور الوكيل وهدفه وخلفيته وخصائص أخرى مثل LLM والأدوات التي يستخدمها. + +لاحظ كيف يتوافق `llm` و `tools` في ملف YAML مع الطرق المزينة بـ `@llm` و `@tool` في فئة Python. + +## أفضل الممارسات + +- **تسمية متسقة**: استخدم اصطلاحات تسمية واضحة ومتسقة لطرقك. على سبيل المثال، يمكن تسمية طرق الوكلاء بأسماء أدوارهم (مثل researcher، reporting_analyst). +- **متغيرات البيئة**: استخدم متغيرات البيئة للمعلومات الحساسة مثل مفاتيح API. +- **المرونة**: صمم طاقمك ليكون مرناً بالسماح بإضافة أو إزالة الوكلاء والمهام بسهولة. +- **توافق YAML-الكود**: في المشاريع الكلاسيكية، تأكد من أن الأسماء والهياكل في ملفات YAML تتوافق بشكل صحيح مع الطرق المزينة في كود Python الخاص بك. + +باتباع هذه الإرشادات واستخدام التعليقات التوضيحية بشكل صحيح، يمكنك الحفاظ على أطقم كلاسيكية منظمة وسهلة الصيانة. للـ crews الجديدة، استخدم بنية JSON-first في [Crews](/ar/concepts/crews). diff --git a/docs/v1.15.13/ar/mcp/dsl-integration.mdx b/docs/v1.15.13/ar/mcp/dsl-integration.mdx new file mode 100644 index 0000000000..392570e1f7 --- /dev/null +++ b/docs/v1.15.13/ar/mcp/dsl-integration.mdx @@ -0,0 +1,349 @@ +--- +title: تكامل MCP DSL +description: تعلم كيفية استخدام صياغة DSL البسيطة في CrewAI لدمج خوادم MCP مباشرة مع وكلائك باستخدام حقل mcps. +icon: code +mode: "wide" +--- + +## نظرة عامة + +يوفر تكامل MCP DSL (لغة المجال المحددة) في CrewAI **الطريقة الأبسط** لربط وكلائك بخوادم MCP (بروتوكول سياق النموذج). ما عليك سوى إضافة حقل `mcps` إلى وكيلك وسيتعامل CrewAI مع كل التعقيدات تلقائياً. + + + هذا هو **النهج الموصى به** لمعظم حالات استخدام MCP. للسيناريوهات المتقدمة + التي تتطلب إدارة اتصال يدوية، راجع + [MCPServerAdapter](/ar/mcp/overview#advanced-mcpserveradapter). + + +## الاستخدام الأساسي + +أضف خوادم MCP إلى وكيلك باستخدام حقل `mcps`: + +```python +from crewai import Agent + +agent = Agent( + role="Research Assistant", + goal="Help with research and analysis tasks", + backstory="Expert assistant with access to advanced research tools", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=your_key&profile=research" + ] +) + +# MCP tools are now automatically available! +# No need for manual connection management or tool configuration +``` + +## تنسيقات المراجع المدعومة + +### خوادم MCP البعيدة الخارجية + +```python +# Basic HTTPS server +"https://api.example.com/mcp" + +# Server with authentication +"https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile" + +# Server with custom path +"https://services.company.com/api/v1/mcp" +``` + +### اختيار أدوات محددة + +استخدم صياغة `#` لاختيار أدوات محددة من خادم: + +```python +# Get only the forecast tool from weather server +"https://weather.api.com/mcp#get_forecast" + +# Get only the search tool from Exa +"https://mcp.exa.ai/mcp?api_key=your_key#web_search_exa" +``` + +### تكاملات MCP المتصلة + +اربط خوادم MCP من كتالوج CrewAI أو أحضر خوادمك الخاصة. بمجرد الاتصال في حسابك، أشر إليها بالمعرف المختصر: + +```python +# Connected MCP with all tools +"snowflake" + +# Specific tool from a connected MCP +"stripe#list_invoices" + +# Multiple connected MCPs +mcps=[ + "snowflake", + "stripe", + "github" +] +``` + +## مثال كامل + +إليك مثالاً كاملاً يستخدم خوادم MCP متعددة: + +```python +from crewai import Agent, Task, Crew, Process + +# Create agent with multiple MCP sources +multi_source_agent = Agent( + role="Multi-Source Research Analyst", + goal="Conduct comprehensive research using multiple data sources", + backstory="""Expert researcher with access to web search, weather data, + financial information, and academic research tools""", + mcps=[ + # External MCP servers + "https://mcp.exa.ai/mcp?api_key=your_exa_key&profile=research", + "https://weather.api.com/mcp#get_current_conditions", + + # Connected MCPs from catalog + "snowflake", + "stripe#list_invoices", + "github#search_repositories" + ] +) + +# Create comprehensive research task +research_task = Task( + description="""Research the impact of AI agents on business productivity. + Include current weather impacts on remote work, financial market trends, + and recent academic publications on AI agent frameworks.""", + expected_output="""Comprehensive report covering: + 1. AI agent business impact analysis + 2. Weather considerations for remote work + 3. Financial market trends related to AI + 4. Academic research citations and insights + 5. Competitive landscape analysis""", + agent=multi_source_agent +) + +# Create and execute crew +research_crew = Crew( + agents=[multi_source_agent], + tasks=[research_task], + process=Process.sequential, + verbose=True +) + +result = research_crew.kickoff() +print(f"Research completed with {len(multi_source_agent.mcps)} MCP data sources") +``` + +## تسمية الأدوات والتنظيم + +يتعامل CrewAI تلقائياً مع تسمية الأدوات لمنع التعارضات: + +```python +# Original MCP server has tools: "search", "analyze" +# CrewAI creates tools: "mcp_exa_ai_search", "mcp_exa_ai_analyze" + +agent = Agent( + role="Tool Organization Demo", + goal="Show how tool naming works", + backstory="Demonstrates automatic tool organization", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=key", # Tools: mcp_exa_ai_* + "https://weather.service.com/mcp", # Tools: weather_service_com_* + "snowflake" # Tools: snowflake_* + ] +) + +# Each server's tools get unique prefixes based on the server name +# This prevents naming conflicts between different MCP servers +``` + +## معالجة الأخطاء والمرونة + +صُمم MCP DSL ليكون متيناً وسهل الاستخدام: + +### التعامل الأنيق مع فشل الخادم + +```python +agent = Agent( + role="Resilient Researcher", + goal="Research despite server issues", + backstory="Experienced researcher who adapts to available tools", + mcps=[ + "https://primary-server.com/mcp", # Primary data source + "https://backup-server.com/mcp", # Backup if primary fails + "https://unreachable-server.com/mcp", # Will be skipped with warning + "snowflake" # Connected MCP from catalog + ] +) + +# Agent will: +# 1. Successfully connect to working servers +# 2. Log warnings for failing servers +# 3. Continue with available tools +# 4. Not crash or hang on server failures +``` + +### حماية المهلة الزمنية + +جميع عمليات MCP لها مهلات زمنية مدمجة: + +- **مهلة الاتصال**: 10 ثوانٍ +- **مهلة تنفيذ الأداة**: 30 ثانية +- **مهلة الاكتشاف**: 15 ثانية + +```python +# These servers will timeout gracefully if unresponsive +mcps=[ + "https://slow-server.com/mcp", # Will timeout after 10s if unresponsive + "https://overloaded-api.com/mcp" # Will timeout if discovery takes > 15s +] +``` + +## ميزات الأداء + +### التخزين المؤقت التلقائي + +تُخزن مخططات الأدوات مؤقتاً لمدة 5 دقائق لتحسين الأداء: + +```python +# First agent creation - discovers tools from server +agent1 = Agent(role="First", goal="Test", backstory="Test", + mcps=["https://api.example.com/mcp"]) + +# Second agent creation (within 5 minutes) - uses cached tool schemas +agent2 = Agent(role="Second", goal="Test", backstory="Test", + mcps=["https://api.example.com/mcp"]) # Much faster! +``` + +### الاتصالات حسب الطلب + +تُنشأ اتصالات الأدوات فقط عند استخدام الأدوات فعلياً: + +```python +# Agent creation is fast - no MCP connections made yet +agent = Agent( + role="On-Demand Agent", + goal="Use tools efficiently", + backstory="Efficient agent that connects only when needed", + mcps=["https://api.example.com/mcp"] +) + +# MCP connection is made only when a tool is actually executed +# This minimizes connection overhead and improves startup performance +``` + +## التكامل مع الميزات الموجودة + +تعمل أدوات MCP بسلاسة مع ميزات CrewAI الأخرى: + +```python +from crewai.tools import BaseTool + +class CustomTool(BaseTool): + name: str = "custom_analysis" + description: str = "Custom analysis tool" + + def _run(self, **kwargs): + return "Custom analysis result" + +agent = Agent( + role="Full-Featured Agent", + goal="Use all available tool types", + backstory="Agent with comprehensive tool access", + + # All tool types work together + tools=[CustomTool()], # Custom tools + apps=["gmail", "slack"], # Platform integrations + mcps=[ # MCP servers + "https://mcp.exa.ai/mcp?api_key=key", + "snowflake" + ], + + verbose=True, + max_iter=15 +) +``` + +## أفضل الممارسات + +### 1. استخدم أدوات محددة عند الإمكان + +```python +# Good - only get the tools you need +mcps=["https://weather.api.com/mcp#get_forecast"] + +# Less efficient - gets all tools from server +mcps=["https://weather.api.com/mcp"] +``` + +### 2. تعامل مع المصادقة بأمان + +```python +import os + +# Store API keys in environment variables +exa_key = os.getenv("EXA_API_KEY") +exa_profile = os.getenv("EXA_PROFILE") + +agent = Agent( + role="Secure Agent", + goal="Use MCP tools securely", + backstory="Security-conscious agent", + mcps=[f"https://mcp.exa.ai/mcp?api_key={exa_key}&profile={exa_profile}"] +) +``` + +### 3. خطط لفشل الخادم + +```python +# Always include backup options +mcps=[ + "https://primary-api.com/mcp", # Primary choice + "https://backup-api.com/mcp", # Backup option + "snowflake" # Connected MCP fallback +] +``` + +### 4. استخدم أدواراً وصفية للوكلاء + +```python +agent = Agent( + role="Weather-Enhanced Market Analyst", + goal="Analyze markets considering weather impacts", + backstory="Financial analyst with access to weather data for agricultural market insights", + mcps=[ + "https://weather.service.com/mcp#get_forecast", + "stripe#list_invoices" + ] +) +``` + +## استكشاف الأخطاء وإصلاحها + +### المشاكل الشائعة + +**لم يتم اكتشاف أدوات:** + +```python +# Check your MCP server URL and authentication +# Verify the server is running and accessible +mcps=["https://mcp.example.com/mcp?api_key=valid_key"] +``` + +**انتهاء مهلة الاتصال:** + +```python +# Server may be slow or overloaded +# CrewAI will log warnings and continue with other servers +# Check server status or try backup servers +``` + +**فشل المصادقة:** + +```python +# Verify API keys and credentials +# Check server documentation for required parameters +# Ensure query parameters are properly URL encoded +``` + +## متقدم: MCPServerAdapter + +للسيناريوهات المعقدة التي تتطلب إدارة اتصال يدوية، استخدم فئة `MCPServerAdapter` من `crewai-tools`. استخدام مدير سياق Python (تعليمة `with`) هو النهج الموصى به لأنه يتعامل تلقائياً مع بدء وإيقاف الاتصال بخادم MCP. diff --git a/docs/v1.15.13/ar/mcp/multiple-servers.mdx b/docs/v1.15.13/ar/mcp/multiple-servers.mdx new file mode 100644 index 0000000000..14e2d4681c --- /dev/null +++ b/docs/v1.15.13/ar/mcp/multiple-servers.mdx @@ -0,0 +1,65 @@ +--- +title: الاتصال بخوادم MCP متعددة +description: تعلم كيفية استخدام MCPServerAdapter في CrewAI للاتصال بخوادم MCP متعددة بشكل متزامن وتجميع أدواتها. +icon: layer-group +mode: "wide" +--- + +## نظرة عامة + +يتيح لك `MCPServerAdapter` في `crewai-tools` الاتصال بخوادم MCP متعددة بشكل متزامن. هذا مفيد عندما يحتاج وكلاؤك للوصول إلى أدوات موزعة عبر خدمات أو بيئات مختلفة. يجمع المحول الأدوات من جميع الخوادم المحددة، مما يجعلها متاحة لوكلاء CrewAI. + +## الإعداد + +للاتصال بخوادم متعددة، توفر قائمة من قواميس معاملات الخادم لـ `MCPServerAdapter`. يجب أن يعرّف كل قاموس في القائمة معاملات خادم MCP واحد. + +تتضمن أنواع النقل المدعومة لكل خادم في القائمة `stdio` و `sse` و `streamable-http`. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters # Needed for Stdio example + +# Define parameters for multiple MCP servers +server_params_list = [ + # Streamable HTTP Server + { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" + }, + # SSE Server + { + "url": "http://localhost:8000/sse", + "transport": "sse" + }, + # StdIO Server + StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, + ) +] + +try: + with MCPServerAdapter(server_params_list) as aggregated_tools: + print(f"Available aggregated tools: {[tool.name for tool in aggregated_tools]}") + + multi_server_agent = Agent( + role="Versatile Assistant", + goal="Utilize tools from local Stdio, remote SSE, and remote HTTP MCP servers.", + backstory="An AI agent capable of leveraging a diverse set of tools from multiple sources.", + tools=aggregated_tools, # All tools are available here + verbose=True, + ) + + ... # Your other agent, tasks, and crew code here + +except Exception as e: + print(f"Error connecting to or using multiple MCP servers (Managed): {e}") + print("Ensure all MCP servers are running and accessible with correct configurations.") + +``` + +## إدارة الاتصال + +عند استخدام مدير السياق (تعليمة `with`)، يتعامل `MCPServerAdapter` مع دورة حياة جميع الاتصالات بخوادم MCP المُعدة (البدء والإيقاف). هذا يبسط إدارة الموارد ويضمن إغلاق جميع الاتصالات بشكل صحيح عند الخروج من السياق. diff --git a/docs/v1.15.13/ar/mcp/overview.mdx b/docs/v1.15.13/ar/mcp/overview.mdx new file mode 100644 index 0000000000..ecb1204ee5 --- /dev/null +++ b/docs/v1.15.13/ar/mcp/overview.mdx @@ -0,0 +1,690 @@ +--- +title: "خوادم MCP كأدوات في CrewAI" +description: "تعلم كيفية دمج خوادم MCP كأدوات في وكلاء CrewAI باستخدام مكتبة `crewai-tools`." +icon: plug +mode: "wide" +--- + +## نظرة عامة + +يوفر [بروتوكول سياق النموذج](https://modelcontextprotocol.io/introduction) (MCP) طريقة موحدة لوكلاء الذكاء الاصطناعي لتوفير سياق لنماذج اللغة الكبيرة من خلال التواصل مع خدمات خارجية تُعرف بخوادم MCP. + +يقدم CrewAI **نهجين** لتكامل MCP: + +### تكامل DSL البسيط (الموصى به) + +استخدم حقل `mcps` مباشرة على الوكلاء لتكامل سلس مع أدوات MCP. يدعم DSL كلاً من **المراجع النصية** (للإعداد السريع) و**الإعدادات المنظمة** (للتحكم الكامل). + +#### المراجع النصية (إعداد سريع) + +مثالية لخوادم HTTPS البعيدة وتكاملات MCP المتصلة من كتالوج CrewAI: + +```python +from crewai import Agent + +agent = Agent( + role="Research Analyst", + goal="Research and analyze information", + backstory="Expert researcher with access to external tools", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=your_key", # External MCP server + "https://api.weather.com/mcp#get_forecast", # Specific tool from server + "snowflake", # Connected MCP from catalog + "stripe#list_invoices" # Specific tool from connected MCP + ] +) +# MCP tools are now automatically available to your agent! +``` + +#### الإعدادات المنظمة (تحكم كامل) + +للتحكم الكامل في إعدادات الاتصال وتصفية الأدوات وجميع أنواع النقل: + +```python +from crewai import Agent +from crewai.mcp import MCPServerStdio, MCPServerHTTP, MCPServerSSE +from crewai.mcp.filters import create_static_tool_filter + +agent = Agent( + role="Advanced Research Analyst", + goal="Research with full control over MCP connections", + backstory="Expert researcher with advanced tool access", + mcps=[ + # Stdio transport for local servers + MCPServerStdio( + command="npx", + args=["-y", "@modelcontextprotocol/server-filesystem"], + env={"API_KEY": "your_key"}, + tool_filter=create_static_tool_filter( + allowed_tool_names=["read_file", "list_directory"] + ), + cache_tools_list=True, + ), + # HTTP/Streamable HTTP transport for remote servers + MCPServerHTTP( + url="https://api.example.com/mcp", + headers={"Authorization": "Bearer your_token"}, + streamable=True, + cache_tools_list=True, + ), + # SSE transport for real-time streaming + MCPServerSSE( + url="https://stream.example.com/mcp/sse", + headers={"Authorization": "Bearer your_token"}, + ), + ] +) +``` + +### متقدم: MCPServerAdapter (للسيناريوهات المعقدة) + +لحالات الاستخدام المتقدمة التي تتطلب إدارة اتصال يدوية، توفر مكتبة `crewai-tools` فئة `MCPServerAdapter`. + +ندعم حالياً آليات النقل التالية: + +- **Stdio**: للخوادم المحلية (التواصل عبر الإدخال/الإخراج القياسي بين العمليات على نفس الجهاز) +- **Server-Sent Events (SSE)**: للخوادم البعيدة (بث بيانات أحادي الاتجاه في الوقت الفعلي من الخادم إلى العميل عبر HTTP) +- **Streamable HTTPS**: للخوادم البعيدة (اتصال مرن، ربما ثنائي الاتجاه عبر HTTPS، يستخدم غالباً SSE للتدفقات من الخادم إلى العميل) + +## فيديو تعليمي + +شاهد هذا الفيديو التعليمي للحصول على دليل شامل حول تكامل MCP مع CrewAI: + + + +## التثبيت + +يتطلب تكامل CrewAI MCP مكتبة `mcp`: + +```shell +# For Simple DSL Integration (Recommended) +uv add mcp + +# For Advanced MCPServerAdapter usage +uv pip install 'crewai-tools[mcp]' +``` + +## البدء السريع: تكامل DSL البسيط + +أسهل طريقة لدمج خوادم MCP هي استخدام حقل `mcps` على وكلائك. يمكنك استخدام مراجع نصية أو إعدادات منظمة. + +### البدء السريع مع المراجع النصية + +```python +from crewai import Agent, Task, Crew + +# Create agent with MCP tools using string references +research_agent = Agent( + role="Research Analyst", + goal="Find and analyze information using advanced search tools", + backstory="Expert researcher with access to multiple data sources", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile", + "snowflake#run_query" + ] +) + +# Create task +research_task = Task( + description="Research the latest developments in AI agent frameworks", + expected_output="Comprehensive research report with citations", + agent=research_agent +) + +# Create and run crew +crew = Crew(agents=[research_agent], tasks=[research_task]) +result = crew.kickoff() +``` + +### البدء السريع مع الإعدادات المنظمة + +```python +from crewai import Agent, Task, Crew +from crewai.mcp import MCPServerStdio, MCPServerHTTP, MCPServerSSE + +# Create agent with structured MCP configurations +research_agent = Agent( + role="Research Analyst", + goal="Find and analyze information using advanced search tools", + backstory="Expert researcher with access to multiple data sources", + mcps=[ + # Local stdio server + MCPServerStdio( + command="python", + args=["local_server.py"], + env={"API_KEY": "your_key"}, + ), + # Remote HTTP server + MCPServerHTTP( + url="https://api.research.com/mcp", + headers={"Authorization": "Bearer your_token"}, + ), + ] +) + +# Create task +research_task = Task( + description="Research the latest developments in AI agent frameworks", + expected_output="Comprehensive research report with citations", + agent=research_agent +) + +# Create and run crew +crew = Crew(agents=[research_agent], tasks=[research_task]) +result = crew.kickoff() +``` + +هذا كل شيء! يتم اكتشاف أدوات MCP تلقائياً وإتاحتها لوكيلك. + +## تنسيقات مراجع MCP + +يدعم حقل `mcps` كلاً من **المراجع النصية** (للإعداد السريع) و**الإعدادات المنظمة** (للتحكم الكامل). يمكنك مزج كلا التنسيقين في نفس القائمة. + +### المراجع النصية + +#### خوادم MCP الخارجية + +```python +mcps=[ + # Full server - get all available tools + "https://mcp.example.com/api", + + # Specific tool from server using # syntax + "https://api.weather.com/mcp#get_current_weather", + + # Server with authentication parameters + "https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile" +] +``` + +#### تكاملات MCP المتصلة + +اربط خوادم MCP من كتالوج CrewAI أو أحضر خوادمك الخاصة. بمجرد الاتصال في حسابك، أشر إليها بالمعرف المختصر: + +```python +mcps=[ + # Connected MCP - get all available tools + "snowflake", + + # Specific tool from a connected MCP using # syntax + "stripe#list_invoices", + + # Multiple connected MCPs + "snowflake", + "stripe", + "github" +] +``` + +### الإعدادات المنظمة + +#### نقل Stdio (خوادم محلية) + +مثالي لخوادم MCP المحلية التي تعمل كعمليات: + +```python +from crewai.mcp import MCPServerStdio +from crewai.mcp.filters import create_static_tool_filter + +mcps=[ + MCPServerStdio( + command="npx", + args=["-y", "@modelcontextprotocol/server-filesystem"], + env={"API_KEY": "your_key"}, + tool_filter=create_static_tool_filter( + allowed_tool_names=["read_file", "write_file"] + ), + cache_tools_list=True, + ), + # Python-based server + MCPServerStdio( + command="python", + args=["path/to/server.py"], + env={"UV_PYTHON": "3.12", "API_KEY": "your_key"}, + ), +] +``` + +#### نقل HTTP/Streamable HTTP (خوادم بعيدة) + +لخوادم MCP البعيدة عبر HTTP/HTTPS: + +```python +from crewai.mcp import MCPServerHTTP + +mcps=[ + # Streamable HTTP (default) + MCPServerHTTP( + url="https://api.example.com/mcp", + headers={"Authorization": "Bearer your_token"}, + streamable=True, + cache_tools_list=True, + ), + # Standard HTTP + MCPServerHTTP( + url="https://api.example.com/mcp", + headers={"Authorization": "Bearer your_token"}, + streamable=False, + ), +] +``` + +#### نقل SSE (البث في الوقت الفعلي) + +للخوادم البعيدة التي تستخدم Server-Sent Events: + +```python +from crewai.mcp import MCPServerSSE + +mcps=[ + MCPServerSSE( + url="https://stream.example.com/mcp/sse", + headers={"Authorization": "Bearer your_token"}, + cache_tools_list=True, + ), +] +``` + +### مراجع مختلطة + +يمكنك دمج المراجع النصية والإعدادات المنظمة: + +```python +from crewai.mcp import MCPServerStdio, MCPServerHTTP + +mcps=[ + # String references + "https://external-api.com/mcp", # External server + "snowflake", # Connected MCP from catalog + + # Structured configurations + MCPServerStdio( + command="npx", + args=["-y", "@modelcontextprotocol/server-filesystem"], + ), + MCPServerHTTP( + url="https://api.example.com/mcp", + headers={"Authorization": "Bearer token"}, + ), +] +``` + +### تصفية الأدوات + +تدعم الإعدادات المنظمة تصفية أدوات متقدمة: + +```python +from crewai.mcp import MCPServerStdio +from crewai.mcp.filters import create_static_tool_filter, create_dynamic_tool_filter, ToolFilterContext + +# Static filtering (allow/block lists) +static_filter = create_static_tool_filter( + allowed_tool_names=["read_file", "write_file"], + blocked_tool_names=["delete_file"], +) + +# Dynamic filtering (context-aware) +def dynamic_filter(context: ToolFilterContext, tool: dict) -> bool: + # Block dangerous tools for certain agent roles + if context.agent.role == "Code Reviewer": + if "delete" in tool.get("name", "").lower(): + return False + return True + +mcps=[ + MCPServerStdio( + command="npx", + args=["-y", "@modelcontextprotocol/server-filesystem"], + tool_filter=static_filter, # or dynamic_filter + ), +] +``` + +## معاملات الإعداد + +يدعم كل نوع نقل خيارات إعداد محددة: + +### معاملات MCPServerStdio + +- **`command`** (مطلوب): الأمر المراد تنفيذه (مثل `"python"` أو `"node"` أو `"npx"` أو `"uvx"`) +- **`args`** (اختياري): قائمة وسيطات الأمر (مثل `["server.py"]` أو `["-y", "@mcp/server"]`) +- **`env`** (اختياري): قاموس متغيرات البيئة لتمريرها إلى العملية +- **`tool_filter`** (اختياري): دالة تصفية الأدوات لتصفية الأدوات المتاحة +- **`cache_tools_list`** (اختياري): ما إذا كان يجب تخزين قائمة الأدوات مؤقتاً لوصول أسرع لاحقاً (الافتراضي: `False`) + +### معاملات MCPServerHTTP + +- **`url`** (مطلوب): عنوان URL الخادم (مثل `"https://api.example.com/mcp"`) +- **`headers`** (اختياري): قاموس رؤوس HTTP للمصادقة أو أغراض أخرى +- **`streamable`** (اختياري): ما إذا كان يجب استخدام نقل HTTP القابل للبث (الافتراضي: `True`) +- **`tool_filter`** (اختياري): دالة تصفية الأدوات لتصفية الأدوات المتاحة +- **`cache_tools_list`** (اختياري): ما إذا كان يجب تخزين قائمة الأدوات مؤقتاً (الافتراضي: `False`) + +### معاملات MCPServerSSE + +- **`url`** (مطلوب): عنوان URL الخادم (مثل `"https://api.example.com/mcp/sse"`) +- **`headers`** (اختياري): قاموس رؤوس HTTP للمصادقة أو أغراض أخرى +- **`tool_filter`** (اختياري): دالة تصفية الأدوات لتصفية الأدوات المتاحة +- **`cache_tools_list`** (اختياري): ما إذا كان يجب تخزين قائمة الأدوات مؤقتاً (الافتراضي: `False`) + +### المعاملات المشتركة + +تدعم جميع أنواع النقل: + +- **`tool_filter`**: دالة تصفية للتحكم في الأدوات المتاحة. يمكن أن تكون: + - `None` (الافتراضي): جميع الأدوات متاحة + - تصفية ثابتة: تُنشأ باستخدام `create_static_tool_filter()` لقوائم السماح/الحظر + - تصفية ديناميكية: تُنشأ باستخدام `create_dynamic_tool_filter()` للتصفية الواعية بالسياق +- **`cache_tools_list`**: عند `True`، تخزن قائمة الأدوات مؤقتاً بعد أول اكتشاف لتحسين الأداء في الاتصالات اللاحقة + +## الميزات الرئيسية + +- **اكتشاف تلقائي للأدوات**: يتم اكتشاف الأدوات ودمجها تلقائياً +- **منع تعارض الأسماء**: تُضاف بادئات أسماء الخوادم لأسماء الأدوات +- **محسّن للأداء**: اتصالات حسب الطلب مع تخزين مؤقت للمخططات +- **مرونة في الأخطاء**: تعامل أنيق مع الخوادم غير المتاحة +- **حماية المهلة الزمنية**: مهلات زمنية مدمجة تمنع تعليق الاتصالات +- **تكامل شفاف**: يعمل بسلاسة مع ميزات CrewAI الموجودة +- **دعم نقل كامل**: أنواع نقل Stdio وHTTP/Streamable HTTP وSSE +- **تصفية متقدمة**: قدرات تصفية أدوات ثابتة وديناميكية +- **مصادقة مرنة**: دعم للرؤوس ومتغيرات البيئة ومعاملات الاستعلام + +## معالجة الأخطاء + +صُمم تكامل MCP DSL ليكون مرناً ويتعامل مع الفشل بأناقة: + +```python +from crewai import Agent +from crewai.mcp import MCPServerStdio, MCPServerHTTP + +agent = Agent( + role="Resilient Agent", + goal="Continue working despite server issues", + backstory="Agent that handles failures gracefully", + mcps=[ + # String references + "https://reliable-server.com/mcp", # Will work + "https://unreachable-server.com/mcp", # Will be skipped gracefully + "snowflake", # Connected MCP from catalog + + # Structured configs + MCPServerStdio( + command="python", + args=["reliable_server.py"], # Will work + ), + MCPServerHTTP( + url="https://slow-server.com/mcp", # Will timeout gracefully + ), + ] +) +# Agent will use tools from working servers and log warnings for failing ones +``` + +جميع أخطاء الاتصال تُعالج بأناقة: + +- **فشل الاتصال**: تُسجل كتحذيرات، ويستمر الوكيل مع الأدوات المتاحة +- **أخطاء المهلة الزمنية**: تنتهي الاتصالات بعد 30 ثانية (قابلة للتعديل) +- **أخطاء المصادقة**: تُسجل بوضوح للتصحيح +- **إعدادات غير صالحة**: تُرفع أخطاء التحقق عند إنشاء الوكيل + +## متقدم: MCPServerAdapter + +للسيناريوهات المعقدة التي تتطلب إدارة اتصال يدوية، استخدم فئة `MCPServerAdapter` من `crewai-tools`. استخدام مدير سياق Python (تعليمة `with`) هو النهج الموصى به لأنه يتعامل تلقائياً مع بدء وإيقاف الاتصال بخادم MCP. + +## إعداد الاتصال + +يدعم `MCPServerAdapter` عدة خيارات إعداد لتخصيص سلوك الاتصال: + +- **`connect_timeout`** (اختياري): الحد الأقصى للوقت بالثواني لانتظار إنشاء اتصال بخادم MCP. القيمة الافتراضية 30 ثانية إذا لم تُحدد. هذا مفيد بشكل خاص للخوادم البعيدة التي قد يكون لها أوقات استجابة متغيرة. + +```python +# Example with custom connection timeout +with MCPServerAdapter(server_params, connect_timeout=60) as tools: + # Connection will timeout after 60 seconds if not established + pass +``` + +```python +from crewai import Agent +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters # For Stdio Server + +# Example server_params (choose one based on your server type): +# 1. Stdio Server: +server_params=StdioServerParameters( + command="python3", + args=["servers/your_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +# 2. SSE Server: +server_params = { + "url": "http://localhost:8000/sse", + "transport": "sse" +} + +# 3. Streamable HTTP Server: +server_params = { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" +} + +# Example usage (uncomment and adapt once server_params is set): +with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="Utilize tools from an MCP server.", + backstory="I can connect to MCP servers and use their tools.", + tools=mcp_tools, # Pass the loaded tools to your agent + reasoning=True, + verbose=True + ) + # ... rest of your crew setup ... +``` + +يوضح هذا النمط العام كيفية دمج الأدوات. للحصول على أمثلة محددة مصممة لكل نوع نقل، راجع الأدلة التفصيلية أدناه. + +## تصفية الأدوات + +هناك طريقتان لتصفية الأدوات: + +1. الوصول إلى أداة محددة باستخدام فهرسة نمط القاموس. +2. تمرير قائمة أسماء الأدوات إلى منشئ `MCPServerAdapter`. + +### الوصول إلى أداة محددة باستخدام فهرسة نمط القاموس. + +```python +with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="Utilize tools from an MCP server.", + backstory="I can connect to MCP servers and use their tools.", + tools=[mcp_tools["tool_name"]], # Pass the loaded tools to your agent + reasoning=True, + verbose=True + ) + # ... rest of your crew setup ... +``` + +### تمرير قائمة أسماء الأدوات إلى منشئ `MCPServerAdapter`. + +```python +with MCPServerAdapter(server_params, "tool_name", connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="Utilize tools from an MCP server.", + backstory="I can connect to MCP servers and use their tools.", + tools=mcp_tools, # Pass the loaded tools to your agent + reasoning=True, + verbose=True + ) + # ... rest of your crew setup ... +``` + +## الاستخدام مع CrewBase + +لاستخدام أدوات MCPServer ضمن فئة CrewBase، استخدم طريقة `get_mcp_tools`. يجب توفير إعدادات الخادم عبر خاصية `mcp_server_params`. يمكنك تمرير إعداد واحد أو قائمة من إعدادات خوادم متعددة. + +```python +@CrewBase +class CrewWithMCP: + # ... define your agents and tasks config file ... + + mcp_server_params = [ + # Streamable HTTP Server + { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" + }, + # SSE Server + { + "url": "http://localhost:8000/sse", + "transport": "sse" + }, + # StdIO Server + StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, + ) + ] + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) # get all available tools + + # ... rest of your crew setup ... +``` + + +عندما تكون فئة الطاقم مزينة بـ `@CrewBase`، تُدار دورة حياة المحول نيابة عنك: + +- أول استدعاء لـ `get_mcp_tools()` ينشئ بكسل `MCPServerAdapter` مشتركاً يُعاد استخدامه من قبل كل وكيل في الطاقم. +- يُغلق المحول تلقائياً بعد اكتمال `.kickoff()` بفضل خطاف ما بعد التشغيل الضمني المحقون من `@CrewBase`، لذا لا حاجة للتنظيف اليدوي. +- إذا لم يتم تعريف `mcp_server_params`، يُرجع `get_mcp_tools()` ببساطة قائمة فارغة، مما يسمح لنفس مسارات الكود بالعمل مع أو بدون إعداد MCP. + +هذا يجعل من الآمن استدعاء `get_mcp_tools()` من طرق وكلاء متعددة أو تفعيل MCP بشكل انتقائي لكل بيئة. + + +### إعداد مهلة الاتصال + +يمكنك إعداد مهلة الاتصال لخوادم MCP عن طريق تعيين خاصية فئة `mcp_connect_timeout`. إذا لم تُحدد مهلة، تكون القيمة الافتراضية 30 ثانية. + +```python +@CrewBase +class CrewWithMCP: + mcp_server_params = [...] + mcp_connect_timeout = 60 # 60 seconds timeout for all MCP connections + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) +``` + +### تصفية الأدوات + +يمكنك تصفية الأدوات المتاحة لوكيلك عن طريق تمرير قائمة أسماء الأدوات إلى طريقة `get_mcp_tools`. + +```python +@agent +def another_agent(self): + return Agent( + config=self.agents_config["your_agent"], + tools=self.get_mcp_tools("tool_1", "tool_2") # get specific tools + ) +``` + +## استكشاف تكاملات MCP + + + + **الموصى به**: استخدم صياغة حقل `mcps=[]` البسيطة لتكامل MCP بلا جهد. + + + الاتصال بخوادم MCP المحلية عبر الإدخال/الإخراج القياسي. مثالي للنصوص البرمجية والملفات التنفيذية المحلية. + + + التكامل مع خوادم MCP البعيدة باستخدام Server-Sent Events لبث البيانات في الوقت الفعلي. + + + استخدام Streamable HTTP المرن للاتصال القوي مع خوادم MCP البعيدة. + + + تجميع الأدوات من عدة خوادم MCP بشكل متزامن باستخدام محول واحد. + + + مراجعة أفضل ممارسات الأمان المهمة لتكامل MCP للحفاظ على سلامة وكلائك. + + + +تحقق من هذا المستودع للحصول على عروض وأمثلة كاملة لتكامل MCP مع CrewAI! + + + CrewAI MCP Demo + + +## البقاء آمناً مع MCP + +تأكد دائماً من أنك تثق بخادم MCP قبل استخدامه. + +#### تحذير أمني: هجمات إعادة ربط DNS + +يمكن أن تكون عمليات نقل SSE عرضة لهجمات إعادة ربط DNS إذا لم تكن مؤمنة بشكل صحيح. +لمنع ذلك: + +1. **تحقق دائماً من رؤوس Origin** على اتصالات SSE الواردة للتأكد من أنها تأتي من مصادر متوقعة +2. **تجنب ربط الخوادم بجميع واجهات الشبكة** (0.0.0.0) عند التشغيل محلياً - اربط فقط بـ localhost (127.0.0.1) بدلاً من ذلك +3. **نفّذ مصادقة مناسبة** لجميع اتصالات SSE + +بدون هذه الحمايات، يمكن للمهاجمين استخدام إعادة ربط DNS للتفاعل مع خوادم MCP المحلية من مواقع ويب بعيدة. + +لمزيد من التفاصيل، راجع [وثائق أمان نقل MCP من Anthropic](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations). + +### القيود + +- **الأوليات المدعومة**: حالياً، يدعم `MCPServerAdapter` بشكل أساسي تكييف `أدوات` MCP. + لا يتم دمج أوليات MCP الأخرى مثل `prompts` أو `resources` مباشرة كمكونات CrewAI من خلال هذا المحول في هذا الوقت. +- **معالجة المخرجات**: يعالج المحول عادةً المخرجات النصية الرئيسية من أداة MCP (مثل `.content[0].text`). قد تتطلب المخرجات المعقدة أو متعددة الوسائط معالجة مخصصة إذا لم تتناسب مع هذا النمط. diff --git a/docs/v1.15.13/ar/mcp/security.mdx b/docs/v1.15.13/ar/mcp/security.mdx new file mode 100644 index 0000000000..e968ff9f51 --- /dev/null +++ b/docs/v1.15.13/ar/mcp/security.mdx @@ -0,0 +1,149 @@ +--- +title: اعتبارات أمان MCP +description: تعرف على أفضل ممارسات الأمان المهمة عند دمج خوادم MCP مع وكلاء CrewAI. +icon: lock +mode: "wide" +--- + +## نظرة عامة + + +الجانب الأكثر أهمية في أمان MCP هو **الثقة**. يجب أن تتصل فقط بخوادم MCP التي تثق بها **بالكامل**. + + +عند دمج خدمات خارجية مثل خوادم MCP (بروتوكول سياق النموذج) في وكلاء CrewAI، يكون الأمان أمراً بالغ الأهمية. +يمكن لخوادم MCP تنفيذ التعليمات البرمجية والوصول إلى البيانات أو التفاعل مع أنظمة أخرى بناءً على الأدوات التي تكشفها. +من الضروري فهم الآثار واتباع أفضل الممارسات لحماية تطبيقاتك وبياناتك. + +### المخاطر + +- تنفيذ تعليمات برمجية عشوائية على الجهاز الذي يعمل عليه الوكيل (خاصة مع نقل `Stdio` إذا كان الخادم يمكنه التحكم في الأمر المُنفذ). +- كشف بيانات حساسة من وكيلك أو بيئته. +- التلاعب بسلوك وكيلك بطرق غير مقصودة، بما في ذلك إجراء استدعاءات API غير مصرح بها نيابة عنك. +- اختطاف عملية استدلال وكيلك من خلال تقنيات حقن المطالبات المتطورة (انظر أدناه). + +### 1. الثقة بخوادم MCP + + +**اتصل فقط بخوادم MCP التي تثق بها.** + + +قبل إعداد `MCPServerAdapter` للاتصال بخادم MCP، تأكد من معرفة: +- **من يشغل الخادم؟** هل هو خدمة معروفة وذات سمعة جيدة، أم خادم داخلي تحت سيطرتك؟ +- **ما الأدوات التي يكشفها؟** افهم قدرات الأدوات. هل يمكن إساءة استخدامها إذا سيطر مهاجم أو إذا كان الخادم نفسه خبيثاً؟ +- **ما البيانات التي يصل إليها أو يعالجها؟** كن على دراية بأي معلومات حساسة قد تُرسل إلى خادم MCP أو يتعامل معها. + +تجنب الاتصال بخوادم MCP غير معروفة أو غير موثقة، خاصة إذا كان وكلاؤك يتعاملون مع مهام أو بيانات حساسة. + +### 2. حقن المطالبات الآمن عبر بيانات الأداة الوصفية: خطر "بروتوكول التحكم بالنموذج" + +خطر كبير وخفي هو إمكانية حقن المطالبات عبر البيانات الوصفية للأداة. إليك كيف يعمل: + +1. عندما يتصل وكيل CrewAI بخادم MCP، يطلب عادةً قائمة الأدوات المتاحة. +2. يستجيب خادم MCP ببيانات وصفية لكل أداة، بما في ذلك اسمها ووصفها وأوصاف معاملاتها. +3. يستخدم نموذج اللغة (LLM) الأساسي لوكيلك هذه البيانات الوصفية لفهم كيف ومتى يستخدم الأدوات. +4. يمكن لخادم MCP خبيث صياغة بياناته الوصفية للأدوات لتتضمن تعليمات مخفية أو صريحة تعمل كحقن مطالبات. + +**الأهم، يمكن أن يحدث هذا الهجوم بمجرد الاتصال بخادم خبيث وسرد أدواته، حتى لو لم يقرر وكيلك *استخدام* أي من تلك الأدوات.** مجرد التعرض للبيانات الوصفية الخبيثة يمكن أن يكون كافياً لاختراق سلوك الوكيل. + +**التخفيف:** + +* **الحذر الشديد مع الخوادم غير الموثوقة:** نكرر: *لا تتصل بخوادم MCP لا تثق بها بالكامل.* يجعل خطر حقن البيانات الوصفية هذا أمراً بالغ الأهمية. + +### أمان نقل Stdio + +عادةً ما يُستخدم نقل Stdio (الإدخال/الإخراج القياسي) لخوادم MCP المحلية التي تعمل على نفس الجهاز مثل تطبيق CrewAI. + +- **عزل العملية**: على الرغم من أنه أكثر أماناً بشكل عام لأنه لا يتضمن تعرض شبكي افتراضياً، تأكد من أن النص البرمجي أو الأمر الذي يُشغله `StdioServerParameters` من مصدر موثوق ولديه أذونات نظام ملفات مناسبة. +- **تنقية المدخلات**: إذا كان نص Stdio البرمجي يأخذ مدخلات معقدة مشتقة من تفاعلات الوكيل، تأكد من أن النص ينقي هذه المدخلات لمنع حقن الأوامر أو الثغرات الأخرى. +- **حدود الموارد**: كن على دراية بأن عملية خادم Stdio المحلية تستهلك موارد محلية (CPU، الذاكرة). تأكد من أنها تعمل بشكل جيد ولن تستنفد موارد النظام. + +### هجمات الوكيل المرتبك + +[مشكلة الوكيل المرتبك](https://en.wikipedia.org/wiki/Confused_deputy_problem) هي ثغرة أمنية كلاسيكية يمكن أن تظهر في تكاملات MCP، خاصة عندما يعمل خادم MCP كوسيط لخدمات طرف ثالث (مثل Google Calendar وGitHub) التي تستخدم OAuth 2.0 للترخيص. + +**السيناريو:** + +1. خادم MCP (نسميه `MCP-Proxy`) يسمح لوكيلك بالتفاعل مع `ThirdPartyAPI`. +2. يستخدم `MCP-Proxy` `client_id` ثابتاً واحداً خاصاً به عند التحدث مع خادم ترخيص `ThirdPartyAPI`. +3. أنت، كمستخدم، تصرح بشكل شرعي لـ `MCP-Proxy` بالوصول إلى `ThirdPartyAPI` نيابة عنك. +4. يصنع مهاجم رابطاً خبيثاً يبدأ تدفق OAuth مع `MCP-Proxy`، لكنه مصمم لخداع خادم ترخيص `ThirdPartyAPI`. +5. إذا نقرت على هذا الرابط، وشاهد خادم ترخيص `ThirdPartyAPI` ملف تعريف ارتباط الموافقة الموجود لـ `client_id` الخاص بـ `MCP-Proxy`، فقد *يتخطى* طلب موافقتك مرة أخرى. +6. قد يُخدع `MCP-Proxy` بعد ذلك لتمرير رمز ترخيص إلى المهاجم. + +**التخفيف (بشكل أساسي لمطوري خوادم MCP):** + +* يجب على خوادم MCP الوسيطة التي تستخدم معرفات عميل ثابتة للخدمات النهائية الحصول على **موافقة صريحة من المستخدم** لكل تطبيق عميل أو وكيل يتصل بها قبل بدء تدفق OAuth. + +**تداعيات مستخدم CrewAI:** + +* كن حذراً إذا أعاد خادم MCP توجيهك لمصادقات OAuth متعددة، خاصة إذا بدت غير متوقعة أو كانت الأذونات المطلوبة واسعة جداً. + +### أمان النقل البعيد (SSE و Streamable HTTP) + +عند الاتصال بخوادم MCP البعيدة عبر SSE أو Streamable HTTP، فإن ممارسات أمان الويب القياسية ضرورية. + +### اعتبارات أمان SSE + +### أ. هجمات إعادة ربط DNS (خاصة لـ SSE) + + +**احمِ ضد هجمات إعادة ربط DNS.** + + +تسمح إعادة ربط DNS لموقع ويب يتحكم فيه مهاجم بتجاوز سياسة نفس الأصل وإجراء طلبات لخوادم على شبكة المستخدم المحلية. + +**استراتيجيات التخفيف لمنفذي خوادم MCP:** +- **تحقق من رؤوس `Origin` و `Host`**: يجب على خوادم MCP (خاصة SSE) التحقق من رؤوس HTTP لضمان أن الطلبات تأتي من نطاقات/عملاء متوقعين. +- **اربط بـ `localhost` (127.0.0.1)**: عند تشغيل خوادم MCP محلياً للتطوير، اربطها بـ `127.0.0.1` بدلاً من `0.0.0.0`. +- **المصادقة**: اطلب مصادقة لجميع الاتصالات بخادم MCP. + +### ب. استخدم HTTPS + +- **تشفير البيانات أثناء النقل**: استخدم دائماً HTTPS لعناوين URL خوادم MCP البعيدة لتشفير الاتصال. + +### ج. تمرير الرمز (نمط مضاد) + +هذا يتعلق بشكل أساسي بمطوري خوادم MCP لكن فهمه يساعد في اختيار خوادم آمنة. + +"تمرير الرمز" هو عندما يقبل خادم MCP رمز وصول من وكيل CrewAI ويمرره ببساطة إلى API آخر بدون تحقق مناسب. + +**المخاطر:** +* يتجاوز ضوابط الأمان على خادم MCP أو API النهائي. +* يكسر مسارات التدقيق والمساءلة. +* يسمح بإساءة استخدام الرموز المسروقة. + +### د. التحقق من المدخلات وتنقيتها + +- **التحقق من المدخلات أمر بالغ الأهمية**: يجب على خوادم MCP التحقق بصرامة من جميع المدخلات المستلمة من الوكلاء *قبل* معالجتها أو تمريرها إلى الأدوات. هذا دفاع أساسي ضد العديد من الثغرات الشائعة: + - **حقن الأوامر:** إذا كانت أداة تبني أوامر shell أو استعلامات SQL بناءً على المدخلات، يجب على الخادم تنقية هذه المدخلات بدقة. + - **اجتياز المسار:** إذا وصلت أداة إلى ملفات بناءً على معاملات المدخلات، يجب على الخادم التحقق من هذه المسارات وتنقيتها. + - **فحوصات نوع البيانات والنطاق:** يجب أن تضمن الخوادم توافق البيانات مع الأنواع والنطاقات المتوقعة. + +### هـ. تحديد المعدل وإدارة الموارد + +- **منع الإساءة**: يجب أن تنفذ خوادم MCP تحديد المعدل لمنع الإساءة. +- **إعادة المحاولة من جانب العميل**: نفّذ منطق إعادة محاولة معقول في مهام CrewAI. + +## 4. نصائح لتنفيذ خادم MCP آمن (للمطورين) + +إذا كنت تطور خادم MCP قد تتصل به وكلاء CrewAI، ضع في الاعتبار أفضل الممارسات التالية: + +- **اتبع ممارسات البرمجة الآمنة**: التزم بمبادئ البرمجة الآمنة القياسية (مثل OWASP Top 10). +- **مبدأ الحد الأدنى من الصلاحيات**: تأكد من أن العملية التي تشغل خادم MCP لديها فقط الأذونات اللازمة. +- **إدارة الاعتماديات**: حافظ على تحديث جميع الاعتماديات لتصحيح الثغرات المعروفة. +- **الإعدادات الافتراضية الآمنة**: صمم خادمك وأدواته لتكون آمنة افتراضياً. +- **التحكم في الوصول للأدوات**: نفّذ آليات قوية للتحكم في الوكلاء أو المستخدمين المصرح لهم بالوصول إلى أدوات محددة. +- **معالجة أخطاء آمنة**: يجب ألا تكشف الخوادم رسائل خطأ داخلية مفصلة أو تتبعات المكدس للعميل. +- **التسجيل والمراقبة الشاملة**: نفّذ تسجيلاً مفصلاً للأحداث المتعلقة بالأمان. +- **الالتزام بمواصفات ترخيص MCP**: إذا كنت تنفذ المصادقة والترخيص، اتبع بدقة [مواصفات ترخيص MCP](https://modelcontextprotocol.io/specification/draft/basic/authorization). +- **تدقيقات أمنية منتظمة**: إذا كان خادم MCP يتعامل مع بيانات حساسة، فكر في إجراء تدقيقات أمنية دورية. + +## 5. قراءة إضافية + +لمزيد من المعلومات التفصيلية حول أمان MCP، راجع التوثيق الرسمي: +- **[أمان نقل MCP](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations)** + +من خلال فهم اعتبارات الأمان هذه وتنفيذ أفضل الممارسات، يمكنك الاستفادة بأمان من قوة خوادم MCP في مشاريع CrewAI. +هذه ليست شاملة بأي حال، لكنها تغطي المخاوف الأمنية الأكثر شيوعاً وأهمية. +ستستمر التهديدات في التطور، لذا من المهم البقاء على اطلاع وتكييف إجراءات الأمان وفقاً لذلك. diff --git a/docs/v1.15.13/ar/mcp/sse.mdx b/docs/v1.15.13/ar/mcp/sse.mdx new file mode 100644 index 0000000000..3e5e352468 --- /dev/null +++ b/docs/v1.15.13/ar/mcp/sse.mdx @@ -0,0 +1,151 @@ +--- +title: نقل SSE +description: تعلم كيفية ربط CrewAI بخوادم MCP البعيدة باستخدام Server-Sent Events (SSE) للاتصال في الوقت الفعلي. +icon: wifi +mode: "wide" +--- + +## نظرة عامة + +توفر Server-Sent Events (SSE) طريقة قياسية لخادم الويب لإرسال تحديثات إلى العميل عبر اتصال HTTP واحد طويل الأمد. في سياق MCP، تُستخدم SSE للخوادم البعيدة لبث البيانات (مثل استجابات الأدوات) إلى تطبيق CrewAI في الوقت الفعلي. + +## المفاهيم الرئيسية + +- **خوادم بعيدة**: SSE مناسب لخوادم MCP المستضافة عن بُعد. +- **بث أحادي الاتجاه**: عادةً ما يكون SSE قناة اتصال أحادية الاتجاه من الخادم إلى العميل. +- **إعداد `MCPServerAdapter`**: لـ SSE، ستوفر عنوان URL الخادم وتحدد نوع النقل. + +## الاتصال عبر SSE + +يمكنك الاتصال بخادم MCP المبني على SSE باستخدام نهجين رئيسيين لإدارة دورة حياة الاتصال: + +### 1. اتصال مُدار بالكامل (الموصى به) + +استخدام مدير سياق Python (تعليمة `with`) هو النهج الموصى به. يتعامل تلقائياً مع إنشاء وإغلاق الاتصال بخادم MCP SSE. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL + "transport": "sse" +} + +# Using MCPServerAdapter with a context manager +try: + with MCPServerAdapter(server_params) as tools: + print(f"Available tools from SSE MCP server: {[tool.name for tool in tools]}") + + # Example: Using a tool from the SSE MCP server + sse_agent = Agent( + role="Remote Service User", + goal="Utilize a tool provided by a remote SSE MCP server.", + backstory="An AI agent that connects to external services via SSE.", + tools=tools, + reasoning=True, + verbose=True, + ) + + sse_task = Task( + description="Fetch real-time stock updates for 'AAPL' using an SSE tool.", + expected_output="The latest stock price for AAPL.", + agent=sse_agent, + markdown=True + ) + + sse_crew = Crew( + agents=[sse_agent], + tasks=[sse_task], + verbose=True, + process=Process.sequential + ) + + if tools: # Only kickoff if tools were loaded + result = sse_crew.kickoff() # Add inputs={'stock_symbol': 'AAPL'} if tool requires it + print("\nCrew Task Result (SSE - Managed):\n", result) + else: + print("Skipping crew kickoff as tools were not loaded (check server connection).") + +except Exception as e: + print(f"Error connecting to or using SSE MCP server (Managed): {e}") + print("Ensure the SSE MCP server is running and accessible at the specified URL.") + +``` + + +استبدل `"http://localhost:8000/sse"` بعنوان URL الفعلي لخادم MCP SSE الخاص بك. + + +### 2. دورة حياة اتصال يدوية + +إذا كنت بحاجة إلى تحكم أدق، يمكنك إدارة دورة حياة اتصال `MCPServerAdapter` يدوياً. + + +**يجب** عليك استدعاء `mcp_server_adapter.stop()` لضمان إغلاق الاتصال وتحرير الموارد. يُوصى بشدة باستخدام كتلة `try...finally`. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL + "transport": "sse" +} + +mcp_server_adapter = None +try: + mcp_server_adapter = MCPServerAdapter(server_params) + mcp_server_adapter.start() + tools = mcp_server_adapter.tools + print(f"Available tools (manual SSE): {[tool.name for tool in tools]}") + + manual_sse_agent = Agent( + role="Remote Data Analyst", + goal="Analyze data fetched from a remote SSE MCP server using manual connection management.", + backstory="An AI skilled in handling SSE connections explicitly.", + tools=tools, + verbose=True + ) + + analysis_task = Task( + description="Fetch and analyze the latest user activity trends from the SSE server.", + expected_output="A summary report of user activity trends.", + agent=manual_sse_agent + ) + + analysis_crew = Crew( + agents=[manual_sse_agent], + tasks=[analysis_task], + verbose=True, + process=Process.sequential + ) + + result = analysis_crew.kickoff() + print("\nCrew Task Result (SSE - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual SSE MCP integration: {e}") + print("Ensure the SSE MCP server is running and accessible.") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: + print("Stopping SSE MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: + print("SSE MCP server adapter was not connected. No stop needed or start failed.") + +``` + +## اعتبارات أمان SSE + + +**هجمات إعادة ربط DNS**: يمكن أن تكون عمليات نقل SSE عرضة لهجمات إعادة ربط DNS إذا لم يكن خادم MCP مؤمناً بشكل صحيح. قد يسمح هذا لمواقع ويب خبيثة بالتفاعل مع خوادم MCP المحلية أو على الشبكة الداخلية. + + +للتخفيف من هذا الخطر: +- يجب أن تتحقق تطبيقات خادم MCP من **رؤوس `Origin`** على اتصالات SSE الواردة. +- عند تشغيل خوادم MCP SSE محلية للتطوير، **اربط فقط بـ `localhost` (`127.0.0.1`)** بدلاً من جميع واجهات الشبكة (`0.0.0.0`). +- نفّذ **مصادقة مناسبة** لجميع اتصالات SSE إذا كشفت أدوات أو بيانات حساسة. + +للحصول على نظرة شاملة على أفضل ممارسات الأمان، يرجى الرجوع إلى صفحة [اعتبارات الأمان](./security.mdx) ووثائق [أمان نقل MCP](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations) الرسمية. diff --git a/docs/v1.15.13/ar/mcp/stdio.mdx b/docs/v1.15.13/ar/mcp/stdio.mdx new file mode 100644 index 0000000000..cf1b20e49f --- /dev/null +++ b/docs/v1.15.13/ar/mcp/stdio.mdx @@ -0,0 +1,134 @@ +--- +title: نقل Stdio +description: تعلم كيفية ربط CrewAI بخوادم MCP المحلية باستخدام آلية نقل Stdio (الإدخال/الإخراج القياسي). +icon: server +mode: "wide" +--- + +## نظرة عامة + +صُمم نقل Stdio (الإدخال/الإخراج القياسي) لربط `MCPServerAdapter` بخوادم MCP المحلية التي تتواصل عبر تدفقات الإدخال والإخراج القياسية. يُستخدم هذا عادةً عندما يكون خادم MCP نصاً برمجياً أو ملفاً تنفيذياً يعمل على نفس الجهاز مثل تطبيق CrewAI. + +## المفاهيم الرئيسية + +- **التنفيذ المحلي**: يدير نقل Stdio عملية تعمل محلياً لخادم MCP. +- **`StdioServerParameters`**: تُستخدم هذه الفئة من مكتبة `mcp` لإعداد الأمر والوسيطات ومتغيرات البيئة لتشغيل خادم Stdio. + +## الاتصال عبر Stdio + +يمكنك الاتصال بخادم MCP المبني على Stdio باستخدام نهجين رئيسيين لإدارة دورة حياة الاتصال: + +### 1. اتصال مُدار بالكامل (الموصى به) + +استخدام مدير سياق Python (تعليمة `with`) هو النهج الموصى به. يتعامل تلقائياً مع بدء عملية خادم MCP وإيقافها عند الخروج من السياق. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters +import os + +# Create a StdioServerParameters object +server_params=StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +with MCPServerAdapter(server_params) as tools: + print(f"Available tools from Stdio MCP server: {[tool.name for tool in tools]}") + + # Example: Using the tools from the Stdio MCP server in a CrewAI Agent + research_agent = Agent( + role="Local Data Processor", + goal="Process data using a local Stdio-based tool.", + backstory="An AI that leverages local scripts via MCP for specialized tasks.", + tools=tools, + reasoning=True, + verbose=True, + ) + + processing_task = Task( + description="Process the input data file 'data.txt' and summarize its contents.", + expected_output="A summary of the processed data.", + agent=research_agent, + markdown=True + ) + + data_crew = Crew( + agents=[research_agent], + tasks=[processing_task], + verbose=True, + process=Process.sequential + ) + + result = data_crew.kickoff() + print("\nCrew Task Result (Stdio - Managed):\n", result) + +``` + +### 2. دورة حياة اتصال يدوية + +إذا كنت بحاجة إلى تحكم أدق في وقت بدء وإيقاف عملية خادم MCP Stdio، يمكنك إدارة دورة حياة `MCPServerAdapter` يدوياً. + + +**يجب** عليك استدعاء `mcp_server_adapter.stop()` لضمان إنهاء عملية الخادم وتحرير الموارد. يُوصى بشدة باستخدام كتلة `try...finally`. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters +import os + +# Create a StdioServerParameters object +stdio_params=StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +mcp_server_adapter = MCPServerAdapter(server_params=stdio_params) +try: + mcp_server_adapter.start() # Manually start the connection and server process + tools = mcp_server_adapter.tools + print(f"Available tools (manual Stdio): {[tool.name for tool in tools]}") + + # Example: Using the tools with your Agent, Task, Crew setup + manual_agent = Agent( + role="Local Task Executor", + goal="Execute a specific local task using a manually managed Stdio tool.", + backstory="An AI proficient in controlling local processes via MCP.", + tools=tools, + verbose=True + ) + + manual_task = Task( + description="Execute the 'perform_analysis' command via the Stdio tool.", + expected_output="Results of the analysis.", + agent=manual_agent + ) + + manual_crew = Crew( + agents=[manual_agent], + tasks=[manual_task], + verbose=True, + process=Process.sequential + ) + + + result = manual_crew.kickoff() # Actual inputs depend on your tool + print("\nCrew Task Result (Stdio - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual Stdio MCP integration: {e}") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: # Check if connected before stopping + print("Stopping Stdio MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: # If adapter exists but not connected (e.g. start failed) + print("Stdio MCP server adapter was not connected. No stop needed or start failed.") + +``` + +تذكر استبدال المسارات والأوامر النائبة بتفاصيل خادم Stdio الفعلية. يمكن استخدام معامل `env` في `StdioServerParameters` لتعيين متغيرات البيئة لعملية الخادم، وهو مفيد لإعداد سلوكها أو توفير المسارات اللازمة (مثل `PYTHONPATH`). diff --git a/docs/v1.15.13/ar/mcp/streamable-http.mdx b/docs/v1.15.13/ar/mcp/streamable-http.mdx new file mode 100644 index 0000000000..a4567ea74f --- /dev/null +++ b/docs/v1.15.13/ar/mcp/streamable-http.mdx @@ -0,0 +1,136 @@ +--- +title: نقل Streamable HTTP +description: تعلم كيفية ربط CrewAI بخوادم MCP البعيدة باستخدام نقل Streamable HTTP المرن. +icon: globe +mode: "wide" +--- + +## نظرة عامة + +يوفر نقل Streamable HTTP طريقة مرنة للاتصال بخوادم MCP البعيدة. يُبنى عادةً على HTTP ويمكنه دعم أنماط اتصال متنوعة، بما في ذلك الطلب والاستجابة والبث، وأحياناً يستخدم Server-Sent Events (SSE) لتدفقات من الخادم إلى العميل ضمن تفاعل HTTP أوسع. + +## المفاهيم الرئيسية + +- **خوادم بعيدة**: مصمم لخوادم MCP المستضافة عن بُعد. +- **المرونة**: يمكنه دعم أنماط تفاعل أكثر تعقيداً من SSE العادي، بما في ذلك الاتصال ثنائي الاتجاه المحتمل إذا نفذه الخادم. +- **إعداد `MCPServerAdapter`**: ستحتاج إلى توفير عنوان URL الأساسي للخادم للاتصال MCP وتحديد `"streamable-http"` كنوع النقل. + +## الاتصال عبر Streamable HTTP + +لديك طريقتان رئيسيتان لإدارة دورة حياة الاتصال مع خادم MCP Streamable HTTP: + +### 1. اتصال مُدار بالكامل (الموصى به) + +النهج الموصى به هو استخدام مدير سياق Python (تعليمة `with`)، الذي يتعامل مع إعداد الاتصال وإنهائه تلقائياً. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8001/mcp", # Replace with your actual Streamable HTTP server URL + "transport": "streamable-http" +} + +try: + with MCPServerAdapter(server_params) as tools: + print(f"Available tools from Streamable HTTP MCP server: {[tool.name for tool in tools]}") + + http_agent = Agent( + role="HTTP Service Integrator", + goal="Utilize tools from a remote MCP server via Streamable HTTP.", + backstory="An AI agent adept at interacting with complex web services.", + tools=tools, + verbose=True, + ) + + http_task = Task( + description="Perform a complex data query using a tool from the Streamable HTTP server.", + expected_output="The result of the complex data query.", + agent=http_agent, + ) + + http_crew = Crew( + agents=[http_agent], + tasks=[http_task], + verbose=True, + process=Process.sequential + ) + + result = http_crew.kickoff() + print("\nCrew Task Result (Streamable HTTP - Managed):\n", result) + +except Exception as e: + print(f"Error connecting to or using Streamable HTTP MCP server (Managed): {e}") + print("Ensure the Streamable HTTP MCP server is running and accessible at the specified URL.") + +``` +**ملاحظة:** استبدل `"http://localhost:8001/mcp"` بعنوان URL الفعلي لخادم MCP Streamable HTTP الخاص بك. + +### 2. دورة حياة اتصال يدوية + +للسيناريوهات التي تتطلب تحكماً أكثر صراحة، يمكنك إدارة اتصال `MCPServerAdapter` يدوياً. + + +من **الضروري** استدعاء `mcp_server_adapter.stop()` عند الانتهاء لإغلاق الاتصال وتحرير الموارد. كتلة `try...finally` هي الطريقة الأكثر أماناً لضمان ذلك. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8001/mcp", # Replace with your actual Streamable HTTP server URL + "transport": "streamable-http" +} + +mcp_server_adapter = None +try: + mcp_server_adapter = MCPServerAdapter(server_params) + mcp_server_adapter.start() + tools = mcp_server_adapter.tools + print(f"Available tools (manual Streamable HTTP): {[tool.name for tool in tools]}") + + manual_http_agent = Agent( + role="Advanced Web Service User", + goal="Interact with an MCP server using manually managed Streamable HTTP connections.", + backstory="An AI specialist in fine-tuning HTTP-based service integrations.", + tools=tools, + verbose=True + ) + + data_processing_task = Task( + description="Submit data for processing and retrieve results via Streamable HTTP.", + expected_output="Processed data or confirmation.", + agent=manual_http_agent + ) + + data_crew = Crew( + agents=[manual_http_agent], + tasks=[data_processing_task], + verbose=True, + process=Process.sequential + ) + + result = data_crew.kickoff() + print("\nCrew Task Result (Streamable HTTP - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual Streamable HTTP MCP integration: {e}") + print("Ensure the Streamable HTTP MCP server is running and accessible.") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: + print("Stopping Streamable HTTP MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: + print("Streamable HTTP MCP server adapter was not connected. No stop needed or start failed.") +``` + +## اعتبارات الأمان + +عند استخدام نقل Streamable HTTP، فإن أفضل ممارسات أمان الويب العامة ضرورية: +- **استخدم HTTPS**: فضّل دائماً HTTPS لعناوين URL خوادم MCP لتشفير البيانات أثناء النقل. +- **المصادقة**: نفّذ آليات مصادقة قوية إذا كان خادم MCP يكشف أدوات أو بيانات حساسة. +- **التحقق من المدخلات**: تأكد من أن خادم MCP يتحقق من جميع الطلبات والمعاملات الواردة. + +للحصول على دليل شامل حول تأمين تكاملات MCP، يرجى الرجوع إلى صفحة [اعتبارات الأمان](./security.mdx) ووثائق [أمان نقل MCP](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations) الرسمية. diff --git a/docs/v1.15.13/ar/observability/arize-phoenix.mdx b/docs/v1.15.13/ar/observability/arize-phoenix.mdx new file mode 100644 index 0000000000..239cced3ec --- /dev/null +++ b/docs/v1.15.13/ar/observability/arize-phoenix.mdx @@ -0,0 +1,150 @@ +--- +title: Arize Phoenix +description: تكامل Arize Phoenix مع CrewAI باستخدام OpenTelemetry و OpenInference +icon: magnifying-glass-chart +mode: "wide" +--- + +# تكامل Arize Phoenix + +يوضح هذا الدليل كيفية دمج **Arize Phoenix** مع **CrewAI** باستخدام OpenTelemetry عبر حزمة [OpenInference](https://github.com/openinference/openinference) SDK. بنهاية هذا الدليل، ستتمكن من تتبع وكلاء CrewAI وتصحيح أخطاء وكلائك بسهولة. + +> **ما هو Arize Phoenix؟** [Arize Phoenix](https://phoenix.arize.com) هو منصة مراقبة LLM توفر التتبع والتقييم لتطبيقات الذكاء الاصطناعي. + +[![شاهد عرض فيديو لتكاملنا مع Phoenix](https://storage.googleapis.com/arize-assets/fixtures/setup_crewai.png)](https://www.youtube.com/watch?v=Yc5q3l6F7Ww) + +## البدء + +سنمر عبر مثال بسيط لاستخدام CrewAI ودمجه مع Arize Phoenix عبر OpenTelemetry باستخدام OpenInference. + +يمكنك أيضاً الوصول إلى هذا الدليل على [Google Colab](https://colab.research.google.com/github/Arize-ai/phoenix/blob/main/tutorials/tracing/crewai_tracing_tutorial.ipynb). + +### الخطوة 1: تثبيت الاعتماديات + +```bash +pip install openinference-instrumentation-crewai crewai crewai-tools arize-phoenix-otel +``` + +### الخطوة 2: إعداد متغيرات البيئة + +قم بإعداد مفاتيح API لـ Phoenix Cloud وإعداد OpenTelemetry لإرسال التتبعات إلى Phoenix. Phoenix Cloud هو إصدار مستضاف من Arize Phoenix، لكنه ليس مطلوباً لاستخدام هذا التكامل. + +يمكنك الحصول على مفتاح Serper API المجاني [هنا](https://serper.dev/). + +```python +import os +from getpass import getpass + +# Get your Phoenix Cloud credentials +PHOENIX_API_KEY = getpass("🔑 Enter your Phoenix Cloud API Key: ") + +# Get API keys for services +OPENAI_API_KEY = getpass("🔑 Enter your OpenAI API key: ") +SERPER_API_KEY = getpass("🔑 Enter your Serper API key: ") + +# Set environment variables +os.environ["PHOENIX_CLIENT_HEADERS"] = f"api_key={PHOENIX_API_KEY}" +os.environ["PHOENIX_COLLECTOR_ENDPOINT"] = "https://app.phoenix.arize.com" # Phoenix Cloud, change this to your own endpoint if you are using a self-hosted instance +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +os.environ["SERPER_API_KEY"] = SERPER_API_KEY +``` + +### الخطوة 3: تهيئة OpenTelemetry مع Phoenix + +قم بتهيئة OpenInference OpenTelemetry instrumentation SDK لبدء التقاط التتبعات وإرسالها إلى Phoenix. + +```python +from phoenix.otel import register + +tracer_provider = register( + project_name="crewai-tracing-demo", + auto_instrument=True, +) +``` + +### الخطوة 4: إنشاء تطبيق CrewAI + +سننشئ تطبيق CrewAI حيث يتعاون وكيلان للبحث وكتابة مقال مدونة حول تطورات الذكاء الاصطناعي. + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool +from openinference.instrumentation.crewai import CrewAIInstrumentor +from phoenix.otel import register + +# setup monitoring for your crew +tracer_provider = register( + endpoint="http://localhost:6006/v1/traces") +CrewAIInstrumentor().instrument(skip_dep_check=True, tracer_provider=tracer_provider) +search_tool = SerperDevTool() + +# Define your agents with roles and goals +researcher = Agent( + role="Senior Research Analyst", + goal="Uncover cutting-edge developments in AI and data science", + backstory="""You work at a leading tech think tank. + Your expertise lies in identifying emerging trends. + You have a knack for dissecting complex data and presenting actionable insights.""", + verbose=True, + allow_delegation=False, + tools=[search_tool], +) +writer = Agent( + role="Tech Content Strategist", + goal="Craft compelling content on tech advancements", + backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles. + You transform complex concepts into compelling narratives.""", + verbose=True, + allow_delegation=True, +) + +# Create tasks for your agents +task1 = Task( + description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024. + Identify key trends, breakthrough technologies, and potential industry impacts.""", + expected_output="Full analysis report in bullet points", + agent=researcher, +) + +task2 = Task( + description="""Using the insights provided, develop an engaging blog + post that highlights the most significant AI advancements. + Your post should be informative yet accessible, catering to a tech-savvy audience. + Make it sound cool, avoid complex words so it doesn't sound like AI.""", + expected_output="Full blog post of at least 4 paragraphs", + agent=writer, +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[researcher, writer], tasks=[task1, task2], verbose=1, process=Process.sequential +) + +# Get your crew to work! +result = crew.kickoff() + +print("######################") +print(result) +``` + +### الخطوة 5: عرض التتبعات في Phoenix + +بعد تشغيل الوكيل، يمكنك عرض التتبعات المولدة من تطبيق CrewAI في Phoenix. سترى خطوات مفصلة لتفاعلات الوكلاء واستدعاءات LLM، مما يساعدك في التصحيح والتحسين. + +سجل الدخول إلى حساب Phoenix Cloud الخاص بك وانتقل إلى المشروع الذي حددته في معامل `project_name`. سترى عرض زمني للتتبع مع جميع تفاعلات الوكلاء واستخدامات الأدوات واستدعاءات LLM. + +![مثال تتبع في Phoenix يوضح تفاعلات الوكلاء](https://storage.googleapis.com/arize-assets/fixtures/crewai_traces.png) + + +### معلومات التوافق +- Python 3.8+ +- CrewAI >= 0.86.0 +- Arize Phoenix >= 7.0.1 +- OpenTelemetry SDK >= 1.31.0 + + +### المراجع +- [وثائق Phoenix](https://docs.arize.com/phoenix/) - نظرة عامة على منصة Phoenix. +- [وثائق CrewAI](https://docs.crewai.com/) - نظرة عامة على إطار عمل CrewAI. +- [وثائق OpenTelemetry](https://opentelemetry.io/docs/) - دليل OpenTelemetry +- [OpenInference GitHub](https://github.com/openinference/openinference) - الكود المصدري لـ OpenInference SDK. diff --git a/docs/v1.15.13/ar/observability/braintrust.mdx b/docs/v1.15.13/ar/observability/braintrust.mdx new file mode 100644 index 0000000000..7f52d9e928 --- /dev/null +++ b/docs/v1.15.13/ar/observability/braintrust.mdx @@ -0,0 +1,232 @@ +--- +title: Braintrust +description: تكامل Braintrust مع CrewAI باستخدام تتبع وتقييم OpenTelemetry +icon: magnifying-glass-chart +mode: "wide" +--- + +# تكامل Braintrust + +يوضح هذا الدليل كيفية دمج **Braintrust** مع **CrewAI** باستخدام OpenTelemetry للتتبع والتقييم الشامل. بنهاية هذا الدليل، ستتمكن من تتبع وكلاء CrewAI ومراقبة أدائهم وتقييم مخرجاتهم باستخدام منصة المراقبة القوية من Braintrust. + +> **ما هو Braintrust؟** [Braintrust](https://www.braintrust.dev) هو منصة تقييم ومراقبة للذكاء الاصطناعي توفر تتبعاً شاملاً وتقييماً ومراقبة لتطبيقات الذكاء الاصطناعي مع تتبع تجارب مدمج وتحليلات أداء. + +## البدء + +سنمر عبر مثال بسيط لاستخدام CrewAI ودمجه مع Braintrust عبر OpenTelemetry للمراقبة والتقييم الشامل. + +### الخطوة 1: تثبيت الاعتماديات + +```bash +uv add braintrust[otel] crewai crewai-tools opentelemetry-instrumentation-openai opentelemetry-instrumentation-crewai python-dotenv +``` + +### الخطوة 2: إعداد متغيرات البيئة + +قم بإعداد مفاتيح API لـ Braintrust وإعداد OpenTelemetry لإرسال التتبعات إلى Braintrust. ستحتاج إلى مفتاح API من Braintrust ومفتاح API من OpenAI. + +```python +import os +from getpass import getpass + +# Get your Braintrust credentials +BRAINTRUST_API_KEY = getpass("🔑 Enter your Braintrust API Key: ") + +# Get API keys for services +OPENAI_API_KEY = getpass("🔑 Enter your OpenAI API key: ") + +# Set environment variables +os.environ["BRAINTRUST_API_KEY"] = BRAINTRUST_API_KEY +os.environ["BRAINTRUST_PARENT"] = "project_name:crewai-demo" +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +``` + +### الخطوة 3: تهيئة OpenTelemetry مع Braintrust + +قم بتهيئة أداة Braintrust OpenTelemetry لبدء التقاط التتبعات وإرسالها إلى Braintrust. + +```python +import os +from typing import Any, Dict + +from braintrust.otel import BraintrustSpanProcessor +from crewai import Agent, Crew, Task +from crewai.llm import LLM +from opentelemetry import trace +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.instrumentation.openai import OpenAIInstrumentor +from opentelemetry.sdk.trace import TracerProvider + +def setup_tracing() -> None: + """Setup OpenTelemetry tracing with Braintrust.""" + current_provider = trace.get_tracer_provider() + if isinstance(current_provider, TracerProvider): + provider = current_provider + else: + provider = TracerProvider() + trace.set_tracer_provider(provider) + + provider.add_span_processor(BraintrustSpanProcessor()) + CrewAIInstrumentor().instrument(tracer_provider=provider) + OpenAIInstrumentor().instrument(tracer_provider=provider) + + +setup_tracing() +``` + +### الخطوة 4: إنشاء تطبيق CrewAI + +سننشئ تطبيق CrewAI حيث يتعاون وكيلان للبحث وكتابة مقال مدونة حول تطورات الذكاء الاصطناعي، مع تفعيل التتبع الشامل. + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool + +def create_crew() -> Crew: + """Create a crew with multiple agents for comprehensive tracing.""" + llm = LLM(model="gpt-4o-mini") + search_tool = SerperDevTool() + + researcher = Agent( + role="Senior Research Analyst", + goal="Uncover cutting-edge developments in AI and data science", + backstory="""You work at a leading tech think tank. + Your expertise lies in identifying emerging trends. + You have a knack for dissecting complex data and presenting actionable insights.""", + verbose=True, + allow_delegation=False, + llm=llm, + tools=[search_tool], + ) + + writer = Agent( + role="Tech Content Strategist", + goal="Craft compelling content on tech advancements", + backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles. + You transform complex concepts into compelling narratives.""", + verbose=True, + allow_delegation=True, + llm=llm, + ) + + research_task = Task( + description="""Conduct a comprehensive analysis of the latest advancements in {topic}. + Identify key trends, breakthrough technologies, and potential industry impacts.""", + expected_output="Full analysis report in bullet points", + agent=researcher, + ) + + writing_task = Task( + description="""Using the insights provided, develop an engaging blog + post that highlights the most significant {topic} advancements. + Your post should be informative yet accessible, catering to a tech-savvy audience. + Make it sound cool, avoid complex words so it doesn't sound like AI.""", + expected_output="Full blog post of at least 4 paragraphs", + agent=writer, + context=[research_task], + ) + + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True, + process=Process.sequential + ) + + return crew + +def run_crew(): + """Run the crew and return results.""" + crew = create_crew() + result = crew.kickoff(inputs={"topic": "AI developments"}) + return result + +if __name__ == "__main__": + result = run_crew() + print(result) +``` + +### الخطوة 5: عرض التتبعات في Braintrust + +بعد تشغيل طاقمك، يمكنك عرض تتبعات شاملة في Braintrust من خلال وجهات نظر مختلفة: + + + + + عرض تتبع Braintrust + + + + + + عرض الجدول الزمني Braintrust + + + + + + عرض المحادثة Braintrust + + + + +### الخطوة 6: التقييم عبر SDK (التجارب) + +يمكنك أيضاً تشغيل التقييمات باستخدام Braintrust Eval SDK. هذا مفيد لمقارنة الإصدارات أو تسجيل المخرجات. فيما يلي مثال Python باستخدام فئة `Eval`: + +```python +# eval_crew.py +from braintrust import Eval +from autoevals import Levenshtein + +def evaluate_crew_task(input_data): + """Task function that wraps our crew for evaluation.""" + crew = create_crew() + result = crew.kickoff(inputs={"topic": input_data["topic"]}) + return str(result) + +Eval( + "AI Research Crew", + { + "data": lambda: [ + {"topic": "artificial intelligence trends 2024"}, + {"topic": "machine learning breakthroughs"}, + {"topic": "AI ethics and governance"}, + ], + "task": evaluate_crew_task, + "scores": [Levenshtein], + }, +) +``` + +قم بإعداد مفتاح API الخاص بك وشغّل: + +```bash +export BRAINTRUST_API_KEY="YOUR_API_KEY" +braintrust eval eval_crew.py +``` + +راجع [دليل Braintrust Eval SDK](https://www.braintrust.dev/docs/start/eval-sdk) لمزيد من التفاصيل. + +### الميزات الرئيسية لتكامل Braintrust + +- **تتبع شامل**: تتبع جميع تفاعلات الوكلاء واستخدام الأدوات واستدعاءات LLM +- **مراقبة الأداء**: مراقبة أوقات التنفيذ واستخدام الرموز ومعدلات النجاح +- **تتبع التجارب**: مقارنة إعدادات الطاقم والنماذج المختلفة +- **التقييم الآلي**: إعداد مقاييس تقييم مخصصة لمخرجات الطاقم +- **تتبع الأخطاء**: مراقبة وتصحيح حالات الفشل عبر عمليات تنفيذ الطاقم +- **تحليل التكاليف**: تتبع استخدام الرموز والتكاليف المرتبطة + +### معلومات التوافق +- Python 3.8+ +- CrewAI >= 0.86.0 +- Braintrust >= 0.1.0 +- OpenTelemetry SDK >= 1.31.0 + +### المراجع +- [وثائق Braintrust](https://www.braintrust.dev/docs) - نظرة عامة على منصة Braintrust +- [تكامل Braintrust CrewAI](https://www.braintrust.dev/docs/integrations/crew-ai) - دليل التكامل الرسمي مع CrewAI +- [Braintrust Eval SDK](https://www.braintrust.dev/docs/start/eval-sdk) - تشغيل التجارب عبر SDK +- [وثائق CrewAI](https://docs.crewai.com/) - نظرة عامة على إطار عمل CrewAI +- [وثائق OpenTelemetry](https://opentelemetry.io/docs/) - دليل OpenTelemetry +- [Braintrust GitHub](https://github.com/braintrustdata/braintrust) - الكود المصدري لـ Braintrust SDK diff --git a/docs/v1.15.13/ar/observability/datadog.mdx b/docs/v1.15.13/ar/observability/datadog.mdx new file mode 100644 index 0000000000..0d6ebebe96 --- /dev/null +++ b/docs/v1.15.13/ar/observability/datadog.mdx @@ -0,0 +1,109 @@ +--- +title: تكامل Datadog +description: تعلم كيفية دمج Datadog مع CrewAI لإرسال تتبعات مراقبة LLM إلى Datadog. +icon: dog +mode: "wide" +--- + +# دمج Datadog مع CrewAI + +سيوضح هذا الدليل كيفية دمج **[Datadog LLM Observability](https://docs.datadoghq.com/llm_observability/)** مع **CrewAI** باستخدام [أداة Datadog للتجهيز التلقائي](https://docs.datadoghq.com/llm_observability/instrumentation/auto_instrumentation?tab=python). بنهاية هذا الدليل، ستتمكن من إرسال تتبعات مراقبة LLM إلى Datadog وعرض تشغيلات وكلاء CrewAI في [عرض التنفيذ الوكيلي](https://docs.datadoghq.com/llm_observability/monitoring/agent_monitoring) من Datadog LLM Observability. + +## ما هو Datadog LLM Observability؟ + +[Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/) يساعد مهندسي الذكاء الاصطناعي وعلماء البيانات ومطوري التطبيقات على تطوير وتقييم ومراقبة تطبيقات LLM بسرعة. حسّن جودة المخرجات والأداء والتكاليف والمخاطر الإجمالية بثقة مع تجارب منظمة وتتبع شامل عبر وكلاء الذكاء الاصطناعي والتقييمات. + +## البدء + +### تثبيت الاعتماديات + +```shell +pip install ddtrace crewai crewai-tools +``` + +### تعيين متغيرات البيئة + +إذا لم يكن لديك مفتاح API من Datadog، يمكنك [إنشاء حساب](https://www.datadoghq.com/) و[الحصول على مفتاح API](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys). + +ستحتاج أيضاً إلى تحديد اسم تطبيق ML في متغيرات البيئة التالية. تطبيق ML هو تجميع لتتبعات LLM Observability المرتبطة بتطبيق محدد قائم على LLM. + +```shell +export DD_API_KEY= +export DD_SITE= +export DD_LLMOBS_ENABLED=true +export DD_LLMOBS_ML_APP= +export DD_LLMOBS_AGENTLESS_ENABLED=true +export DD_APM_TRACING_ENABLED=false +``` + +بالإضافة إلى ذلك، قم بإعداد مفاتيح API لمزودي LLM + +```shell +export OPENAI_API_KEY= +export ANTHROPIC_API_KEY= +export GEMINI_API_KEY= +... +``` + +### إنشاء تطبيق وكيل CrewAI + +```python +# crewai_agent.py +from crewai import Agent, Task, Crew + +from crewai_tools import ( + WebsiteSearchTool +) + +web_rag_tool = WebsiteSearchTool() + +writer = Agent( + role="Writer", + goal="You make math engaging and understandable for young children through poetry", + backstory="You're an expert in writing haikus but you know nothing of math.", + tools=[web_rag_tool], +) + +task = Task( + description=("What is {multiplication}?"), + expected_output=("Compose a haiku that includes the answer."), + agent=writer +) + +crew = Crew( + agents=[writer], + tasks=[task], + share_crew=False +) + +output = crew.kickoff(dict(multiplication="2 * 2")) +``` + +### تشغيل التطبيق مع التجهيز التلقائي من Datadog + +مع تعيين [متغيرات البيئة](#تعيين-متغيرات-البيئة)، يمكنك الآن تشغيل التطبيق مع التجهيز التلقائي من Datadog. + +```shell +ddtrace-run python crewai_agent.py +``` + +### عرض التتبعات في Datadog + +بعد تشغيل التطبيق، يمكنك عرض التتبعات في [عرض تتبعات Datadog LLM Observability](https://app.datadoghq.com/llm/traces)، باختيار اسم تطبيق ML الذي اخترته من القائمة المنسدلة أعلى اليسار. + +النقر على تتبع سيعرض لك تفاصيل التتبع، بما في ذلك إجمالي الرموز المستخدمة وعدد استدعاءات LLM والنماذج المستخدمة والتكلفة المقدرة. + + +عرض تتبع Datadog LLM Observability + + +بالإضافة إلى ذلك، يمكنك عرض رسم بياني لتنفيذ التتبع، الذي يوضح تدفق التحكم والبيانات للتتبع. + + +عرض تدفق تنفيذ وكيل Datadog LLM Observability + + +## المراجع + +- [Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/) +- [التجهيز التلقائي لـ CrewAI من Datadog LLM Observability](https://docs.datadoghq.com/llm_observability/instrumentation/auto_instrumentation?tab=python#crew-ai) diff --git a/docs/v1.15.13/ar/observability/galileo.mdx b/docs/v1.15.13/ar/observability/galileo.mdx new file mode 100644 index 0000000000..9c51f2306c --- /dev/null +++ b/docs/v1.15.13/ar/observability/galileo.mdx @@ -0,0 +1,86 @@ +--- +title: Galileo +description: تكامل Galileo مع CrewAI للتتبع والتقييم +icon: telescope +mode: "wide" +--- + +## نظرة عامة + +يوضح هذا الدليل كيفية دمج **Galileo** مع **CrewAI** للتتبع الشامل وهندسة التقييم. بنهاية هذا الدليل، ستتمكن من تتبع وكلاء CrewAI ومراقبة أدائهم وتقييم سلوكهم باستخدام منصة المراقبة القوية من Galileo. + +> **ما هو Galileo؟** [Galileo](https://galileo.ai) هو منصة تقييم ومراقبة للذكاء الاصطناعي توفر تتبعاً شاملاً وتقييماً ومراقبة لتطبيقات الذكاء الاصطناعي. تمكّن الفرق من التقاط البيانات الحقيقية وإنشاء حواجز قوية وتشغيل تجارب منهجية مع تتبع تجارب مدمج وتحليلات أداء. + +## البدء + +يتبع هذا البرنامج التعليمي [البدء السريع مع CrewAI](/ar/quickstart) ويوضح كيفية إضافة [CrewAIEventListener](https://v2docs.galileo.ai/sdk-api/python/reference/handlers/crewai/handler) من Galileo كمعالج أحداث. + +> **ملاحظة** يفترض هذا البرنامج التعليمي أنك أكملت [البدء السريع مع CrewAI](/ar/quickstart). + +### الخطوة 1: تثبيت الاعتماديات + +ثبّت الاعتماديات المطلوبة لتطبيقك: + +```bash +uv add galileo +``` + +### الخطوة 2: أضف إلى ملف .env من [البدء السريع مع CrewAI](/ar/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 " +``` + +### الخطوة 3: إضافة مستمع أحداث Galileo + +لتفعيل التسجيل مع Galileo، تحتاج إلى إنشاء مثيل من `CrewAIEventListener`. استورد حزمة معالج CrewAI من Galileo بإضافة الكود التالي في أعلى ملف 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: شغّل طاقمك + +شغّل طاقمك باستخدام CrewAI CLI: + +```bash +crewai run +``` + +### الخطوة 5: عرض التتبعات في Galileo + +بمجرد انتهاء طاقمك، سيتم تفريغ التتبعات وستظهر في Galileo. + +![عرض تتبع Galileo](/images/galileo-trace-veiw.png) + +## فهم تكامل Galileo + +يتكامل Galileo مع CrewAI عن طريق تسجيل مستمع أحداث يلتقط أحداث تنفيذ الطاقم (مثل إجراءات الوكلاء واستدعاءات الأدوات واستجابات النماذج) ويعيد توجيهها إلى Galileo للمراقبة والتقييم. + +### فهم مستمع الأحداث + +إنشاء مثيل `CrewAIEventListener()` هو كل ما يلزم لتفعيل Galileo لتشغيل CrewAI. عند الإنشاء، يقوم المستمع بـ: + +- التسجيل تلقائياً مع CrewAI +- قراءة إعدادات Galileo من متغيرات البيئة +- تسجيل جميع بيانات التشغيل في مشروع Galileo وتدفق السجل المحدد بواسطة `GALILEO_PROJECT` و `GALILEO_LOG_STREAM` + +لا يلزم أي إعداد إضافي أو تغييرات في الكود. diff --git a/docs/v1.15.13/ar/observability/langdb.mdx b/docs/v1.15.13/ar/observability/langdb.mdx new file mode 100644 index 0000000000..42726faaaf --- /dev/null +++ b/docs/v1.15.13/ar/observability/langdb.mdx @@ -0,0 +1,167 @@ +--- +title: تكامل LangDB +description: إدارة وتأمين وتحسين سير عمل CrewAI مع بوابة LangDB AI — الوصول إلى أكثر من 350 نموذجاً وتوجيه تلقائي وتحسين التكاليف ومراقبة كاملة. +icon: database +mode: "wide" +--- + +# مقدمة + +توفر [بوابة LangDB AI](https://langdb.ai) واجهات API متوافقة مع OpenAI للاتصال بنماذج لغة كبيرة متعددة وتعمل كمنصة مراقبة تجعل تتبع سير عمل CrewAI شاملاً وسهلاً مع توفير الوصول إلى أكثر من 350 نموذج لغة. مع استدعاء `init()` واحد، يتم التقاط جميع تفاعلات الوكلاء وتنفيذ المهام واستدعاءات LLM، مما يوفر مراقبة شاملة وبنية تحتية جاهزة للإنتاج لتطبيقاتك. + + + مثال تتبع LangDB CrewAI + + +**تحقق من:** [عرض مثال التتبع المباشر](https://app.langdb.ai/sharing/threads/3becbfed-a1be-ae84-ea3c-4942867a3e22) + +## الميزات + +### قدرات بوابة AI +- **الوصول إلى أكثر من 350 LLM**: الاتصال بجميع نماذج اللغة الرئيسية من خلال تكامل واحد +- **النماذج الافتراضية**: إنشاء إعدادات نماذج مخصصة مع معاملات وقواعد توجيه محددة +- **MCP الافتراضي**: تفعيل التوافق والتكامل مع أنظمة MCP لتعزيز اتصال الوكلاء +- **حواجز الحماية**: تنفيذ تدابير السلامة وضوابط الامتثال لسلوك الوكلاء + +### المراقبة والتتبع +- **تتبع تلقائي**: استدعاء `init()` واحد يلتقط جميع تفاعلات CrewAI +- **رؤية شاملة**: مراقبة سير عمل الوكلاء من البداية إلى النهاية +- **تتبع استخدام الأدوات**: تتبع الأدوات التي يستخدمها الوكلاء ونتائجها +- **مراقبة استدعاءات النماذج**: رؤى مفصلة لتفاعلات LLM +- **تحليلات الأداء**: مراقبة زمن الاستجابة واستخدام الرموز والتكاليف +- **دعم التصحيح**: تنفيذ خطوة بخطوة لاستكشاف الأخطاء +- **المراقبة في الوقت الفعلي**: لوحة معلومات التتبعات والمقاييس الحية + +## تعليمات الإعداد + + + + ثبّت عميل LangDB مع علامة ميزة CrewAI: + ```bash + pip install 'pylangdb[crewai]' + ``` + + + قم بإعداد بيانات اعتماد LangDB: + ```bash + export LANGDB_API_KEY="" + export LANGDB_PROJECT_ID="" + export LANGDB_API_BASE_URL='https://api.us-east-1.langdb.ai' + ``` + + + استورد وهيّئ LangDB قبل إعداد كود CrewAI: + ```python + from pylangdb.crewai import init + # Initialize LangDB + init() + ``` + + + قم بإعداد LLM مع رؤوس LangDB: + ```python + from crewai import Agent, Task, Crew, LLM + import os + + # Configure LLM with LangDB headers + llm = LLM( + model="openai/gpt-4o", + api_key=os.getenv("LANGDB_API_KEY"), + base_url=os.getenv("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.getenv("LANGDB_PROJECT_ID")} + ) + ``` + + + +## مثال سريع للبدء + +```python +import os +from pylangdb.crewai import init +from crewai import Agent, Task, Crew, LLM + +init() + +def create_llm(model): + return LLM( + model=model, + api_key=os.environ.get("LANGDB_API_KEY"), + base_url=os.environ.get("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.environ.get("LANGDB_PROJECT_ID")} + ) + +researcher = Agent( + role="Research Specialist", + goal="Research topics thoroughly", + backstory="Expert researcher with skills in finding information", + llm=create_llm("openai/gpt-4o"), + verbose=True +) + +task = Task( + description="Research the given topic and provide a comprehensive summary", + agent=researcher, + expected_output="Detailed research summary with key findings" +) + +crew = Crew(agents=[researcher], tasks=[task]) +result = crew.kickoff() +print(result) +``` + +## عرض التتبعات في LangDB + +بعد تشغيل تطبيق CrewAI، يمكنك عرض تتبعات مفصلة في لوحة معلومات LangDB: + + + لوحة معلومات تتبع LangDB تعرض سير عمل CrewAI + + +### ما ستراه + +- **تفاعلات الوكلاء**: التدفق الكامل لمحادثات الوكلاء وتسليم المهام +- **استخدام الأدوات**: الأدوات التي تم استدعاؤها ومدخلاتها ومخرجاتها +- **استدعاءات النماذج**: تفاعلات LLM المفصلة مع المطالبات والاستجابات +- **مقاييس الأداء**: تتبع زمن الاستجابة واستخدام الرموز والتكاليف +- **الجدول الزمني للتنفيذ**: عرض خطوة بخطوة لسير العمل بالكامل + +## استكشاف الأخطاء وإصلاحها + +### المشاكل الشائعة + +- **عدم ظهور تتبعات**: تأكد من استدعاء `init()` قبل أي استيرادات CrewAI +- **أخطاء المصادقة**: تحقق من مفتاح API ومعرف المشروع في LangDB + +## الموارد + + + + الوثائق والأدلة الرسمية لـ LangDB + + + برامج تعليمية خطوة بخطوة لبناء وكلاء AI + + + أمثلة تكامل CrewAI الكاملة + + + الوصول إلى تتبعاتك وتحليلاتك + + + تصفح أكثر من 350 نموذج لغة متاح + + + خيارات الاستضافة الذاتية وقدرات المؤسسات + + + +## الخطوات التالية + +غطى هذا الدليل أساسيات دمج بوابة LangDB AI مع CrewAI. لتعزيز سير عمل الذكاء الاصطناعي بشكل أكبر، استكشف: + +- **النماذج الافتراضية**: إنشاء إعدادات نماذج مخصصة مع استراتيجيات توجيه +- **حواجز الحماية والسلامة**: تنفيذ تصفية المحتوى وضوابط الامتثال +- **النشر في الإنتاج**: إعداد خطط احتياطية وإعادة المحاولة وتوازن الأحمال + +لمزيد من الميزات المتقدمة وحالات الاستخدام، زُر [وثائق LangDB](https://docs.langdb.ai) أو استكشف [كتالوج النماذج](https://app.langdb.ai/models) لاكتشاف جميع النماذج المتاحة. diff --git a/docs/v1.15.13/ar/observability/langfuse.mdx b/docs/v1.15.13/ar/observability/langfuse.mdx new file mode 100644 index 0000000000..e62d2e6572 --- /dev/null +++ b/docs/v1.15.13/ar/observability/langfuse.mdx @@ -0,0 +1,109 @@ +--- +title: تكامل Langfuse +description: تعلم كيفية دمج Langfuse مع CrewAI عبر OpenTelemetry باستخدام OpenLit +icon: vials +mode: "wide" +--- + +# دمج Langfuse مع CrewAI + +يوضح هذا الدفتر كيفية دمج **Langfuse** مع **CrewAI** باستخدام OpenTelemetry عبر حزمة **OpenLit** SDK. بنهاية هذا الدفتر، ستتمكن من تتبع تطبيقات CrewAI مع Langfuse لتحسين المراقبة والتصحيح. + +> **ما هو Langfuse؟** [Langfuse](https://langfuse.com) هو منصة هندسة LLM مفتوحة المصدر. توفر قدرات التتبع والمراقبة لتطبيقات LLM، مما يساعد المطورين على التصحيح والتحليل والتحسين. يتكامل Langfuse مع أدوات وأطر عمل متنوعة عبر تكاملات أصلية وOpenTelemetry وواجهات API/SDKs. + +[![فيديو نظرة عامة على Langfuse](https://github.com/user-attachments/assets/3926b288-ff61-4b95-8aa1-45d041c70866)](https://langfuse.com/watch-demo) + +## البدء + +سنمر عبر مثال بسيط لاستخدام CrewAI ودمجه مع Langfuse عبر OpenTelemetry باستخدام OpenLit. + +### الخطوة 1: تثبيت الاعتماديات + +```python +%pip install langfuse openlit crewai crewai_tools +``` + +### الخطوة 2: إعداد متغيرات البيئة + +عيّن مفاتيح API لـ Langfuse وإعدادات تصدير OpenTelemetry لإرسال التتبعات إلى Langfuse. يرجى الرجوع إلى [وثائق Langfuse OpenTelemetry](https://langfuse.com/docs/opentelemetry/get-started) لمزيد من المعلومات. + +```python +import os + +# Get keys for your project from the project settings page: https://cloud.langfuse.com +os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..." +os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..." +os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # 🇪🇺 EU region +# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # 🇺🇸 US region + + +# Your OpenAI key +os.environ["OPENAI_API_KEY"] = "sk-proj-..." +``` + +مع تعيين متغيرات البيئة، يمكننا الآن تهيئة عميل Langfuse. تهيئ `get_client()` عميل Langfuse باستخدام بيانات الاعتماد المقدمة في متغيرات البيئة. + +```python +from langfuse import get_client + +langfuse = get_client() + +# Verify connection +if langfuse.auth_check(): + print("Langfuse client is authenticated and ready!") +else: + print("Authentication failed. Please check your credentials and host.") +``` + +### الخطوة 3: تهيئة OpenLit + +قم بتهيئة OpenLit OpenTelemetry instrumentation SDK لبدء التقاط تتبعات OpenTelemetry. + +```python +import openlit + +openlit.init() +``` + +### الخطوة 4: إنشاء تطبيق CrewAI بسيط + +سننشئ تطبيق CrewAI بسيط حيث يتعاون عدة وكلاء للإجابة على سؤال المستخدم. + +```python +from crewai import Agent, Task, Crew + +from crewai_tools import ( + WebsiteSearchTool +) + +web_rag_tool = WebsiteSearchTool() + +writer = Agent( + role="Writer", + goal="You make math engaging and understandable for young children through poetry", + backstory="You're an expert in writing haikus but you know nothing of math.", + tools=[web_rag_tool], + ) + +task = Task(description=("What is {multiplication}?"), + expected_output=("Compose a haiku that includes the answer."), + agent=writer) + +crew = Crew( + agents=[writer], + tasks=[task], + share_crew=False +) +``` + +### الخطوة 5: عرض التتبعات في Langfuse + +بعد تشغيل الوكيل، يمكنك عرض التتبعات المولدة من تطبيق CrewAI في [Langfuse](https://cloud.langfuse.com). سترى خطوات مفصلة لتفاعلات LLM، مما يساعدك في التصحيح والتحسين. + +![مثال تتبع CrewAI في Langfuse](https://langfuse.com/images/cookbook/integration_crewai/crewai-example-trace.png) + +_[مثال تتبع عام في Langfuse](https://cloud.langfuse.com/project/cloramnkj0002jz088vzn1ja4/traces/e2cf380ffc8d47d28da98f136140642b?timestamp=2025-02-05T15%3A12%3A02.717Z&observation=3b32338ee6a5d9af)_ + +## المراجع + +- [وثائق Langfuse OpenTelemetry](https://langfuse.com/docs/opentelemetry/get-started) diff --git a/docs/v1.15.13/ar/observability/langtrace.mdx b/docs/v1.15.13/ar/observability/langtrace.mdx new file mode 100644 index 0000000000..d07f3f35ee --- /dev/null +++ b/docs/v1.15.13/ar/observability/langtrace.mdx @@ -0,0 +1,73 @@ +--- +title: تكامل Langtrace +description: كيفية مراقبة التكلفة وزمن الاستجابة وأداء وكلاء CrewAI باستخدام Langtrace، أداة مراقبة خارجية. +icon: chart-line +mode: "wide" +--- + +# نظرة عامة على Langtrace + +Langtrace هو أداة مفتوحة المصدر خارجية تساعدك في إعداد المراقبة والتقييمات لنماذج اللغة الكبيرة (LLMs) وأطر عمل LLM وقواعد بيانات المتجهات. +على الرغم من أنها ليست مبنية مباشرة في CrewAI، يمكن استخدام Langtrace جنباً إلى جنب مع CrewAI للحصول على رؤية عميقة في التكلفة وزمن الاستجابة وأداء وكلاء CrewAI. +يتيح لك هذا التكامل تسجيل المعاملات الفائقة ومراقبة تراجعات الأداء وإنشاء عملية للتحسين المستمر لوكلائك. + +![نظرة عامة على سلسلة مختارة من جلسات تشغيل الوكلاء](/images/langtrace1.png) +![نظرة عامة على تتبعات الوكلاء](/images/langtrace2.png) +![نظرة عامة على تتبعات LLM بالتفصيل](/images/langtrace3.png) + +## تعليمات الإعداد + + + + سجّل بزيارة [https://langtrace.ai/signup](https://langtrace.ai/signup). + + + عيّن نوع المشروع إلى `CrewAI` وقم بتوليد مفتاح API. + + + استخدم الأمر التالي: + + ```bash + pip install langtrace-python-sdk + ``` + + + استورد وهيّئ Langtrace في بداية نصك البرمجي، قبل أي استيرادات CrewAI: + + ```python + from langtrace_python_sdk import langtrace + langtrace.init(api_key='') + + # Now import CrewAI modules + from crewai import Agent, Task, Crew + ``` + + + +### الميزات وتطبيقاتها على CrewAI + +1. **تتبع رموز LLM والتكاليف** + + - مراقبة استخدام الرموز والتكاليف المرتبطة لكل تفاعل وكيل CrewAI. + +2. **رسم بياني للتتبع لخطوات التنفيذ** + + - تصور تدفق تنفيذ مهام CrewAI، بما في ذلك زمن الاستجابة والسجلات. + - مفيد لتحديد الاختناقات في سير عمل الوكلاء. + +3. **تنظيم مجموعات البيانات مع التعليق اليدوي** + + - إنشاء مجموعات بيانات من مخرجات مهام CrewAI للتدريب أو التقييم المستقبلي. + +4. **إدارة إصدارات المطالبات** + + - تتبع الإصدارات المختلفة من المطالبات المستخدمة في وكلاء CrewAI. + - مفيد لاختبار A/B وتحسين أداء الوكلاء. + +5. **ساحة المطالبات مع مقارنات النماذج** + + - اختبار ومقارنة مطالبات ونماذج مختلفة لوكلاء CrewAI قبل النشر. + +6. **الاختبارات والتقييمات** + + - إعداد اختبارات آلية لوكلاء ومهام CrewAI. diff --git a/docs/v1.15.13/ar/observability/maxim.mdx b/docs/v1.15.13/ar/observability/maxim.mdx new file mode 100644 index 0000000000..dd311643bf --- /dev/null +++ b/docs/v1.15.13/ar/observability/maxim.mdx @@ -0,0 +1,221 @@ +--- +title: "تكامل Maxim" +description: "بدء مراقبة وتقييم ومراقبة الوكلاء" +icon: "infinity" +mode: "wide" +--- + +# نظرة عامة على Maxim + +يوفر Maxim AI مراقبة شاملة للوكلاء وتقييماً ومراقبة لتطبيقات CrewAI. مع تكامل Maxim بسطر واحد، يمكنك بسهولة تتبع وتحليل تفاعلات الوكلاء ومقاييس الأداء والمزيد. + +## الميزات + +### إدارة المطالبات + +تمكّنك قدرات إدارة المطالبات في Maxim من إنشاء وتنظيم وتحسين المطالبات لوكلاء CrewAI. بدلاً من ترميز التعليمات مباشرة، استفد من SDK الخاص بـ Maxim لاسترداد وتطبيق مطالبات مُدارة بالإصدارات ديناميكياً. + + + + أنشئ وصقل وجرّب وانشر مطالباتك عبر الساحة. نظّم مطالباتك باستخدام المجلدات والإصدارات، وجرّب مع حالات العالم الحقيقي عن طريق ربط الأدوات والسياق، وانشر بناءً على منطق مخصص. + + + + + مع بناء الفرق لتطبيقات الذكاء الاصطناعي، يُعد جزء كبير من التجريب هو التكرار على هيكل المطالبات. للتعاون بفعالية وتنظيم التغييرات بوضوح، يسمح Maxim بإصدارات المطالبات ومقارنة التشغيلات عبر الإصدارات. + + + + + التكرار على المطالبات أثناء تطوير تطبيق الذكاء الاصطناعي يحتاج تجارب عبر النماذج وهياكل المطالبات وغيرها. لمقارنة الإصدارات واتخاذ قرارات مستنيرة، تسمح ساحة المقارنة بعرض جنب إلى جنب للنتائج. + + ## **لماذا تستخدم مقارنة المطالبات؟** + + تجمع مقارنة المطالبات عدة مطالبات فردية في عرض واحد، مما يمكّن من نهج مبسط لسير عمل متنوع: + + 1. **مقارنة النماذج**: تقييم أداء نماذج مختلفة على نفس المطالبة. + 2. **تحسين المطالبات**: مقارنة إصدارات مختلفة لتحديد الصياغة الأكثر فعالية. + 3. **اتساق عبر النماذج**: ضمان مخرجات متسقة عبر نماذج مختلفة لنفس المطالبة. + 4. **قياس الأداء**: تحليل مقاييس مثل زمن الاستجابة والتكلفة وعدد الرموز عبر نماذج ومطالبات مختلفة. + + + +### المراقبة والتقييمات + +يوفر Maxim AI مراقبة وتقييماً شاملاً لوكلاء CrewAI، مما يساعدك في فهم ما يحدث بالضبط أثناء كل تنفيذ. + + + + تتبع دورة حياة وكيلك الكاملة، بما في ذلك استدعاءات الأدوات ومسارات الوكلاء وتدفقات القرار بسهولة. + + + + + شغّل تقييمات مفصلة على التتبعات الكاملة أو العقد الفردية مع دعم لـ: + + - التفاعلات متعددة الخطوات وتحليل التتبع الدقيق + - تقييمات على مستوى الجلسة + - محاكاة لاختبار العالم الحقيقي + + + + + +

+ تقييم السجلات الملتقطة تلقائياً من واجهة المستخدم بناءً على المرشحات والعينات +

+
+ +

+ استخدام التقييم البشري أو التصنيف لتقييم جودة سجلاتك +

+
+ +

+ تقييم أي مكون من تتبعك أو سجلك للحصول على رؤى حول سلوك وكيلك +

+
+
+ --- +
+ + عيّن حدوداً على **الأخطاء والتكلفة واستخدام الرموز وتغذية المستخدم الراجعة وزمن الاستجابة** واحصل على تنبيهات فورية عبر Slack أو PagerDuty. + + + + + تصور التتبعات عبر الزمن ومقاييس الاستخدام وزمن الاستجابة ومعدلات الأخطاء بسهولة. + + + +
+ +## البدء + +### المتطلبات الأساسية + +- إصدار Python >= 3.10 +- حساب Maxim ([سجّل هنا](https://getmaxim.ai/)) +- توليد مفتاح API من Maxim +- مشروع CrewAI + +### التثبيت + +ثبّت Maxim SDK عبر pip: + +```python +pip install maxim-py +``` + +أو أضفه إلى ملف `requirements.txt`: + +``` +maxim-py +``` + +### الإعداد الأساسي + +### 1. إعداد متغيرات البيئة + +```python +### Environment Variables Setup + +# Create a `.env` file in your project root: + +# Maxim API Configuration +MAXIM_API_KEY=your_api_key_here +MAXIM_LOG_REPO_ID=your_repo_id_here +``` + +### 2. استيراد الحزم المطلوبة + +```python +from crewai import Agent, Task, Crew, Process +from maxim import Maxim +from maxim.logger.crewai import instrument_crewai +``` + +### 3. تهيئة Maxim بمفتاح API + +```python {8} +# Instrument CrewAI with just one line +instrument_crewai(Maxim().logger()) +``` + +### 4. إنشاء وتشغيل تطبيق CrewAI كالمعتاد + +```python +# Create your agent +researcher = Agent( + role='Senior Research Analyst', + goal='Uncover cutting-edge developments in AI', + backstory="You are an expert researcher at a tech think tank...", + verbose=True, + llm=llm +) + +# Define the task +research_task = Task( + description="Research the latest AI advancements...", + expected_output="", + agent=researcher +) + +# Configure and run the crew +crew = Crew( + agents=[researcher], + tasks=[research_task], + verbose=True +) + +try: + result = crew.kickoff() +finally: + maxim.cleanup() # Ensure cleanup happens even if errors occur +``` + +هذا كل شيء! سيتم الآن تسجيل جميع تفاعلات وكلاء CrewAI وستكون متاحة في لوحة معلومات Maxim. + +تحقق من دفتر Google Colab هذا كمرجع سريع - [الدفتر](https://colab.research.google.com/drive/1ZKIZWsmgQQ46n8TH9zLsT1negKkJA6K8?usp=sharing) + +## عرض تتبعاتك + +بعد تشغيل تطبيق CrewAI: + +1. سجل الدخول إلى [لوحة معلومات Maxim](https://app.getmaxim.ai/login) +2. انتقل إلى مستودعك +3. اعرض تتبعات الوكلاء المفصلة، بما في ذلك: + - محادثات الوكلاء + - أنماط استخدام الأدوات + - مقاييس الأداء + - تحليلات التكاليف + + + +## استكشاف الأخطاء وإصلاحها + +### المشاكل الشائعة + +- **عدم ظهور تتبعات**: تأكد من صحة مفتاح API ومعرف المستودع +- تأكد من استدعاء **`instrument_crewai()`** **_قبل_** تشغيل طاقمك +- عيّن `debug=True` في استدعاء `instrument_crewai()` لإظهار أي أخطاء داخلية: + + ```python + instrument_crewai(logger, debug=True) + ``` +- أعدّ وكلاءك مع `verbose=True` لالتقاط سجلات مفصلة +- تحقق مرة أخرى من أن `instrument_crewai()` يُستدعى **قبل** إنشاء أو تنفيذ الوكلاء + +## الموارد + + + + وثائق CrewAI الرسمية + + + وثائق Maxim الرسمية + + + Maxim Github + + diff --git a/docs/v1.15.13/ar/observability/mlflow.mdx b/docs/v1.15.13/ar/observability/mlflow.mdx new file mode 100644 index 0000000000..d8945f14d7 --- /dev/null +++ b/docs/v1.15.13/ar/observability/mlflow.mdx @@ -0,0 +1,206 @@ +--- +title: تكامل MLflow +description: ابدأ بسرعة في مراقبة وكلائك باستخدام MLflow. +icon: bars-staggered +mode: "wide" +--- + +# نظرة عامة على MLflow + +[MLflow](https://mlflow.org/) هو منصة مفتوحة المصدر لمساعدة ممارسي تعلم الآلة والفرق في التعامل مع تعقيدات عملية تعلم الآلة. + +يوفر ميزة التتبع التي تعزز قابلية مراقبة نماذج اللغة الكبيرة (LLM) في تطبيقات الذكاء الاصطناعي التوليدي الخاصة بك من خلال التقاط معلومات تفصيلية حول تنفيذ خدمات تطبيقك. +يوفر التتبع طريقة لتسجيل المدخلات والمخرجات والبيانات الوصفية المرتبطة بكل خطوة وسيطة في الطلب، مما يتيح لك تحديد مصدر الأخطاء والسلوكيات غير المتوقعة بسهولة. + +![نظرة عامة على استخدام تتبع crewAI مع MLflow](/images/mlflow-tracing.gif) + +### الميزات + +- **لوحة معلومات التتبع**: راقب أنشطة وكلاء crewAI الخاصين بك من خلال لوحات معلومات تفصيلية تتضمن المدخلات والمخرجات والبيانات الوصفية للنطاقات. +- **التتبع الآلي**: تكامل مؤتمت بالكامل مع crewAI، يمكن تفعيله عبر تشغيل `mlflow.crewai.autolog()`. +- **أدوات التتبع اليدوي بأقل مجهود**: خصّص أدوات التتبع من خلال واجهات برمجة التطبيقات عالية المستوى من MLflow مثل المزخرفات وأغلفة الدوال ومديري السياق. +- **التوافق مع OpenTelemetry**: يدعم تتبع MLflow تصدير التتبعات إلى جامع OpenTelemetry، الذي يمكن استخدامه بعد ذلك لتصدير التتبعات إلى خلفيات متنوعة مثل Jaeger وZipkin وAWS X-Ray. +- **تغليف ونشر الوكلاء**: قم بتغليف ونشر وكلاء crewAI الخاصين بك إلى خادم استدلال مع مجموعة متنوعة من أهداف النشر. +- **استضافة آمنة لنماذج LLM**: استضف نماذج LLM متعددة من مزودين مختلفين في نقطة نهاية موحدة من خلال بوابة MLflow. +- **التقييم**: قيّم وكلاء crewAI الخاصين بك باستخدام مجموعة واسعة من المقاييس عبر واجهة برمجة تطبيقات مريحة `mlflow.evaluate()`. + +## تعليمات الإعداد + + + + ```shell + # The crewAI integration is available in mlflow>=2.19.0 + pip install mlflow + ``` + + + ```shell + # This process is optional, but it is recommended to use MLflow tracking server for better visualization and broader features. + mlflow server + ``` + + + أضف السطرين التاليين إلى كود تطبيقك: + + ```python + import mlflow + + mlflow.crewai.autolog() + + # Optional: Set a tracking URI and an experiment name if you have a tracking server + mlflow.set_tracking_uri("http://localhost:5000") + mlflow.set_experiment("CrewAI") + ``` + + مثال على الاستخدام لتتبع وكلاء CrewAI: + + ```python + from crewai import Agent, Crew, Task + from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + from crewai_tools import SerperDevTool, WebsiteSearchTool + + from textwrap import dedent + + content = "Users name is John. He is 30 years old and lives in San Francisco." + string_source = StringKnowledgeSource( + content=content, metadata={"preference": "personal"} + ) + + search_tool = WebsiteSearchTool() + + + class TripAgents: + def city_selection_agent(self): + return Agent( + role="City Selection Expert", + goal="Select the best city based on weather, season, and prices", + backstory="An expert in analyzing travel data to pick ideal destinations", + tools=[ + search_tool, + ], + verbose=True, + ) + + def local_expert(self): + return Agent( + role="Local Expert at this city", + goal="Provide the BEST insights about the selected city", + backstory="""A knowledgeable local guide with extensive information + about the city, it's attractions and customs""", + tools=[search_tool], + verbose=True, + ) + + + class TripTasks: + def identify_task(self, agent, origin, cities, interests, range): + return Task( + description=dedent( + f""" + Analyze and select the best city for the trip based + on specific criteria such as weather patterns, seasonal + events, and travel costs. This task involves comparing + multiple cities, considering factors like current weather + conditions, upcoming cultural or seasonal events, and + overall travel expenses. + Your final answer must be a detailed + report on the chosen city, and everything you found out + about it, including the actual flight costs, weather + forecast and attractions. + + Traveling from: {origin} + City Options: {cities} + Trip Date: {range} + Traveler Interests: {interests} + """ + ), + agent=agent, + expected_output="Detailed report on the chosen city including flight costs, weather forecast, and attractions", + ) + + def gather_task(self, agent, origin, interests, range): + return Task( + description=dedent( + f""" + As a local expert on this city you must compile an + in-depth guide for someone traveling there and wanting + to have THE BEST trip ever! + Gather information about key attractions, local customs, + special events, and daily activity recommendations. + Find the best spots to go to, the kind of place only a + local would know. + This guide should provide a thorough overview of what + the city has to offer, including hidden gems, cultural + hotspots, must-visit landmarks, weather forecasts, and + high level costs. + The final answer must be a comprehensive city guide, + rich in cultural insights and practical tips, + tailored to enhance the travel experience. + + Trip Date: {range} + Traveling from: {origin} + Traveler Interests: {interests} + """ + ), + agent=agent, + expected_output="Comprehensive city guide including hidden gems, cultural hotspots, and practical travel tips", + ) + + + class TripCrew: + def __init__(self, origin, cities, date_range, interests): + self.cities = cities + self.origin = origin + self.interests = interests + self.date_range = date_range + + def run(self): + agents = TripAgents() + tasks = TripTasks() + + city_selector_agent = agents.city_selection_agent() + local_expert_agent = agents.local_expert() + + identify_task = tasks.identify_task( + city_selector_agent, + self.origin, + self.cities, + self.interests, + self.date_range, + ) + gather_task = tasks.gather_task( + local_expert_agent, self.origin, self.interests, self.date_range + ) + + crew = Crew( + agents=[city_selector_agent, local_expert_agent], + tasks=[identify_task, gather_task], + verbose=True, + memory=True, + knowledge={ + "sources": [string_source], + "metadata": {"preference": "personal"}, + }, + ) + + result = crew.kickoff() + return result + + + trip_crew = TripCrew("California", "Tokyo", "Dec 12 - Dec 20", "sports") + result = trip_crew.run() + + print(result) + ``` + راجع [وثائق تتبع MLflow](https://mlflow.org/docs/latest/llms/tracing/index.html) لمزيد من الإعدادات وحالات الاستخدام. + + + الآن يتم التقاط تتبعات وكلاء crewAI الخاصين بك بواسطة MLflow. + لنقم بزيارة خادم تتبع MLflow لعرض التتبعات والحصول على رؤى حول وكلائك. + + افتح `127.0.0.1:5000` في متصفحك لزيارة خادم تتبع MLflow. + + MLflow tracing example with crewai + + + diff --git a/docs/v1.15.13/ar/observability/neatlogs.mdx b/docs/v1.15.13/ar/observability/neatlogs.mdx new file mode 100644 index 0000000000..7fbc188ad5 --- /dev/null +++ b/docs/v1.15.13/ar/observability/neatlogs.mdx @@ -0,0 +1,134 @@ +--- +title: تكامل Neatlogs +description: افهم وأصلح وشارك عمليات تشغيل وكلاء CrewAI الخاصة بك +icon: magnifying-glass-chart +mode: "wide" +--- + +# مقدمة + +يساعدك Neatlogs على **رؤية ما فعله وكيلك**، و**لماذا**، و**مشاركته**. + +يلتقط كل خطوة: الأفكار، واستدعاءات الأدوات، والاستجابات، والتقييمات. لا سجلات خام. فقط تتبعات واضحة ومنظمة. ممتاز لتصحيح الأخطاء والتعاون. + +## لماذا تستخدم Neatlogs؟ + +يستخدم وكلاء CrewAI أدوات متعددة وخطوات تفكير. عندما يحدث خطأ ما، تحتاج إلى السياق - وليس فقط الأخطاء. + +يتيح لك Neatlogs: + +- تتبع مسار اتخاذ القرار بالكامل +- إضافة ملاحظات مباشرة على الخطوات +- الدردشة مع التتبع باستخدام مساعد الذكاء الاصطناعي +- مشاركة عمليات التشغيل علنياً للحصول على ملاحظات +- تحويل الرؤى إلى مهام + +كل ذلك في مكان واحد. + +إدارة تتبعاتك بسهولة + +![التتبعات](/images/neatlogs-1.png) +![استجابة التتبع](/images/neatlogs-2.png) + +أفضل تجربة مستخدم لعرض تتبع CrewAI. انشر التعليقات أينما تريد. استخدم الذكاء الاصطناعي لتصحيح الأخطاء. + +![تفاصيل التتبع](/images/neatlogs-3.png) +![روبوت الدردشة الذكي مع التتبع](/images/neatlogs-4.png) +![درج التعليقات](/images/neatlogs-5.png) + +## الميزات الأساسية + +- **عارض التتبع**: تتبع الأفكار والأدوات والقرارات بالتسلسل +- **التعليقات المضمنة**: أشر إلى زملاء الفريق على أي خطوة تتبع +- **الملاحظات والتقييم**: حدد المخرجات كصحيحة أو غير صحيحة +- **إبراز الأخطاء**: وسم تلقائي لأخطاء API/الأدوات +- **تحويل المهام**: حوّل التعليقات إلى مهام موكلة +- **اسأل التتبع (AI)**: تحدث مع تتبعك باستخدام روبوت Neatlogs الذكي +- **المشاركة العامة**: انشر روابط التتبع لمجتمعك + +## إعداد سريع مع CrewAI + + + + قم بزيارة [neatlogs.com](https://neatlogs.com/?utm_source=crewAI-docs)، وأنشئ مشروعاً، وانسخ مفتاح API. + + + ```bash + pip install neatlogs + ``` + (أحدث إصدار 0.8.0، Python 3.8+؛ رخصة MIT) + + + قبل بدء وكلاء Crew، أضف: + + ```python + import neatlogs + neatlogs.init("YOUR_PROJECT_API_KEY") + ``` + + يعمل الوكلاء كالمعتاد. يلتقط Neatlogs كل شيء تلقائياً. + + + + + + +## تحت الغطاء + +وفقاً لـ GitHub، فإن Neatlogs: + +- يلتقط الأفكار واستدعاءات الأدوات والاستجابات والأخطاء وإحصائيات الرموز المميزة +- يدعم توليد المهام بالذكاء الاصطناعي وسير عمل التقييم المتين + +كل ذلك بسطرين فقط من الكود. + + + +## شاهده وهو يعمل + +### عرض توضيحي كامل (4 دقائق) + + + +### تكامل CrewAI (30 ثانية) + + + + + +## الروابط والدعم + +- [وثائق Neatlogs](https://docs.neatlogs.com/) +- [لوحة التحكم ومفتاح API](https://app.neatlogs.com/) +- [تابعنا على Twitter](https://twitter.com/neatlogs) +- البريد الإلكتروني: hello@neatlogs.com +- [GitHub SDK](https://github.com/NeatLogs/neatlogs) + + + +## الخلاصة + +بمجرد: + +```bash +pip install neatlogs + +import neatlogs +neatlogs.init("YOUR_API_KEY") + +You can now capture, understand, share, and act on your CrewAI agent runs in seconds. +No setup overhead. Full trace transparency. Full team collaboration. +``` diff --git a/docs/v1.15.13/ar/observability/openlit.mdx b/docs/v1.15.13/ar/observability/openlit.mdx new file mode 100644 index 0000000000..a0aa5533d4 --- /dev/null +++ b/docs/v1.15.13/ar/observability/openlit.mdx @@ -0,0 +1,181 @@ +--- +title: تكامل OpenLIT +description: ابدأ بسرعة في مراقبة وكلائك بسطر واحد فقط من الكود باستخدام OpenTelemetry. +icon: magnifying-glass-chart +mode: "wide" +--- + +# نظرة عامة على OpenLIT + +[OpenLIT](https://github.com/openlit/openlit?src=crewai-docs) هو أداة مفتوحة المصدر تجعل من السهل مراقبة أداء وكلاء الذكاء الاصطناعي ونماذج LLM وقواعد بيانات المتجهات ووحدات GPU بسطر **واحد** فقط من الكود. + +يوفر تتبعاً ومقاييس أصلية لـ OpenTelemetry لتتبع المعلمات المهمة مثل التكلفة وزمن الاستجابة والتفاعلات وتسلسل المهام. +يمكّنك هذا الإعداد من تتبع المعلمات الفائقة ومراقبة مشكلات الأداء، مما يساعدك في إيجاد طرق لتحسين وضبط وكلائك بمرور الوقت. + + + Overview Agent usage including cost and tokens + Overview of agent otel traces and metrics + Overview of agent traces in details + + +### الميزات + +- **لوحة معلومات التحليلات**: راقب صحة وأداء وكلائك من خلال لوحات معلومات تفصيلية تتتبع المقاييس والتكاليف وتفاعلات المستخدمين. +- **SDK مراقبة أصلي لـ OpenTelemetry**: حزم SDK محايدة للمورد لإرسال التتبعات والمقاييس إلى أدوات المراقبة الحالية مثل Grafana وDataDog وغيرها. +- **تتبع التكاليف للنماذج المخصصة والمعدّلة**: خصّص تقديرات التكلفة لنماذج محددة باستخدام ملفات تسعير مخصصة لوضع ميزانية دقيقة. +- **لوحة مراقبة الاستثناءات**: اكتشف وحل المشكلات بسرعة من خلال تتبع الاستثناءات والأخطاء الشائعة بلوحة مراقبة. +- **الامتثال والأمان**: اكتشف التهديدات المحتملة مثل الألفاظ البذيئة وتسريبات المعلومات الشخصية. +- **كشف حقن الموجهات**: حدد حقن الكود المحتمل وتسريبات الأسرار. +- **إدارة مفاتيح API والأسرار**: تعامل مع مفاتيح API لنماذج LLM وأسرارك مركزياً بأمان، مع تجنب الممارسات غير الآمنة. +- **إدارة الموجهات**: أدر وأصدر موجهات الوكلاء باستخدام PromptHub للوصول المتسق والسهل عبر الوكلاء. +- **ساحة تجربة النماذج**: اختبر وقارن نماذج مختلفة لوكلاء CrewAI قبل النشر. + +## تعليمات الإعداد + + + + + + ```shell + git clone git@github.com:openlit/openlit.git + ``` + + + من المجلد الجذري لـ [مستودع OpenLIT](https://github.com/openlit/openlit)، شغّل الأمر التالي: + ```shell + docker compose up -d + ``` + + + + + ```shell + pip install openlit + ``` + + + أضف السطرين التاليين إلى كود تطبيقك: + + + ```python + import openlit + openlit.init(otlp_endpoint="http://127.0.0.1:4318") + ``` + + مثال على الاستخدام لمراقبة وكيل CrewAI: + + ```python + from crewai import Agent, Task, Crew, Process + import openlit + + openlit.init(disable_metrics=True) + # Define your agents + researcher = Agent( + role="Researcher", + goal="Conduct thorough research and analysis on AI and AI agents", + backstory="You're an expert researcher, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently researching for a new client.", + allow_delegation=False, + llm='command-r' + ) + + + # Define your task + task = Task( + description="Generate a list of 5 interesting ideas for an article, then write one captivating paragraph for each idea that showcases the potential of a full article on this topic. Return the list of ideas with their paragraphs and your notes.", + expected_output="5 bullet points, each with a paragraph and accompanying notes.", + ) + + # Define the manager agent + manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success. Your role is to coordinate the efforts of the crew members, ensuring that each task is completed on time and to the highest standard.", + allow_delegation=True, + llm='command-r' + ) + + # Instantiate your crew with a custom manager + crew = Crew( + agents=[researcher], + tasks=[task], + manager_agent=manager, + process=Process.hierarchical, + ) + + # Start the crew's work + result = crew.kickoff() + + print(result) + ``` + + + + أضف السطرين التاليين إلى كود تطبيقك: + ```python + import openlit + + openlit.init() + ``` + + شغّل الأمر التالي لإعداد نقطة نهاية تصدير OTEL: + ```shell + export OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4318" + ``` + + مثال على الاستخدام لمراقبة وكيل CrewAI غير متزامن: + + ```python + import asyncio + from crewai import Crew, Agent, Task + import openlit + + openlit.init(otlp_endpoint="http://127.0.0.1:4318") + + # Create an agent with code execution enabled + coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True, + llm="command-r" + ) + + # Create a task that requires code execution + data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="5 bullet points, each with a paragraph and accompanying notes.", + ) + + # Create a crew and add the task + analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] + ) + + # Async function to kickoff the crew asynchronously + async def async_crew_execution(): + result = await analysis_crew.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + + # Run the async function + asyncio.run(async_crew_execution()) + ``` + + + راجع [مستودع Python SDK الخاص بـ OpenLIT](https://github.com/openlit/openlit/tree/main/sdk/python) لمزيد من الإعدادات المتقدمة وحالات الاستخدام. + + + مع جمع بيانات مراقبة الوكلاء وإرسالها إلى OpenLIT، الخطوة التالية هي عرض وتحليل هذه البيانات للحصول على رؤى حول أداء وكيلك وسلوكه وتحديد مجالات التحسين. + + ما عليك سوى التوجه إلى OpenLIT على `127.0.0.1:3000` في متصفحك لبدء الاستكشاف. يمكنك تسجيل الدخول باستخدام بيانات الاعتماد الافتراضية + - **البريد الإلكتروني**: `user@openlit.io` + - **كلمة المرور**: `openlituser` + + + Overview Agent usage including cost and tokens + Overview of agent otel traces and metrics + + + + diff --git a/docs/v1.15.13/ar/observability/opik.mdx b/docs/v1.15.13/ar/observability/opik.mdx new file mode 100644 index 0000000000..60442fe475 --- /dev/null +++ b/docs/v1.15.13/ar/observability/opik.mdx @@ -0,0 +1,130 @@ +--- +title: تكامل Opik +description: تعرّف على كيفية استخدام Comet Opik لتصحيح الأخطاء وتقييم ومراقبة تطبيقات CrewAI الخاصة بك مع تتبع شامل وتقييمات آلية ولوحات معلومات جاهزة للإنتاج. +icon: meteor +mode: "wide" +--- + +# نظرة عامة على Opik + +مع [Comet Opik](https://www.comet.com/docs/opik/)، يمكنك تصحيح الأخطاء وتقييم ومراقبة تطبيقات LLM وأنظمة RAG وسير العمل الوكيلي مع تتبع شامل وتقييمات آلية ولوحات معلومات جاهزة للإنتاج. + + + Opik agent monitoring example with CrewAI + + +يوفر Opik دعماً شاملاً لكل مرحلة من مراحل تطوير تطبيق CrewAI الخاص بك: + +- **تسجيل التتبعات والنطاقات**: تتبع تلقائي لاستدعاءات LLM ومنطق التطبيق لتصحيح الأخطاء وتحليل أنظمة التطوير والإنتاج. أضف التعليقات التوضيحية يدوياً أو برمجياً، واعرض وقارن الاستجابات عبر المشاريع. +- **تقييم أداء تطبيق LLM**: قيّم وفقاً لمجموعة اختبار مخصصة وشغّل مقاييس تقييم مدمجة أو حدد مقاييسك الخاصة في SDK أو واجهة المستخدم. +- **الاختبار ضمن خط أنابيب CI/CD**: أنشئ خطوط أساس أداء موثوقة مع اختبارات وحدة LLM من Opik، المبنية على PyTest. شغّل تقييمات عبر الإنترنت للمراقبة المستمرة في الإنتاج. +- **مراقبة وتحليل بيانات الإنتاج**: افهم أداء نماذجك على بيانات غير مرئية في الإنتاج وأنشئ مجموعات بيانات لتكرارات التطوير الجديدة. + +## الإعداد +يوفر Comet نسخة مستضافة من منصة Opik، أو يمكنك تشغيل المنصة محلياً. + +لاستخدام النسخة المستضافة، ما عليك سوى [إنشاء حساب Comet مجاني](https://www.comet.com/signup?utm_medium=github&utm_source=crewai_docs) والحصول على مفتاح API الخاص بك. + +لتشغيل منصة Opik محلياً، راجع [دليل التثبيت](https://www.comet.com/docs/opik/self-host/overview/) لمزيد من المعلومات. + +في هذا الدليل سنستخدم مثال البدء السريع الخاص بـ CrewAI. + + + + ```shell + pip install crewai crewai-tools opik --upgrade + ``` + + + ```python + import opik + opik.configure(use_local=False) + ``` + + + أولاً، نقوم بإعداد مفاتيح API لمزود LLM كمتغيرات بيئة: + + ```python + import os + import getpass + + if "OPENAI_API_KEY" not in os.environ: + os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ") + ``` + + + الخطوة الأولى هي إنشاء مشروعنا. سنستخدم مثالاً من وثائق CrewAI: + + ```python + from crewai import Agent, Crew, Task, Process + + + class YourCrewName: + def agent_one(self) -> Agent: + return Agent( + role="Data Analyst", + goal="Analyze data trends in the market", + backstory="An experienced data analyst with a background in economics", + verbose=True, + ) + + def agent_two(self) -> Agent: + return Agent( + role="Market Researcher", + goal="Gather information on market dynamics", + backstory="A diligent researcher with a keen eye for detail", + verbose=True, + ) + + def task_one(self) -> Task: + return Task( + name="Collect Data Task", + description="Collect recent market data and identify trends.", + expected_output="A report summarizing key trends in the market.", + agent=self.agent_one(), + ) + + def task_two(self) -> Task: + return Task( + name="Market Research Task", + description="Research factors affecting market dynamics.", + expected_output="An analysis of factors influencing the market.", + agent=self.agent_two(), + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.agent_one(), self.agent_two()], + tasks=[self.task_one(), self.task_two()], + process=Process.sequential, + verbose=True, + ) + + ``` + + الآن يمكننا استيراد متتبع Opik وتشغيل الطاقم: + + ```python + from opik.integrations.crewai import track_crewai + + track_crewai(project_name="crewai-integration-demo") + + my_crew = YourCrewName().crew() + result = my_crew.kickoff() + + print(result) + ``` + بعد تشغيل تطبيق CrewAI، قم بزيارة تطبيق Opik لعرض: + - تتبعات LLM والنطاقات وبياناتها الوصفية + - تفاعلات الوكلاء وتدفق تنفيذ المهام + - مقاييس الأداء مثل زمن الاستجابة واستخدام الرموز المميزة + - مقاييس التقييم (مدمجة أو مخصصة) + + + +## الموارد + +- [وثائق Opik](https://www.comet.com/docs/opik/) +- [Opik + CrewAI Colab](https://colab.research.google.com/github/comet-ml/opik/blob/main/apps/opik-documentation/documentation/docs/cookbook/crewai.ipynb) +- [X](https://x.com/cometml) +- [Slack](https://slack.comet.com/) diff --git a/docs/v1.15.13/ar/observability/overview.mdx b/docs/v1.15.13/ar/observability/overview.mdx new file mode 100644 index 0000000000..9e6e239c7d --- /dev/null +++ b/docs/v1.15.13/ar/observability/overview.mdx @@ -0,0 +1,120 @@ +--- +title: "نظرة عامة" +description: "راقب وقيّم وحسّن وكلاء CrewAI الخاصين بك باستخدام أدوات مراقبة شاملة" +icon: "face-smile" +mode: "wide" +--- + +## المراقبة في CrewAI + +تعد المراقبة أمراً بالغ الأهمية لفهم كيفية أداء وكلاء CrewAI، وتحديد الاختناقات، وضمان التشغيل الموثوق في بيئات الإنتاج. يغطي هذا القسم مختلف الأدوات والمنصات التي توفر إمكانيات المراقبة والتقييم والتحسين لسير عمل وكلائك. + +## لماذا تعد المراقبة مهمة + +- **مراقبة الأداء**: تتبع أوقات تنفيذ الوكلاء واستخدام الرموز المميزة واستهلاك الموارد +- **ضمان الجودة**: تقييم جودة المخرجات واتساقها عبر سيناريوهات مختلفة +- **تصحيح الأخطاء**: تحديد وحل المشكلات في سلوك الوكلاء وتنفيذ المهام +- **إدارة التكاليف**: مراقبة استخدام API لنماذج LLM والتكاليف المرتبطة بها +- **التحسين المستمر**: جمع الرؤى لتحسين أداء الوكلاء بمرور الوقت + +## أدوات المراقبة المتاحة + +### منصات المراقبة والتتبع + + + + + تتبع شامل لسير عمل CrewAI مع التقاط تلقائي لتفاعلات الوكلاء. + + + + مراقبة أصلية لـ OpenTelemetry مع تتبع التكاليف وتحليلات الأداء. + + + + إدارة دورة حياة تعلم الآلة مع إمكانيات التتبع والتقييم. + + + + منصة هندسة LLM مع تتبع وتحليلات تفصيلية. + + + + مراقبة مفتوحة المصدر لنماذج LLM وأطر العمل الوكيلية. + + + + منصة مراقبة الذكاء الاصطناعي للمراقبة واستكشاف الأخطاء وإصلاحها. + + + + بوابة ذكاء اصطناعي مع مراقبة شاملة وميزات موثوقية. + + + + تصحيح الأخطاء وتقييم ومراقبة تطبيقات LLM مع تتبع شامل. + + + + منصة Weights & Biases لتتبع وتقييم تطبيقات الذكاء الاصطناعي. + + + +### التقييم وضمان الجودة + + + + منصة تقييم شاملة لمخرجات LLM وسلوكيات الوكلاء. + + + +## مقاييس المراقبة الرئيسية + +### مقاييس الأداء +- **وقت التنفيذ**: المدة التي يستغرقها الوكلاء لإكمال المهام +- **استخدام الرموز المميزة**: الرموز المدخلة/المخرجة المستهلكة من استدعاءات LLM +- **زمن استجابة API**: أوقات الاستجابة من الخدمات الخارجية +- **معدل النجاح**: نسبة المهام المكتملة بنجاح + +### مقاييس الجودة +- **دقة المخرجات**: صحة استجابات الوكلاء +- **الاتساق**: الموثوقية عبر مدخلات متشابهة +- **الصلة**: مدى تطابق المخرجات مع النتائج المتوقعة +- **السلامة**: الامتثال لسياسات المحتوى والإرشادات + +### مقاييس التكلفة +- **تكاليف API**: النفقات من استخدام مزودي LLM +- **استخدام الموارد**: استهلاك الحوسبة والذاكرة +- **التكلفة لكل مهمة**: الكفاءة الاقتصادية لعمليات الوكلاء +- **تتبع الميزانية**: المراقبة مقابل حدود الإنفاق + +## البدء + +1. **اختر أدواتك**: حدد منصات المراقبة التي تتوافق مع احتياجاتك +2. **أضف الأدوات لكودك**: أضف المراقبة لتطبيقات CrewAI الخاصة بك +3. **أعدّ لوحات المعلومات**: هيئ العروض المرئية للمقاييس الرئيسية +4. **حدد التنبيهات**: أنشئ إشعارات للأحداث المهمة +5. **أنشئ خطوط الأساس**: قس الأداء الأولي للمقارنة +6. **كرر وحسّن**: استخدم الرؤى لتحسين وكلائك + +## أفضل الممارسات + +### مرحلة التطوير +- استخدم التتبع التفصيلي لفهم سلوك الوكلاء +- طبّق مقاييس التقييم مبكراً في التطوير +- راقب استخدام الموارد أثناء الاختبار +- أعدّ فحوصات جودة آلية + +### مرحلة الإنتاج +- طبّق مراقبة وتنبيهات شاملة +- تتبع اتجاهات الأداء بمرور الوقت +- راقب الشذوذ والتدهور +- حافظ على رؤية التكاليف والتحكم بها + +### التحسين المستمر +- مراجعات أداء وتحسين منتظمة +- اختبار A/B لتكوينات وكلاء مختلفة +- حلقات تغذية راجعة لتحسين الجودة +- توثيق الدروس المستفادة + +اختر أدوات المراقبة التي تناسب حالة الاستخدام والبنية التحتية ومتطلبات المراقبة الخاصة بك لضمان أن وكلاء CrewAI يعملون بشكل موثوق وفعال. diff --git a/docs/v1.15.13/ar/observability/patronus-evaluation.mdx b/docs/v1.15.13/ar/observability/patronus-evaluation.mdx new file mode 100644 index 0000000000..c6b522640e --- /dev/null +++ b/docs/v1.15.13/ar/observability/patronus-evaluation.mdx @@ -0,0 +1,206 @@ +--- +title: تقييم Patronus AI +description: راقب وقيّم أداء وكلاء CrewAI باستخدام منصة التقييم الشاملة من Patronus AI لمخرجات LLM وسلوكيات الوكلاء. +icon: shield-check +mode: "wide" +--- + +# تقييم Patronus AI + +## نظرة عامة + +يوفر [Patronus AI](https://patronus.ai) إمكانيات تقييم ومراقبة شاملة لوكلاء CrewAI، مما يمكّنك من تقييم مخرجات النماذج وسلوكيات الوكلاء والأداء العام للنظام. يتيح لك هذا التكامل تنفيذ سير عمل تقييم مستمر يساعد في الحفاظ على الجودة والموثوقية في بيئات الإنتاج. + +## الميزات الرئيسية + +- **التقييم الآلي**: تقييم فوري لمخرجات وسلوكيات الوكلاء +- **معايير مخصصة**: حدد معايير تقييم محددة مصممة لحالات الاستخدام الخاصة بك +- **مراقبة الأداء**: تتبع مقاييس أداء الوكلاء بمرور الوقت +- **ضمان الجودة**: ضمان جودة مخرجات متسقة عبر سيناريوهات مختلفة +- **السلامة والامتثال**: مراقبة المشكلات المحتملة وانتهاكات السياسات + +## أدوات التقييم + +يوفر Patronus ثلاث أدوات تقييم رئيسية لحالات استخدام مختلفة: + +1. **PatronusEvalTool**: يسمح للوكلاء باختيار المقيّم والمعايير الأنسب لمهمة التقييم. +2. **PatronusPredefinedCriteriaEvalTool**: يستخدم مقيّماً ومعايير محددة مسبقاً من قبل المستخدم. +3. **PatronusLocalEvaluatorTool**: يستخدم دوال تقييم مخصصة محددة من قبل المستخدم. + +## التثبيت + +لاستخدام هذه الأدوات، تحتاج إلى تثبيت حزمة Patronus: + +```shell +uv add patronus +``` + +ستحتاج أيضاً إلى إعداد مفتاح API الخاص بـ Patronus كمتغير بيئة: + +```shell +export PATRONUS_API_KEY="your_patronus_api_key" +``` + +## خطوات البدء + +لاستخدام أدوات تقييم Patronus بفعالية، اتبع الخطوات التالية: + +1. **تثبيت Patronus**: ثبّت حزمة Patronus باستخدام الأمر أعلاه. +2. **إعداد مفتاح API**: عيّن مفتاح API الخاص بـ Patronus كمتغير بيئة. +3. **اختيار الأداة المناسبة**: حدد أداة تقييم Patronus المناسبة بناءً على احتياجاتك. +4. **إعداد الأداة**: هيئ الأداة بالمعاملات اللازمة. + +## أمثلة + +### استخدام PatronusEvalTool + +يوضح المثال التالي كيفية استخدام `PatronusEvalTool`، التي تسمح للوكلاء باختيار المقيّم والمعايير الأنسب: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusEvalTool + +# Initialize the tool +patronus_eval_tool = PatronusEvalTool() + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code and verify that the output is code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate and evaluate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence. Select the most appropriate evaluator and criteria for evaluating your output.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +### استخدام PatronusPredefinedCriteriaEvalTool + +يوضح المثال التالي كيفية استخدام `PatronusPredefinedCriteriaEvalTool`، التي تستخدم مقيّماً ومعايير محددة مسبقاً: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusPredefinedCriteriaEvalTool + +# Initialize the tool with predefined criteria +patronus_eval_tool = PatronusPredefinedCriteriaEvalTool( + evaluators=[{"evaluator": "judge", "criteria": "contains-code"}] +) + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +### استخدام PatronusLocalEvaluatorTool + +يوضح المثال التالي كيفية استخدام `PatronusLocalEvaluatorTool`، التي تستخدم دوال تقييم مخصصة: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusLocalEvaluatorTool +from patronus import Client, EvaluationResult +import random + +# Initialize the Patronus client +client = Client() + +# Register a custom evaluator +@client.register_local_evaluator("random_evaluator") +def random_evaluator(**kwargs): + score = random.random() + return EvaluationResult( + score_raw=score, + pass_=score >= 0.5, + explanation="example explanation", + ) + +# Initialize the tool with the custom evaluator +patronus_eval_tool = PatronusLocalEvaluatorTool( + patronus_client=client, + evaluator="random_evaluator", + evaluated_model_gold_answer="example label", +) + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +## المعاملات + +### PatronusEvalTool + +لا تتطلب `PatronusEvalTool` أي معاملات أثناء التهيئة. تقوم تلقائياً بجلب المقيّمين والمعايير المتاحة من API الخاص بـ Patronus. + +### PatronusPredefinedCriteriaEvalTool + +تقبل `PatronusPredefinedCriteriaEvalTool` المعاملات التالية أثناء التهيئة: + +- **evaluators**: مطلوب. قائمة من القواميس تحتوي على المقيّم والمعايير المراد استخدامها. مثال: `[{"evaluator": "judge", "criteria": "contains-code"}]`. + +### PatronusLocalEvaluatorTool + +تقبل `PatronusLocalEvaluatorTool` المعاملات التالية أثناء التهيئة: + +- **patronus_client**: مطلوب. مثيل عميل Patronus. +- **evaluator**: اختياري. اسم المقيّم المحلي المسجل للاستخدام. القيمة الافتراضية هي سلسلة نصية فارغة. +- **evaluated_model_gold_answer**: اختياري. الإجابة المرجعية للاستخدام في التقييم. القيمة الافتراضية هي سلسلة نصية فارغة. + +## الاستخدام + +عند استخدام أدوات تقييم Patronus، تقدم مدخلات النموذج ومخرجاته وسياقه، وتعيد الأداة نتائج التقييم من API الخاص بـ Patronus. + +بالنسبة لـ `PatronusEvalTool` و`PatronusPredefinedCriteriaEvalTool`، المعاملات التالية مطلوبة عند استدعاء الأداة: + +- **evaluated_model_input**: وصف مهمة الوكيل بنص بسيط. +- **evaluated_model_output**: مخرجات الوكيل للمهمة. +- **evaluated_model_retrieved_context**: سياق الوكيل. + +بالنسبة لـ `PatronusLocalEvaluatorTool`، نفس المعاملات مطلوبة، لكن المقيّم والإجابة المرجعية يتم تحديدهما أثناء التهيئة. + +## الخلاصة + +توفر أدوات تقييم Patronus طريقة قوية لتقييم وتسجيل درجات مدخلات ومخرجات النماذج باستخدام منصة Patronus AI. من خلال تمكين الوكلاء من تقييم مخرجاتهم أو مخرجات وكلاء آخرين، يمكن لهذه الأدوات المساعدة في تحسين جودة وموثوقية سير عمل CrewAI. diff --git a/docs/v1.15.13/ar/observability/portkey.mdx b/docs/v1.15.13/ar/observability/portkey.mdx new file mode 100644 index 0000000000..e676b7a353 --- /dev/null +++ b/docs/v1.15.13/ar/observability/portkey.mdx @@ -0,0 +1,823 @@ +--- +title: تكامل Portkey +description: كيفية استخدام Portkey مع CrewAI +icon: key +mode: "wide" +--- + +Portkey CrewAI Header Image + + + +## مقدمة + +يعزز Portkey إمكانيات CrewAI بميزات جاهزة للإنتاج، محولاً طواقم الوكلاء التجريبية إلى أنظمة متينة من خلال توفير: + +- **مراقبة كاملة** لكل خطوة وكيل واستخدام أداة وتفاعل +- **موثوقية مدمجة** مع آليات الاحتياط وإعادة المحاولة وموازنة الأحمال +- **تتبع التكاليف وتحسينها** لإدارة إنفاقك على الذكاء الاصطناعي +- **الوصول إلى أكثر من 200 نموذج LLM** من خلال تكامل واحد +- **حواجز الحماية** للحفاظ على سلوك الوكلاء آمناً ومتوافقاً +- **موجهات مُتحكم بإصداراتها** لأداء وكلاء متسق + + +### التثبيت والإعداد + + + +```bash +pip install -U crewai portkey-ai +``` + + + +أنشئ مفتاح API لـ Portkey مع حدود ميزانية/معدل اختيارية من [لوحة تحكم Portkey](https://app.portkey.ai/). يمكنك أيضاً إرفاق إعدادات للموثوقية والتخزين المؤقت والمزيد لهذا المفتاح. المزيد عن هذا لاحقاً. + + + +التكامل بسيط - ما عليك سوى تحديث إعداد LLM في تكوين CrewAI الخاص بك: + +```python +from crewai import LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Create an LLM instance with Portkey integration +gpt_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", # We are using a Virtual key, so this is a placeholder + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_LLM_VIRTUAL_KEY", + trace_id="unique-trace-id", # Optional, for request tracing + ) +) + +#Use them in your Crew Agents like this: + + @agent + def lead_market_analyst(self) -> Agent: + return Agent( + config=self.agents_config['lead_market_analyst'], + verbose=True, + memory=False, + llm=gpt_llm + ) + +``` + + +**ما هي المفاتيح الافتراضية؟** تخزّن المفاتيح الافتراضية في Portkey مفاتيح API لمزودي LLM (OpenAI وAnthropic وغيرها) بشكل آمن في خزنة مشفرة. تتيح تدوير المفاتيح وإدارة الميزانية بسهولة. [تعرّف على المزيد حول المفاتيح الافتراضية هنا](https://portkey.ai/docs/product/ai-gateway/virtual-keys). + + + + +## ميزات الإنتاج + +### 1. مراقبة محسّنة + +يوفر Portkey مراقبة شاملة لوكلاء CrewAI، مما يساعدك على فهم ما يحدث بالضبط أثناء كل عملية تنفيذ. + + + + + + + +توفر التتبعات عرضاً هرمياً لتنفيذ طاقمك، يظهر تسلسل استدعاءات LLM واستدعاءات الأدوات وانتقالات الحالة. + +```python +# Add trace_id to enable hierarchical tracing in Portkey +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + trace_id="unique-session-id" # Add unique trace ID + ) +) +``` + + + + + + + +يسجّل Portkey كل تفاعل مع نماذج LLM، بما في ذلك: + +- حمولات الطلب والاستجابة الكاملة +- مقاييس زمن الاستجابة واستخدام الرموز المميزة +- حسابات التكلفة +- استدعاءات الأدوات وتنفيذ الدوال + +يمكن تصفية جميع السجلات حسب البيانات الوصفية ومعرّفات التتبع والنماذج والمزيد، مما يسهّل تصحيح أخطاء عمليات تشغيل طاقم محددة. + + + + + + + +يوفر Portkey لوحات معلومات مدمجة تساعدك على: + +- تتبع التكلفة واستخدام الرموز المميزة عبر جميع عمليات تشغيل الطاقم +- تحليل مقاييس الأداء مثل زمن الاستجابة ومعدلات النجاح +- تحديد الاختناقات في سير عمل الوكلاء +- مقارنة تكوينات الطاقم ونماذج LLM المختلفة + +يمكنك تصفية وتقسيم جميع المقاييس حسب بيانات وصفية مخصصة لتحليل أنواع طواقم أو مجموعات مستخدمين أو حالات استخدام محددة. + + + + + Analytics with metadata filters + + +أضف بيانات وصفية مخصصة لتكوين LLM في CrewAI لتمكين تصفية وتقسيم قوية: + +```python +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + metadata={ + "crew_type": "research_crew", + "environment": "production", + "_user": "user_123", # Special _user field for user analytics + "request_source": "mobile_app" + } + ) +) +``` + +يمكن استخدام هذه البيانات الوصفية لتصفية السجلات والتتبعات والمقاييس في لوحة تحكم Portkey، مما يتيح لك تحليل عمليات تشغيل طاقم أو مستخدمين أو بيئات محددة. + + + +### 2. الموثوقية - حافظ على تشغيل طواقمك بسلاسة + +عند تشغيل الطواقم في الإنتاج، قد تحدث مشكلات - حدود معدل API أو مشكلات الشبكة أو انقطاعات المزود. تضمن ميزات الموثوقية في Portkey استمرار عمل وكلائك بسلاسة حتى عند حدوث مشكلات. + +من السهل تفعيل الاحتياط في إعداد CrewAI الخاص بك باستخدام تكوين Portkey: + +```python +from crewai import LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Create LLM with fallback configuration +portkey_llm = LLM( + model="gpt-4o", + max_tokens=1000, + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + config={ + "strategy": { + "mode": "fallback" + }, + "targets": [ + { + "provider": "openai", + "api_key": "YOUR_OPENAI_API_KEY", + "override_params": {"model": "gpt-4o"} + }, + { + "provider": "anthropic", + "api_key": "YOUR_ANTHROPIC_API_KEY", + "override_params": {"model": "claude-3-opus-20240229"} + } + ] + } + ) +) + +# Use this LLM configuration with your agents +``` + +سيحاول هذا التكوين تلقائياً استخدام Claude إذا فشل طلب GPT-4o، مما يضمن استمرار تشغيل طاقمك. + + + + يتعامل مع حالات الفشل المؤقتة تلقائياً. إذا فشل استدعاء LLM، سيعيد Portkey محاولة نفس الطلب لعدد محدد من المرات - مثالي لحدود المعدل أو انقطاعات الشبكة. + + + امنع وكلاءك من التعليق. عيّن مهلات لضمان حصولك على استجابات (أو الفشل بأمان) ضمن الأطر الزمنية المطلوبة. + + + أرسل طلبات مختلفة إلى مزودين مختلفين. وجّه التفكير المعقد إلى GPT-4 والمهام الإبداعية إلى Claude والاستجابات السريعة إلى Gemini بناءً على احتياجاتك. + + + استمر في العمل حتى لو فشل مزودك الأساسي. انتقل تلقائياً إلى مزودين احتياطيين للحفاظ على التوفر. + + + وزّع الطلبات عبر مفاتيح API أو مزودين متعددين. ممتاز لعمليات الطاقم عالية الحجم والبقاء ضمن حدود المعدل. + + + +### 3. إدارة الموجهات في CrewAI + +يساعدك استوديو هندسة الموجهات من Portkey في إنشاء وإدارة وتحسين الموجهات المستخدمة في وكلاء CrewAI. بدلاً من ترميز الموجهات أو التعليمات بشكل ثابت، استخدم API عرض الموجهات من Portkey لجلب وتطبيق موجهاتك المُصدَرة ديناميكياً. + + +![Prompt Playground Interface](https://raw.githubusercontent.com/siddharthsambharia-portkey/Portkey-Product-Images/refs/heads/main/CrewAI%20Portkey%20Docs.webp) + + + + +ساحة تجربة الموجهات هي مكان لمقارنة واختبار ونشر الموجهات المثالية لتطبيق الذكاء الاصطناعي الخاص بك. هي المكان الذي تجرّب فيه نماذج مختلفة وتختبر المتغيرات وتقارن المخرجات وتحسّن استراتيجية هندسة الموجهات قبل النشر في الإنتاج. تتيح لك: + +1. تطوير الموجهات بشكل تكراري قبل استخدامها في وكلائك +2. اختبار الموجهات مع متغيرات ونماذج مختلفة +3. مقارنة المخرجات بين إصدارات موجهات مختلفة +4. التعاون مع أعضاء الفريق في تطوير الموجهات + +تجعل هذه البيئة المرئية من الأسهل صياغة موجهات فعالة لكل خطوة في سير عمل وكلاء CrewAI. + + + +يسترجع API عرض الموجهات قوالب الموجهات الخاصة بك مع جميع المعاملات المُعدّة: + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL, Portkey + +# Initialize Portkey admin client +portkey_admin = Portkey(api_key="YOUR_PORTKEY_API_KEY") + +# Retrieve prompt using the render API +prompt_data = portkey_client.prompts.render( + prompt_id="YOUR_PROMPT_ID", + variables={ + "agent_role": "Senior Research Scientist", + } +) + +backstory_agent_prompt=prompt_data.data.messages[0]["content"] + + +# Set up LLM with Portkey integration +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY" + ) +) + +# Create agent using the rendered prompt +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory=backstory_agent, # Use the rendered prompt + verbose=True, + llm=portkey_llm +) +``` + + + +يمكنك: +- إنشاء إصدارات متعددة من نفس الموجه +- مقارنة الأداء بين الإصدارات +- الرجوع إلى إصدارات سابقة عند الحاجة +- تحديد الإصدار المراد استخدامه في كودك: + +```python +# Use a specific prompt version +prompt_data = portkey_admin.prompts.render( + prompt_id="YOUR_PROMPT_ID@version_number", + variables={ + "agent_role": "Senior Research Scientist", + "agent_goal": "Discover groundbreaking insights" + } +) +``` + + + +تستخدم موجهات Portkey قوالب بنمط Mustache لاستبدال المتغيرات بسهولة: + +``` +You are a {{agent_role}} with expertise in {{domain}}. + +Your mission is to {{agent_goal}} by leveraging your knowledge +and experience in the field. + +Always maintain a {{tone}} tone and focus on providing {{focus_area}}. +``` + +عند العرض، ما عليك سوى تمرير المتغيرات: + +```python +prompt_data = portkey_admin.prompts.render( + prompt_id="YOUR_PROMPT_ID", + variables={ + "agent_role": "Senior Research Scientist", + "domain": "artificial intelligence", + "agent_goal": "discover groundbreaking insights", + "tone": "professional", + "focus_area": "practical applications" + } +) +``` + + + + + تعرّف على المزيد حول ميزات إدارة الموجهات في Portkey + + +### 4. حواجز الحماية لطواقم آمنة + +تضمن حواجز الحماية أن وكلاء CrewAI يعملون بأمان ويستجيبون بشكل مناسب في جميع الحالات. + +**لماذا تستخدم حواجز الحماية؟** + +قد يواجه وكلاء CrewAI أوضاع فشل مختلفة: +- توليد محتوى ضار أو غير مناسب +- تسريب معلومات حساسة مثل المعلومات الشخصية +- توهم معلومات غير صحيحة +- توليد مخرجات بتنسيقات غير صحيحة + +تضيف حواجز حماية Portkey حماية لكل من المدخلات والمخرجات. + +**تطبيق حواجز الحماية** + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Create LLM with guardrails +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "input_guardrails": ["guardrails-id-xxx", "guardrails-id-yyy"], + "output_guardrails": ["guardrails-id-zzz"] + } + ) +) + +# Create agent with guardrailed LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +يمكن لحواجز حماية Portkey: +- كشف وحذف المعلومات الشخصية في المدخلات والمخرجات +- تصفية المحتوى الضار أو غير المناسب +- التحقق من تنسيقات الاستجابة وفقاً للمخططات +- التحقق من التوهمات مقابل الحقائق المرجعية +- تطبيق منطق الأعمال والقواعد المخصصة + + + استكشف ميزات حواجز الحماية في Portkey لتعزيز سلامة الوكلاء + + +### 5. تتبع المستخدمين باستخدام البيانات الوصفية + +تتبع المستخدمين الفرديين عبر وكلاء CrewAI باستخدام نظام البيانات الوصفية في Portkey. + +**ما هي البيانات الوصفية في Portkey؟** + +تتيح لك البيانات الوصفية ربط بيانات مخصصة بكل طلب، مما يمكّن التصفية والتقسيم والتحليلات. الحقل الخاص `_user` مصمم خصيصاً لتتبع المستخدمين. + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLM with user tracking +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + metadata={ + "_user": "user_123", # Special _user field for user analytics + "user_tier": "premium", + "user_company": "Acme Corp", + "session_id": "abc-123" + } + ) +) + +# Create agent with tracked LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +**تصفية التحليلات حسب المستخدم** + +مع وجود البيانات الوصفية، يمكنك تصفية التحليلات حسب المستخدم وتحليل مقاييس الأداء على أساس كل مستخدم: + + + + + +يمكّن هذا: +- تتبع التكاليف والميزانية لكل مستخدم +- تحليلات مستخدم مخصصة +- مقاييس على مستوى الفريق أو المؤسسة +- مراقبة خاصة بالبيئة (التجريب مقابل الإنتاج) + + + استكشف كيفية استخدام البيانات الوصفية المخصصة لتعزيز تحليلاتك + + +### 6. التخزين المؤقت لطواقم فعالة + +طبّق التخزين المؤقت لجعل وكلاء CrewAI أكثر كفاءة وفعالية من حيث التكلفة: + + + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLM with simple caching +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "cache": { + "mode": "simple" + } + } + ) +) + +# Create agent with cached LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +يقوم التخزين المؤقت البسيط بمطابقة دقيقة لموجهات الإدخال، مع تخزين الطلبات المتطابقة لتجنب عمليات تنفيذ النموذج الزائدة. + + + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLM with semantic caching +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "cache": { + "mode": "semantic" + } + } + ) +) + +# Create agent with semantically cached LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +يأخذ التخزين المؤقت الدلالي في الاعتبار التشابه السياقي بين طلبات الإدخال، مع تخزين الاستجابات للمدخلات المتشابهة دلالياً. + + + +### 7. التوافق بين النماذج + +يدعم CrewAI مزودي LLM متعددين، ويوسّع Portkey هذه القدرة من خلال توفير الوصول إلى أكثر من 200 نموذج LLM عبر واجهة موحدة. يمكنك التبديل بسهولة بين نماذج مختلفة دون تغيير منطق الوكيل الأساسي: + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Set up LLMs with different providers +openai_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY" + ) +) + +anthropic_llm = LLM( + model="claude-3-5-sonnet-latest", + max_tokens=1000, + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_ANTHROPIC_VIRTUAL_KEY" + ) +) + +# Choose which LLM to use for each agent based on your needs +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=openai_llm # Use anthropic_llm for Anthropic +) +``` + +يوفر Portkey الوصول إلى نماذج LLM من مزودين بما في ذلك: + +- OpenAI (GPT-4o، GPT-4 Turbo، إلخ) +- Anthropic (Claude 3.5 Sonnet، Claude 3 Opus، إلخ) +- Mistral AI (Mistral Large، Mistral Medium، إلخ) +- Google Vertex AI (Gemini 1.5 Pro، إلخ) +- Cohere (Command، Command-R، إلخ) +- AWS Bedrock (Claude، Titan، إلخ) +- النماذج المحلية/الخاصة + + + اطلع على القائمة الكاملة لمزودي LLM المدعومين من Portkey + + +## إعداد حوكمة المؤسسة لـ CrewAI + +**لماذا حوكمة المؤسسة؟** +إذا كنت تستخدم CrewAI داخل مؤسستك، فأنت بحاجة إلى مراعاة عدة جوانب حوكمة: +- **إدارة التكاليف**: التحكم في إنفاق الذكاء الاصطناعي وتتبعه عبر الفرق +- **التحكم في الوصول**: إدارة الفرق التي يمكنها استخدام نماذج محددة +- **تحليلات الاستخدام**: فهم كيفية استخدام الذكاء الاصطناعي عبر المؤسسة +- **الأمان والامتثال**: الحفاظ على معايير أمان المؤسسة +- **الموثوقية**: ضمان خدمة متسقة لجميع المستخدمين + +يضيف Portkey طبقة حوكمة شاملة لتلبية احتياجات المؤسسة هذه. لننفّذ هذه الضوابط خطوة بخطوة. + + + +المفاتيح الافتراضية هي طريقة Portkey الآمنة لإدارة مفاتيح API لمزودي LLM. توفر ضوابط أساسية مثل: +- حدود الميزانية لاستخدام API +- إمكانيات تحديد المعدل +- تخزين آمن لمفاتيح API + +لإنشاء مفتاح افتراضي: +انتقل إلى [المفاتيح الافتراضية](https://app.portkey.ai/virtual-keys) في تطبيق Portkey. احفظ وانسخ معرّف المفتاح الافتراضي + + + + + + +احفظ معرّف المفتاح الافتراضي - ستحتاجه في الخطوة التالية. + + + + +تحدد التكوينات في Portkey كيفية توجيه طلباتك، مع ميزات مثل التوجيه المتقدم والاحتياط وإعادة المحاولة. + +لإنشاء تكوينك: +1. انتقل إلى [التكوينات](https://app.portkey.ai/configs) في لوحة تحكم Portkey +2. أنشئ تكويناً جديداً بـ: + ```json + { + "virtual_key": "YOUR_VIRTUAL_KEY_FROM_STEP1", + "override_params": { + "model": "gpt-4o" // Your preferred model name + } + } + ``` +3. احفظ ولاحظ اسم التكوين للخطوة التالية + + + + + + + + +الآن أنشئ مفتاح API لـ Portkey وأرفق التكوين الذي أنشأته في الخطوة 2: + +1. انتقل إلى [مفاتيح API](https://app.portkey.ai/api-keys) في Portkey وأنشئ مفتاح API جديد +2. حدد تكوينك من `الخطوة 2` +3. أنشئ واحفظ مفتاح API الخاص بك + + + + + + + + +بعد إعداد مفتاح API لـ Portkey مع التكوين المرفق، اربطه بوكلاء CrewAI: + +```python +from crewai import Agent, LLM +from portkey_ai import PORTKEY_GATEWAY_URL + +# Configure LLM with your API key +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="YOUR_PORTKEY_API_KEY" +) + +# Create agent with Portkey-enabled LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + + + + + +### الخطوة 1: تطبيق ضوابط الميزانية وحدود المعدل + +تمكّن المفاتيح الافتراضية التحكم الدقيق في الوصول إلى LLM على مستوى الفريق/القسم. يساعدك هذا على: +- إعداد [حدود الميزانية](https://portkey.ai/docs/product/ai-gateway/virtual-keys/budget-limits) +- منع الارتفاعات غير المتوقعة في الاستخدام باستخدام حدود المعدل +- تتبع إنفاق الأقسام + +#### إعداد ضوابط خاصة بالقسم: +1. انتقل إلى [المفاتيح الافتراضية](https://app.portkey.ai/virtual-keys) في لوحة تحكم Portkey +2. أنشئ مفتاحاً افتراضياً جديداً لكل قسم مع حدود ميزانية ومعدل +3. هيئ الحدود الخاصة بكل قسم + + + + + + + +### الخطوة 2: تحديد قواعد الوصول للنماذج + +مع توسع استخدام الذكاء الاصطناعي، يصبح التحكم في الفرق التي يمكنها الوصول إلى نماذج محددة أمراً بالغ الأهمية. توفر تكوينات Portkey طبقة التحكم هذه مع ميزات مثل: + +#### ميزات التحكم في الوصول: +- **قيود النماذج**: تقييد الوصول إلى نماذج محددة +- **حماية البيانات**: تطبيق حواجز حماية للبيانات الحساسة +- **ضوابط الموثوقية**: إضافة احتياط ومنطق إعادة المحاولة + +#### مثال على التكوين: +إليك تكويناً أساسياً لتوجيه الطلبات إلى OpenAI، تحديداً باستخدام GPT-4o: + +```json +{ + "strategy": { + "mode": "single" + }, + "targets": [ + { + "virtual_key": "YOUR_OPENAI_VIRTUAL_KEY", + "override_params": { + "model": "gpt-4o" + } + } + ] +} +``` + + أنشئ تكوينك في [صفحة التكوينات](https://app.portkey.ai/configs) في لوحة تحكم Portkey. + + + يمكن تحديث التكوينات في أي وقت لضبط الضوابط دون التأثير على التطبيقات قيد التشغيل. + + + + + ### الخطوة 3: تطبيق ضوابط الوصول + + أنشئ مفاتيح API خاصة بالمستخدم تقوم تلقائياً بـ: + - تتبع الاستخدام لكل مستخدم/فريق بمساعدة المفاتيح الافتراضية + - تطبيق التكوينات المناسبة لتوجيه الطلبات + - جمع البيانات الوصفية ذات الصلة لتصفية السجلات + - فرض أذونات الوصول + + أنشئ مفاتيح API من خلال [تطبيق Portkey](https://app.portkey.ai/) + + مثال باستخدام Python SDK: + ```python + from portkey_ai import Portkey + + portkey = Portkey(api_key="YOUR_ADMIN_API_KEY") + + api_key = portkey.api_keys.create( + name="engineering-team", + type="organisation", + workspace_id="YOUR_WORKSPACE_ID", + defaults={ + "config_id": "your-config-id", + "metadata": { + "environment": "production", + "department": "engineering" + } + }, + scopes=["logs.view", "configs.read"] + ) + ``` + + للحصول على تعليمات تفصيلية لإدارة المفاتيح، راجع [وثائق Portkey](https://portkey.ai/docs). + + + + ### الخطوة 4: النشر والمراقبة + بعد توزيع مفاتيح API على أعضاء فريقك، يصبح إعداد CrewAI الجاهز للمؤسسة جاهزاً للعمل. يمكن لكل عضو في الفريق الآن استخدام مفاتيح API المخصصة له مع مستويات وصول وضوابط ميزانية مناسبة. + + راقب الاستخدام في لوحة تحكم Portkey: + - تتبع التكاليف حسب القسم + - أنماط استخدام النماذج + - حجم الطلبات + - معدلات الأخطاء + + + + + +### ميزات المؤسسة متاحة الآن +**تكامل CrewAI الخاص بك يتضمن الآن:** +- ضوابط ميزانية للأقسام +- حوكمة الوصول للنماذج +- تتبع الاستخدام والإسناد +- حواجز أمان +- ميزات الموثوقية + + +## الأسئلة الشائعة + + + + يضيف Portkey جاهزية الإنتاج لـ CrewAI من خلال مراقبة شاملة (تتبعات وسجلات ومقاييس) وميزات موثوقية (احتياط وإعادة محاولة وتخزين مؤقت) والوصول إلى أكثر من 200 نموذج LLM عبر واجهة موحدة. هذا يسهّل تصحيح الأخطاء وتحسين وتوسيع تطبيقات الوكلاء. + + + + نعم! يتكامل Portkey بسلاسة مع تطبيقات CrewAI الحالية. ما عليك سوى تحديث كود تكوين LLM بالنسخة المُمكّنة من Portkey. يبقى باقي كود الوكيل والطاقم دون تغيير. + + + + يدعم Portkey جميع ميزات CrewAI، بما في ذلك الوكلاء والأدوات وسير العمل مع تدخل بشري وجميع أنواع عمليات المهام (تسلسلي وهرمي وغيرها). يضيف المراقبة والموثوقية دون تقييد أي من وظائف الإطار. + + + + نعم، يتيح لك Portkey استخدام `trace_id` متسق عبر وكلاء متعددين في طاقم لتتبع سير العمل بالكامل. هذا مفيد بشكل خاص للطواقم المعقدة حيث تريد فهم مسار التنفيذ الكامل عبر وكلاء متعددين. + + + + يتيح لك Portkey إضافة بيانات وصفية مخصصة لتكوين LLM، والتي يمكنك استخدامها للتصفية. أضف حقولاً مثل `crew_name` أو `crew_type` أو `session_id` للعثور على عمليات تنفيذ طاقم محددة وتحليلها بسهولة. + + + + نعم! يستخدم Portkey مفاتيح API الخاصة بك لمزودي LLM المختلفين. يخزنها بشكل آمن كمفاتيح افتراضية، مما يتيح لك إدارة وتدوير المفاتيح بسهولة دون تغيير كودك. + + + + +## الموارد + + + +

وثائق CrewAI الرسمية

+
+ +

احصل على إرشادات مخصصة لتنفيذ هذا التكامل

+
+
diff --git a/docs/v1.15.13/ar/observability/tracing.mdx b/docs/v1.15.13/ar/observability/tracing.mdx new file mode 100644 index 0000000000..234a62fcd0 --- /dev/null +++ b/docs/v1.15.13/ar/observability/tracing.mdx @@ -0,0 +1,214 @@ +--- +title: تتبع CrewAI +description: التتبع المدمج لطواقم وتدفقات CrewAI مع منصة CrewAI AMP +icon: magnifying-glass-chart +mode: "wide" +--- + +# التتبع المدمج في CrewAI + +يوفر CrewAI إمكانيات تتبع مدمجة تتيح لك مراقبة وتصحيح أخطاء الطواقم والتدفقات في الوقت الفعلي. يوضح هذا الدليل كيفية تفعيل التتبع لكل من **الطواقم** و**التدفقات** باستخدام منصة المراقبة المتكاملة في CrewAI. + +> **ما هو تتبع CrewAI؟** يوفر التتبع المدمج في CrewAI مراقبة شاملة لوكلاء الذكاء الاصطناعي، بما في ذلك قرارات الوكلاء وجداول تنفيذ المهام واستخدام الأدوات واستدعاءات LLM - كل ذلك متاح عبر [منصة CrewAI AMP](https://app.crewai.com). + +![واجهة تتبع CrewAI](/images/crewai-tracing.png) + +## المتطلبات الأساسية + +قبل أن تتمكن من استخدام تتبع CrewAI، تحتاج إلى: + +1. **حساب CrewAI AMP**: سجّل للحصول على حساب مجاني على [app.crewai.com](https://app.crewai.com) +2. **مصادقة CLI**: استخدم CLI الخاص بـ CrewAI لمصادقة بيئتك المحلية + +```bash +crewai login +``` + +## تعليمات الإعداد + +### الخطوة 1: إنشاء حساب CrewAI AMP + +قم بزيارة [app.crewai.com](https://app.crewai.com) وأنشئ حسابك المجاني. سيمنحك هذا الوصول إلى منصة CrewAI AMP حيث يمكنك عرض التتبعات والمقاييس وإدارة طواقمك. + +### الخطوة 2: تثبيت CLI الخاص بـ CrewAI والمصادقة + +إذا لم تكن قد فعلت ذلك بالفعل، ثبّت CrewAI مع أدوات CLI: + +```bash +uv add 'crewai[tools]' +``` + +ثم صادق على CLI مع حساب CrewAI AMP الخاص بك: + +```bash +crewai login +``` + +سيقوم هذا الأمر بـ: + +1. فتح متصفحك إلى صفحة المصادقة +2. طلب إدخال رمز الجهاز +3. مصادقة بيئتك المحلية مع حساب CrewAI AMP +4. تفعيل إمكانيات التتبع لتطويرك المحلي + +### الخطوة 3: تفعيل التتبع في طاقمك + +يمكنك تفعيل التتبع لطاقمك عبر تعيين معامل `tracing` إلى `True`: + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool + +# Define your agents +researcher = Agent( + role="Senior Research Analyst", + goal="Uncover cutting-edge developments in AI and data science", + backstory="""You work at a leading tech think tank. + Your expertise lies in identifying emerging trends. + You have a knack for dissecting complex data and presenting actionable insights.""", + verbose=True, + tools=[SerperDevTool()], +) + +writer = Agent( + role="Tech Content Strategist", + goal="Craft compelling content on tech advancements", + backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles. + You transform complex concepts into compelling narratives.""", + verbose=True, +) + +# Create tasks for your agents +research_task = Task( + description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024. + Identify key trends, breakthrough technologies, and potential industry impacts.""", + expected_output="Full analysis report in bullet points", + agent=researcher, +) + +writing_task = Task( + description="""Using the insights provided, develop an engaging blog + post that highlights the most significant AI advancements. + Your post should be informative yet accessible, catering to a tech-savvy audience.""", + expected_output="Full blog post of at least 4 paragraphs", + agent=writer, +) + +# Enable tracing in your crew +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + tracing=True, # Enable built-in tracing + verbose=True +) + +# Execute your crew +result = crew.kickoff() +``` + +### الخطوة 4: تفعيل التتبع في التدفق + +بالمثل، يمكنك تفعيل التتبع لتدفقات CrewAI: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + counter: int = 0 + message: str = "" + +class ExampleFlow(Flow[ExampleState]): + def __init__(self): + super().__init__(tracing=True) # Enable tracing for the flow + + @start() + def first_method(self): + print("Starting the flow") + self.state.counter = 1 + self.state.message = "Flow started" + return "continue" + + @listen("continue") + def second_method(self): + print("Continuing the flow") + self.state.counter += 1 + self.state.message = "Flow continued" + return "finish" + + @listen("finish") + def final_method(self): + print("Finishing the flow") + self.state.counter += 1 + self.state.message = "Flow completed" + +# Create and run the flow with tracing enabled +flow = ExampleFlow(tracing=True) +result = flow.kickoff() +``` + +### الخطوة 5: عرض التتبعات في لوحة تحكم CrewAI AMP + +بعد تشغيل الطاقم أو التدفق، يمكنك عرض التتبعات التي أنشأها تطبيق CrewAI في لوحة تحكم CrewAI AMP. يجب أن ترى خطوات تفصيلية لتفاعلات الوكلاء واستخدامات الأدوات واستدعاءات LLM. +ما عليك سوى النقر على الرابط أدناه لعرض التتبعات أو التوجه إلى علامة تبويب التتبعات في لوحة التحكم [هنا](https://app.crewai.com/crewai_plus/trace_batches) +![واجهة تتبع CrewAI](/images/view-traces.png) + +### البديل: إعداد متغير البيئة + +يمكنك أيضاً تفعيل التتبع عالمياً عبر تعيين متغير بيئة: + +```bash +export CREWAI_TRACING_ENABLED=true +``` + +أو إضافته إلى ملف `.env`: + +```env +CREWAI_TRACING_ENABLED=true +``` + +عند تعيين متغير البيئة هذا، ستُفعّل جميع الطواقم والتدفقات التتبع تلقائياً، حتى بدون تعيين `tracing=True` صراحةً. + +## عرض التتبعات + +### الوصول إلى لوحة تحكم CrewAI AMP + +1. قم بزيارة [app.crewai.com](https://app.crewai.com) وسجّل الدخول إلى حسابك +2. انتقل إلى لوحة تحكم مشروعك +3. انقر على علامة تبويب **التتبعات** لعرض تفاصيل التنفيذ + +### ما ستراه في التتبعات + +يوفر تتبع CrewAI رؤية شاملة لـ: + +- **قرارات الوكلاء**: شاهد كيف يفكر الوكلاء في المهام ويتخذون القرارات +- **جدول تنفيذ المهام**: تمثيل مرئي لتسلسلات المهام والتبعيات +- **استخدام الأدوات**: مراقبة الأدوات المستدعاة ونتائجها +- **استدعاءات LLM**: تتبع جميع تفاعلات نماذج اللغة، بما في ذلك الموجهات والاستجابات +- **مقاييس الأداء**: أوقات التنفيذ واستخدام الرموز المميزة والتكاليف +- **تتبع الأخطاء**: معلومات تفصيلية عن الأخطاء وتتبعات المكدس + +### ميزات التتبع + +- **جدول التنفيذ**: انقر عبر مراحل التنفيذ المختلفة +- **سجلات تفصيلية**: الوصول إلى سجلات شاملة لتصحيح الأخطاء +- **تحليلات الأداء**: حلّل أنماط التنفيذ وحسّن الأداء +- **إمكانيات التصدير**: حمّل التتبعات لمزيد من التحليل + +### مشكلات المصادقة + +إذا واجهت مشاكل في المصادقة: + +1. تأكد من تسجيل الدخول: `crewai login` +2. تحقق من اتصال الإنترنت +3. تحقق من حسابك على [app.crewai.com](https://app.crewai.com) + +### التتبعات لا تظهر + +إذا لم تظهر التتبعات في لوحة التحكم: + +1. تأكد من تعيين `tracing=True` في الطاقم/التدفق +2. تحقق من `CREWAI_TRACING_ENABLED=true` إذا كنت تستخدم متغيرات البيئة +3. تأكد من المصادقة عبر `crewai login` +4. تحقق من أن الطاقم/التدفق قيد التنفيذ فعلاً diff --git a/docs/v1.15.13/ar/observability/truefoundry.mdx b/docs/v1.15.13/ar/observability/truefoundry.mdx new file mode 100644 index 0000000000..9260f43fcb --- /dev/null +++ b/docs/v1.15.13/ar/observability/truefoundry.mdx @@ -0,0 +1,146 @@ +--- +title: تكامل TrueFoundry +icon: chart-line +mode: "wide" +--- + +توفر TrueFoundry [بوابة ذكاء اصطناعي](https://www.truefoundry.com/ai-gateway) جاهزة للمؤسسات يمكنها التكامل مع أطر العمل الوكيلية مثل CrewAI وتوفير الحوكمة والمراقبة لتطبيقات الذكاء الاصطناعي. تعمل بوابة TrueFoundry AI كواجهة موحدة للوصول إلى LLM، وتوفر: + +- **وصول موحد لـ API**: الاتصال بأكثر من 250 نموذج LLM (OpenAI وClaude وGemini وGroq وMistral) عبر API واحد +- **زمن استجابة منخفض**: زمن استجابة داخلي أقل من 3 مللي ثانية مع توجيه ذكي وموازنة أحمال +- **أمان المؤسسة**: امتثال SOC 2 وHIPAA وGDPR مع RBAC وتسجيل المراجعة +- **إدارة الحصص والتكاليف**: حصص قائمة على الرموز المميزة وتحديد المعدل وتتبع استخدام شامل +- **المراقبة**: تسجيل كامل للطلبات/الاستجابات ومقاييس وتتبعات مع احتفاظ قابل للتخصيص + +## كيف يتكامل TrueFoundry مع CrewAI + + +### التثبيت والإعداد + + + +```bash +pip install crewai +``` + + + +1. سجّل في [حساب TrueFoundry](https://www.truefoundry.com/register) +2. اتبع الخطوات هنا في [البدء السريع](https://docs.truefoundry.com/gateway/quick-start) + + + +![إعداد كود TrueFoundry](/images/new-code-snippet.png) + +```python +from crewai import LLM + +# Create an LLM instance with TrueFoundry AI Gateway +truefoundry_llm = LLM( + model="openai-main/gpt-4o", # Similarly, you can call any model from any provider + base_url="your_truefoundry_gateway_base_url", + api_key="your_truefoundry_api_key" +) + +# Use in your CrewAI agents +from crewai import Agent + +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + llm=truefoundry_llm, + verbose=True + ) +``` + + + +### مثال كامل على CrewAI + +```python +from crewai import Agent, Task, Crew, LLM + +# Configure LLM with TrueFoundry +llm = LLM( + model="openai-main/gpt-4o", + base_url="your_truefoundry_gateway_base_url", + api_key="your_truefoundry_api_key" +) + +# Create agents +researcher = Agent( + role='Research Analyst', + goal='Conduct detailed market research', + backstory='Expert market analyst with attention to detail', + llm=llm, + verbose=True +) + +writer = Agent( + role='Content Writer', + goal='Create comprehensive reports', + backstory='Experienced technical writer', + llm=llm, + verbose=True +) + +# Create tasks +research_task = Task( + description='Research AI market trends for 2024', + agent=researcher, + expected_output='Comprehensive research summary' +) + +writing_task = Task( + description='Create a market research report', + agent=writer, + expected_output='Well-structured report with insights', + context=[research_task] +) + +# Create and execute crew +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True +) + +result = crew.kickoff() +``` + +### المراقبة والحوكمة + +راقب وكلاء CrewAI من خلال علامة تبويب المقاييس في TrueFoundry: +![مقاييس TrueFoundry](/images/gateway-metrics.png) + +مع بوابة الذكاء الاصطناعي من TrueFoundry، يمكنك مراقبة وتحليل: + +- **مقاييس الأداء**: تتبع مقاييس زمن الاستجابة الرئيسية مثل زمن استجابة الطلب ووقت أول رمز (TTFS) وزمن الاستجابة بين الرموز (ITL) بنسب مئوية P99 وP90 وP50 +- **التكلفة واستخدام الرموز المميزة**: احصل على رؤية لتكاليف تطبيقك مع تفاصيل دقيقة لرموز الإدخال/الإخراج والنفقات المرتبطة لكل نموذج +- **أنماط الاستخدام**: افهم كيف يُستخدم تطبيقك مع تحليلات تفصيلية لنشاط المستخدم وتوزيع النماذج والاستخدام حسب الفريق +- **تحديد المعدل وموازنة الأحمال**: يمكنك إعداد تحديد المعدل وموازنة الأحمال والاحتياط لنماذجك + +## التتبع + +لفهم أعمق حول التتبع، يرجى مراجعة [البدء بالتتبع](https://docs.truefoundry.com/docs/tracing/tracing-getting-started). للتتبع، يمكنك إضافة Traceloop SDK: + +```bash +pip install traceloop-sdk +``` + +```python +from traceloop.sdk import Traceloop + +# Initialize enhanced tracing +Traceloop.init( + api_endpoint="https://your-truefoundry-endpoint/api/tracing", + headers={ + "Authorization": f"Bearer {your_truefoundry_pat_token}", + "TFY-Tracing-Project": "your_project_name", + }, +) +``` + +يوفر هذا ارتباط تتبع إضافي عبر سير عمل CrewAI بالكامل. +![تتبع CrewAI مع TrueFoundry](/images/tracing_crewai.png) diff --git a/docs/v1.15.13/ar/observability/weave.mdx b/docs/v1.15.13/ar/observability/weave.mdx new file mode 100644 index 0000000000..c2ded9a867 --- /dev/null +++ b/docs/v1.15.13/ar/observability/weave.mdx @@ -0,0 +1,125 @@ +--- +title: تكامل Weave +description: تعرّف على كيفية استخدام Weights & Biases (W&B) Weave لتتبع وتجربة وتقييم وتحسين تطبيقات CrewAI. +icon: radar +mode: "wide" +--- + +# نظرة عامة على Weave + +[Weights & Biases (W&B) Weave](https://weave-docs.wandb.ai/) هو إطار عمل لتتبع وتجربة وتقييم ونشر وتحسين التطبيقات المبنية على نماذج اللغة الكبيرة. + +![نظرة عامة على استخدام تتبع W&B Weave مع CrewAI](/images/weave-tracing.gif) + +يوفر Weave دعماً شاملاً لكل مرحلة من مراحل تطوير تطبيق CrewAI: + +- **التتبع والمراقبة**: تتبع تلقائي لاستدعاءات LLM ومنطق التطبيق لتصحيح الأخطاء وتحليل أنظمة الإنتاج +- **التكرار المنهجي**: تحسين والتكرار على الموجهات ومجموعات البيانات والنماذج +- **التقييم**: استخدام مقيّمين مخصصين أو مُعدّين مسبقاً لتقييم أداء الوكلاء وتحسينه بشكل منهجي +- **حواجز الحماية**: حماية وكلائك بحماية مسبقة ولاحقة للإشراف على المحتوى وسلامة الموجهات + +يلتقط Weave التتبعات تلقائياً لتطبيقات CrewAI، مما يمكّنك من مراقبة وتحليل أداء وكلائك وتفاعلاتهم وتدفق التنفيذ. يساعدك هذا في بناء مجموعات بيانات تقييم أفضل وتحسين سير عمل وكلائك. + +## تعليمات الإعداد + + + + ```shell + pip install crewai weave + ``` + + + سجّل في [حساب Weights & Biases](https://wandb.ai) إذا لم تكن قد فعلت ذلك بالفعل. ستحتاج إليه لعرض التتبعات والمقاييس. + + + أضف الكود التالي إلى تطبيقك: + + ```python + import weave + + # Initialize Weave with your project name + weave.init(project_name="crewai_demo") + ``` + + بعد التهيئة، سيوفر Weave عنوان URL حيث يمكنك عرض التتبعات والمقاييس. + + + ```python + from crewai import Agent, Task, Crew, LLM, Process + + # Create an LLM with a temperature of 0 to ensure deterministic outputs + llm = LLM(model="gpt-4o", temperature=0) + + # Create agents + researcher = Agent( + role='Research Analyst', + goal='Find and analyze the best investment opportunities', + backstory='Expert in financial analysis and market research', + llm=llm, + verbose=True, + allow_delegation=False, + ) + + writer = Agent( + role='Report Writer', + goal='Write clear and concise investment reports', + backstory='Experienced in creating detailed financial reports', + llm=llm, + verbose=True, + allow_delegation=False, + ) + + # Create tasks + research_task = Task( + description='Deep research on the {topic}', + expected_output='Comprehensive market data including key players, market size, and growth trends.', + agent=researcher + ) + + writing_task = Task( + description='Write a detailed report based on the research', + expected_output='The report should be easy to read and understand. Use bullet points where applicable.', + agent=writer + ) + + # Create a crew + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True, + process=Process.sequential, + ) + + # Run the crew + result = crew.kickoff(inputs={"topic": "AI in material science"}) + print(result) + ``` + + + بعد تشغيل تطبيق CrewAI، قم بزيارة عنوان URL الذي وفره Weave أثناء التهيئة لعرض: + - استدعاءات LLM وبياناتها الوصفية + - تفاعلات الوكلاء وتدفق تنفيذ المهام + - مقاييس الأداء مثل زمن الاستجابة واستخدام الرموز المميزة + - أي أخطاء أو مشكلات حدثت أثناء التنفيذ + + + Weave tracing example with CrewAI + + + + +## الميزات + +- يلتقط Weave تلقائياً جميع عمليات CrewAI: تفاعلات الوكلاء وتنفيذ المهام؛ استدعاءات LLM مع البيانات الوصفية واستخدام الرموز المميزة؛ استخدام الأدوات ونتائجها. +- يدعم التكامل جميع طرق تنفيذ CrewAI: `kickoff()` و`kickoff_for_each()` و`kickoff_async()` و`kickoff_for_each_async()`. +- تتبع تلقائي لجميع [أدوات crewAI](https://github.com/crewAIInc/crewAI-tools). +- دعم ميزة التدفق مع تصحيح المزخرفات (`@start` و`@listen` و`@router` و`@or_` و`@and_`). +- تتبع حواجز الحماية المخصصة المُمررة لمهام CrewAI `Task` باستخدام `@weave.op()`. + +لمعلومات تفصيلية حول ما هو مدعوم، قم بزيارة [وثائق Weave CrewAI](https://weave-docs.wandb.ai/guides/integrations/crewai/#getting-started-with-flow). + +## الموارد + +- [وثائق Weave](https://weave-docs.wandb.ai) +- [مثال على لوحة معلومات Weave x CrewAI](https://wandb.ai/ayut/crewai_demo/weave/traces?cols=%7B%22wb_run_id%22%3Afalse%2C%22attributes.weave.client_version%22%3Afalse%2C%22attributes.weave.os_name%22%3Afalse%2C%22attributes.weave.os_release%22%3Afalse%2C%22attributes.weave.os_version%22%3Afalse%2C%22attributes.weave.source%22%3Afalse%2C%22attributes.weave.sys_version%22%3Afalse%7D&peekPath=%2Fayut%2Fcrewai_demo%2Fcalls%2F0195c838-38cb-71a2-8a15-651ecddf9d89) +- [X](https://x.com/weave_wb) diff --git a/docs/v1.15.13/ar/quickstart.mdx b/docs/v1.15.13/ar/quickstart.mdx new file mode 100644 index 0000000000..0ac17fb3f6 --- /dev/null +++ b/docs/v1.15.13/ar/quickstart.mdx @@ -0,0 +1,257 @@ +--- +title: البدء السريع +description: ابنِ أول Flow في CrewAI خلال دقائق — التنسيق والحالة وفريقًا بوكيل واحد ينتج تقريرًا فعليًا. +icon: rocket +mode: "wide" +--- + +### شاهد: بناء Agents و Flows في CrewAI باستخدام Coding Agent Skills + +قم بتثبيت مهارات وكيل البرمجة الخاصة بنا (Claude Code، Codex، ...) لتشغيل وكلاء البرمجة بسرعة مع CrewAI. + +يمكنك تثبيتها باستخدام `npx skills add crewaiinc/skills` + + + +في هذا الدليل ستُنشئ **Flow** يحدد موضوع بحث، ويشغّل **طاقمًا بوكيل واحد** (باحث يستخدم البحث على الويب)، وينتهي بتقرير **Markdown** على القرص. يُعد Flow الطريقة الموصى بها لتنظيم التطبيقات الإنتاجية: يمتلك **الحالة** و**ترتيب التنفيذ**، بينما **الوكلاء** ينفّذون العمل داخل خطوة الطاقم. + +إذا لم تُكمل تثبيت CrewAI بعد، اتبع [دليل التثبيت](/ar/installation) أولًا. + +## المتطلبات الأساسية + +- بيئة Python وواجهة سطر أوامر CrewAI (راجع [التثبيت](/ar/installation)) +- نموذج لغوي مهيأ بالمفاتيح الصحيحة — راجع [LLMs](/ar/concepts/llms#setting-up-your-llm) +- مفتاح API من [Serper.dev](https://serper.dev/) (`SERPER_API_KEY`) للبحث على الويب في هذا الدرس + +## ابنِ أول Flow لك + + + + من الطرفية، أنشئ مشروع Flow (اسم المجلد يستخدم شرطة سفلية، مثل `latest_ai_flow`): + + + ```shell Terminal + crewai create flow latest-ai-flow + cd latest_ai_flow + ``` + + + يُنشئ ذلك تطبيق Flow ضمن `src/latest_ai_flow/`، بما في ذلك طاقمًا أوليًا في `crews/content_crew/` ستستبدله بطاقم بحث **بوكيل واحد** في الخطوات التالية. + + + + أنشئ `src/latest_ai_flow/crews/content_crew/agents/researcher.jsonc` (أنشئ مجلد `agents/` إذا لزم). تُملأ المتغيرات مثل `{topic}` من `crew.kickoff(inputs=...)`. + + ```jsonc agents/researcher.jsonc + { + "role": "باحث بيانات أول في {topic}", + "goal": "اكتشاف أحدث التطورات في {topic}", + "backstory": "أنت باحث يجد المعلومات الأكثر صلة ويعرضها بوضوح.", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true + } + } + ``` + + + + + أنشئ `src/latest_ai_flow/crews/content_crew/crew.jsonc`: + + ```jsonc crew.jsonc + { + "name": "Research Crew", + "agents": ["researcher"], + "tasks": [ + { + "name": "research_task", + "description": "أجرِ بحثًا معمقًا عن {topic}. استخدم البحث على الويب للعثور على معلومات حديثة وموثوقة.", + "expected_output": "تقرير بصيغة Markdown بأقسام واضحة: الاتجاهات الرئيسية، أدوات أو شركات بارزة، والآثار. بين 800 و1200 كلمة تقريبًا. دون إحاطة المستند بأكمله بكتل كود.", + "agent": "researcher", + "output_file": "output/report.md", + "markdown": true + } + ], + "process": "sequential", + "verbose": true + } + ``` + + + + + استبدل `content_crew.py` المُولّد بمحمل صغير يحول `crew.jsonc` إلى `Crew`. + + ```python content_crew.py + # src/latest_ai_flow/crews/content_crew/content_crew.py + from pathlib import Path + + from crewai.project import load_crew + + + def kickoff_content_crew(inputs: dict): + crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc")) + return crew.kickoff(inputs={**default_inputs, **inputs}) + ``` + + + + + اربط الطاقم بـ Flow: خطوة `@start()` تضبط الموضوع في **الحالة**، وخطوة `@listen` تشغّل الطاقم. يظل `output_file` للمهمة يكتب `output/report.md`. + + ```python main.py + # src/latest_ai_flow/main.py + from pydantic import BaseModel + + from crewai.flow import Flow, listen, start + + from latest_ai_flow.crews.content_crew.content_crew import kickoff_content_crew + + + class ResearchFlowState(BaseModel): + topic: str = "" + report: str = "" + + + class LatestAiFlow(Flow[ResearchFlowState]): + @start() + def prepare_topic(self, crewai_trigger_payload: dict | None = None): + if crewai_trigger_payload: + self.state.topic = crewai_trigger_payload.get("topic", "AI Agents") + else: + self.state.topic = "AI Agents" + print(f"الموضوع: {self.state.topic}") + + @listen(prepare_topic) + def run_research(self): + result = kickoff_content_crew(inputs={"topic": self.state.topic}) + self.state.report = result.raw + print("اكتمل طاقم البحث.") + + @listen(run_research) + def summarize(self): + print("مسار التقرير: output/report.md") + + + def kickoff(): + LatestAiFlow().kickoff() + + + def plot(): + LatestAiFlow().plot() + + + if __name__ == "__main__": + kickoff() + ``` + + + إذا كان اسم الحزمة ليس `latest_ai_flow`، عدّل استيراد `kickoff_content_crew` ليطابق مسار الوحدة في مشروعك. + + + + + في جذر المشروع، ضبط `.env`: + + - `SERPER_API_KEY` — من [Serper.dev](https://serper.dev/) + - مفاتيح مزوّد النموذج حسب الحاجة — راجع [إعداد LLM](/ar/concepts/llms#setting-up-your-llm) + + + + + ```shell Terminal + crewai install + crewai run + ``` + + + يُنفّذ `crewai run` نقطة دخول Flow المعرّفة في المشروع (نفس أمر الطواقم؛ نوع المشروع `"flow"` في `pyproject.toml`). + + + + يجب أن ترى سجلات من Flow والطاقم. افتح **`output/report.md`** للتقرير المُولَّد (مقتطف): + + + ```markdown output/report.md + # وكلاء الذكاء الاصطناعي: المشهد والاتجاهات الحديثة + + ## ملخص تنفيذي + … + + ## أبرز الاتجاهات + - **استخدام الأدوات والتنسيق** — … + - **التبني المؤسسي** — … + + ## الآثار + … + ``` + + + سيكون الملف الفعلي أطول ويعكس نتائج بحث مباشرة. + + + +## كيف يترابط هذا + +1. **Flow** — يشغّل `LatestAiFlow` أولًا `prepare_topic` ثم `run_research` ثم `summarize`. الحالة (`topic`، `report`) على Flow. +2. **الطاقم** — يحمّل `kickoff_content_crew` ملف `crew.jsonc` ويشغّل مهمة واحدة بوكيل واحد: الباحث يستخدم **Serper** للبحث على الويب ثم يكتب التقرير. +3. **المُخرَج** — يكتب `output_file` للمهمة التقرير في `output/report.md`. + +للتعمق في أنماط Flow (التوجيه، الاستمرارية، الإنسان في الحلقة)، راجع [ابنِ أول Flow](/ar/guides/flows/first-flow) و[Flows](/ar/concepts/flows). للطواقم دون Flow، راجع [Crews](/ar/concepts/crews). لوكيل `Agent` واحد و`kickoff()` بلا مهام، راجع [Agents](/ar/concepts/agents#direct-agent-interaction-with-kickoff). + + +أصبح لديك Flow كامل مع طاقم وكيل وتقرير محفوظ — قاعدة قوية لإضافة خطوات أو طواقم أو أدوات. + + +### اتساق التسمية + +يجب أن تطابق الأسماء في `crew.jsonc` الملفات والمراجع: + +- `agents: ["researcher"]` يحمّل `agents/researcher.jsonc` +- `tasks[].agent: "researcher"` يربط المهمة بذلك الـ agent + +## النشر + +ادفع Flow إلى **[CrewAI AMP](https://app.crewai.com)** بعد أن يعمل محليًا ويكون المشروع في مستودع **GitHub**. من جذر المشروع: + + +```bash المصادقة +crewai login +``` + +```bash إنشاء نشر +crewai deploy create +``` + +```bash الحالة والسجلات +crewai deploy status +crewai deploy logs +``` + +```bash إرسال التحديثات بعد تغيير الكود +crewai deploy push +``` + +```bash عرض النشرات أو حذفها +crewai deploy list +crewai deploy remove +``` + + + + غالبًا ما يستغرق **النشر الأول حوالي دقيقة**. المتطلبات الكاملة ومسار الواجهة الويب في [النشر على AMP](https://docs-platform.crewai.com/platform/ar/guides/deploy-to-amp). + + + + + النشر على AMP خطوة بخطوة (CLI ولوحة التحكم). + + + ناقش الأفكار وشارك مشاريعك وتواصل مع مطوري CrewAI. + + diff --git a/docs/v1.15.13/ar/skills.mdx b/docs/v1.15.13/ar/skills.mdx new file mode 100644 index 0000000000..57c189c968 --- /dev/null +++ b/docs/v1.15.13/ar/skills.mdx @@ -0,0 +1,50 @@ +--- +title: Skills +description: ثبّت crewaiinc/skills من السجل الرسمي على skills.sh—Flows وCrews ووكلاء مرتبطون بالوثائق لـ Claude Code وCursor وCodex وغيرها. +icon: wand-magic-sparkles +mode: "wide" +--- + +# Skills + +**امنح وكيل البرمجة سياق CrewAI في أمر واحد.** + +تُنشر **Skills** الخاصة بـ CrewAI على **[skills.sh/crewaiinc/skills](https://skills.sh/crewaiinc/skills)**—السجل الرسمي لـ `crewaiinc/skills`، بما في ذلك كل مهارة (مثل **design-agent** و**getting-started** و**design-task** و**ask-docs**) وإحصاءات التثبيت والتدقيقات. تعلّم وكلاء البرمجة—مثل Claude Code وCursor وCodex—هيكلة Flows وضبط Crews واستخدام الأدوات واتباع أنماط CrewAI. نفّذ الأمر أدناه (أو الصقه في الوكيل). + +```shell Terminal +npx skills add crewaiinc/skills +``` + +يضيف ذلك حزمة المهارات إلى سير عمل الوكيل لتطبيق اتفاقيات CrewAI دون إعادة شرح الإطار في كل جلسة. المصدر والقضايا على [GitHub](https://github.com/crewAIInc/skills). + +## ما يحصل عليه الوكيل + +- **Flows** — تطبيقات ذات حالة وخطوات وkickoffs للـ crew على نمط CrewAI +- **Crews والوكلاء** — أنماط JSON-first (`crew.jsonc` و `agents/*.jsonc`)، أدوار، مهام، وتفويض +- **الأدوات والتكاملات** — ربط الوكلاء بالبحث وواجهات API وأدوات CrewAI الشائعة +- **هيكل المشروع** — مواءمة مع قوالب CLI واتفاقيات المستودع +- **أنماط محدثة** — تتبع المهارات وثائق CrewAI والممارسات الموصى بها + +## تعرّف أكثر على هذا الموقع + + + + استخدام `AGENTS.md` وسير عمل وكلاء البرمجة مع CrewAI. + + + ابنِ أول Flow وcrew من البداية للنهاية. + + + ثبّت CrewAI CLI وحزمة Python. + + + القائمة الرسمية لـ `crewaiinc/skills`—المهارات والتثبيتات والتدقيقات. + + + مصدر الحزمة والتحديثات والقضايا. + + + +### فيديو: CrewAI مع مهارات وكلاء البرمجة + + + +### 11. Login + +Authenticate with CrewAI AMP using a secure device code flow (no email entry required). + +```shell Terminal +crewai login +``` + +What happens: + +- A verification URL and short code are displayed in your terminal +- Your browser opens to the verification URL +- Enter/confirm the code to complete authentication + +Notes: + +- The OAuth2 provider and domain are configured via `crewai config` (defaults use `login.crewai.com`) +- After successful login, the CLI also attempts to authenticate to the Tool Repository automatically +- If you reset your configuration, run `crewai login` again to re-authenticate + +### 12. API Keys + +When running the `crewai create crew` command, the CLI shows a list of available LLM providers, followed by model selection for your chosen provider. The selected model is saved in the generated `.env` file and each generated agent JSONC file can set its own `llm`. + +Once you've selected an LLM provider and model, you will be prompted for API keys. + +#### Available LLM Providers + +Here's a list of the most popular LLM providers suggested by the CLI: + +- OpenAI +- Groq +- Anthropic +- Google Gemini +- SambaNova + +When you select a provider, the CLI will then show you available models for that provider and prompt you to enter your API key. + +#### Other Options + +If you select "other", you will be able to select from a list of LiteLLM supported providers. + +When you select a provider, the CLI will prompt you to enter the Key name and the API key. + +See the following link for each provider's key name: + +- [LiteLLM Providers](https://docs.litellm.ai/docs/providers) + +### 13. Configuration Management + +Manage CLI configuration settings for CrewAI. + +```shell Terminal +crewai config [COMMAND] [OPTIONS] +``` + +#### Commands: + +- `list`: Display all CLI configuration parameters + +```shell Terminal +crewai config list +``` + +- `set`: Set a CLI configuration parameter + +```shell Terminal +crewai config set +``` + +- `reset`: Reset all CLI configuration parameters to default values + +```shell Terminal +crewai config reset +``` + +#### Available Configuration Parameters + +- `enterprise_base_url`: Base URL of the CrewAI AMP instance +- `oauth2_provider`: OAuth2 provider used for authentication (e.g., workos, okta, auth0) +- `oauth2_audience`: OAuth2 audience value, typically used to identify the target API or resource +- `oauth2_client_id`: OAuth2 client ID issued by the provider, used during authentication requests +- `oauth2_domain`: OAuth2 provider's domain (e.g., your-org.auth0.com) used for issuing tokens + +#### Examples + +Display current configuration: + +```shell Terminal +crewai config list +``` + +Example output: +| Setting | Value | Description | +| :------------------ | :----------------------- | :---------------------------------------------------------- | +| enterprise_base_url | https://app.crewai.com | Base URL of the CrewAI AMP instance | +| org_name | Not set | Name of the currently active organization | +| org_uuid | Not set | UUID of the currently active organization | +| oauth2_provider | workos | OAuth2 provider (e.g., workos, okta, auth0) | +| oauth2_audience | client_01YYY | Audience identifying the target API/resource | +| oauth2_client_id | client_01XXX | OAuth2 client ID issued by the provider | +| oauth2_domain | login.crewai.com | Provider domain (e.g., your-org.auth0.com) | + +Set the enterprise base URL: + +```shell Terminal +crewai config set enterprise_base_url https://my-enterprise.crewai.com +``` + +Set OAuth2 provider: + +```shell Terminal +crewai config set oauth2_provider auth0 +``` + +Set OAuth2 domain: + +```shell Terminal +crewai config set oauth2_domain my-company.auth0.com +``` + +Reset all configuration to defaults: + +```shell Terminal +crewai config reset +``` + + + After resetting configuration, re-run `crewai login` to authenticate again. + + +### 14. Trace Management + +Manage trace collection preferences for your Crew and Flow executions. + +```shell Terminal +crewai traces [COMMAND] +``` + +#### Commands: + +- `enable`: Enable trace collection for crew/flow executions + +```shell Terminal +crewai traces enable +``` + +- `disable`: Disable trace collection for crew/flow executions + +```shell Terminal +crewai traces disable +``` + +- `status`: Show current trace collection status + +```shell Terminal +crewai traces status +``` + +#### How Tracing Works + +Trace collection is controlled by checking three settings in priority order: + +1. **Explicit flag in code** (highest priority - can enable OR disable): + + ```python + crew = Crew(agents=[...], tasks=[...], tracing=True) # Always enable + crew = Crew(agents=[...], tasks=[...], tracing=False) # Always disable + crew = Crew(agents=[...], tasks=[...]) # Check lower priorities (default) + ``` + + - `tracing=True` will **always enable** tracing (overrides everything) + - `tracing=False` will **always disable** tracing (overrides everything) + - `tracing=None` or omitted will check lower priority settings + +2. **Environment variable** (second priority): + + ```env + CREWAI_TRACING_ENABLED=true + ``` + + - Checked only if `tracing` is not explicitly set to `True` or `False` in code + - Set to `true` or `1` to enable tracing + +3. **User preference** (lowest priority): + ```shell Terminal + crewai traces enable + ``` + - Checked only if `tracing` is not set in code and `CREWAI_TRACING_ENABLED` is not set to `true` + - Running `crewai traces enable` is sufficient to enable tracing by itself + + +**To enable tracing**, use any one of these methods: +- Set `tracing=True` in your Crew/Flow code, OR +- Add `CREWAI_TRACING_ENABLED=true` to your `.env` file, OR +- Run `crewai traces enable` + +**To disable tracing**, use any ONE of these methods: + +- Set `tracing=False` in your Crew/Flow code (overrides everything), OR +- Remove or set to `false` the `CREWAI_TRACING_ENABLED` env var, OR +- Run `crewai traces disable` + +Higher priority settings override lower ones. + + + + + For more information about tracing, see the [Tracing + documentation](/observability/tracing). + + + + CrewAI CLI handles authentication to the Tool Repository automatically when + adding packages to your project. Just append `crewai` before any `uv` command + to use it. E.g. `crewai uv add requests`. For more information, see [Tool + Repository](https://docs-platform.crewai.com/platform/en/guides/tool-repository) docs. + + + + Configuration settings are stored in `~/.config/crewai/settings.json`. Some + settings like organization name and UUID are read-only and managed through + authentication and organization commands. Tool repository related settings are + hidden and cannot be set directly by users. + diff --git a/docs/v1.15.13/en/concepts/collaboration.mdx b/docs/v1.15.13/en/concepts/collaboration.mdx new file mode 100644 index 0000000000..867db5b338 --- /dev/null +++ b/docs/v1.15.13/en/concepts/collaboration.mdx @@ -0,0 +1,363 @@ +--- +title: Collaboration +description: How to enable agents to work together, delegate tasks, and communicate effectively within CrewAI teams. +icon: screen-users +mode: "wide" +--- + +## Overview + +Collaboration in CrewAI enables agents to work together as a team by delegating tasks and asking questions to leverage each other's expertise. When `allow_delegation=True`, agents automatically gain access to powerful collaboration tools. + +## Quick Start: Enable Collaboration + +```python +from crewai import Agent, Crew, Task + +# Enable collaboration for agents +researcher = Agent( + role="Research Specialist", + goal="Conduct thorough research on any topic", + backstory="Expert researcher with access to various sources", + allow_delegation=True, # 🔑 Key setting for collaboration + verbose=True +) + +writer = Agent( + role="Content Writer", + goal="Create engaging content based on research", + backstory="Skilled writer who transforms research into compelling content", + allow_delegation=True, # 🔑 Enables asking questions to other agents + verbose=True +) + +# Agents can now collaborate automatically +crew = Crew( + agents=[researcher, writer], + tasks=[...], + verbose=True +) +``` + +## How Agent Collaboration Works + +When `allow_delegation=True`, CrewAI automatically provides agents with two powerful tools: + +### 1. **Delegate Work Tool** +Allows agents to assign tasks to teammates with specific expertise. + +```python +# Agent automatically gets this tool: +# Delegate work to coworker(task: str, context: str, coworker: str) +``` + +### 2. **Ask Question Tool** +Enables agents to ask specific questions to gather information from colleagues. + +```python +# Agent automatically gets this tool: +# Ask question to coworker(question: str, context: str, coworker: str) +``` + +## Collaboration in Action + +Here's a complete example showing agents collaborating on a content creation task: + +```python +from crewai import Agent, Crew, Task, Process + +# Create collaborative agents +researcher = Agent( + role="Research Specialist", + goal="Find accurate, up-to-date information on any topic", + backstory="""You're a meticulous researcher with expertise in finding + reliable sources and fact-checking information across various domains.""", + allow_delegation=True, + verbose=True +) + +writer = Agent( + role="Content Writer", + goal="Create engaging, well-structured content", + backstory="""You're a skilled content writer who excels at transforming + research into compelling, readable content for different audiences.""", + allow_delegation=True, + verbose=True +) + +editor = Agent( + role="Content Editor", + goal="Ensure content quality and consistency", + backstory="""You're an experienced editor with an eye for detail, + ensuring content meets high standards for clarity and accuracy.""", + allow_delegation=True, + verbose=True +) + +# Create a task that encourages collaboration +article_task = Task( + description="""Write a comprehensive 1000-word article about 'The Future of AI in Healthcare'. + + The article should include: + - Current AI applications in healthcare + - Emerging trends and technologies + - Potential challenges and ethical considerations + - Expert predictions for the next 5 years + + Collaborate with your teammates to ensure accuracy and quality.""", + expected_output="A well-researched, engaging 1000-word article with proper structure and citations", + agent=writer # Writer leads, but can delegate research to researcher +) + +# Create collaborative crew +crew = Crew( + agents=[researcher, writer, editor], + tasks=[article_task], + process=Process.sequential, + verbose=True +) + +result = crew.kickoff() +``` + +## Collaboration Patterns + +### Pattern 1: Research → Write → Edit +```python +research_task = Task( + description="Research the latest developments in quantum computing", + expected_output="Comprehensive research summary with key findings and sources", + agent=researcher +) + +writing_task = Task( + description="Write an article based on the research findings", + expected_output="Engaging 800-word article about quantum computing", + agent=writer, + context=[research_task] # Gets research output as context +) + +editing_task = Task( + description="Edit and polish the article for publication", + expected_output="Publication-ready article with improved clarity and flow", + agent=editor, + context=[writing_task] # Gets article draft as context +) +``` + +### Pattern 2: Collaborative Single Task +```python +collaborative_task = Task( + description="""Create a marketing strategy for a new AI product. + + Writer: Focus on messaging and content strategy + Researcher: Provide market analysis and competitor insights + + Work together to create a comprehensive strategy.""", + expected_output="Complete marketing strategy with research backing", + agent=writer # Lead agent, but can delegate to researcher +) +``` + +## Hierarchical Collaboration + +For complex projects, use a hierarchical process with a manager agent: + +```python +from crewai import Agent, Crew, Task, Process + +# Manager agent coordinates the team +manager = Agent( + role="Project Manager", + goal="Coordinate team efforts and ensure project success", + backstory="Experienced project manager skilled at delegation and quality control", + allow_delegation=True, + verbose=True +) + +# Specialist agents +researcher = Agent( + role="Researcher", + goal="Provide accurate research and analysis", + backstory="Expert researcher with deep analytical skills", + allow_delegation=False, # Specialists focus on their expertise + verbose=True +) + +writer = Agent( + role="Writer", + goal="Create compelling content", + backstory="Skilled writer who creates engaging content", + allow_delegation=False, + verbose=True +) + +# Manager-led task +project_task = Task( + description="Create a comprehensive market analysis report with recommendations", + expected_output="Executive summary, detailed analysis, and strategic recommendations", + agent=manager # Manager will delegate to specialists +) + +# Hierarchical crew +crew = Crew( + agents=[manager, researcher, writer], + tasks=[project_task], + process=Process.hierarchical, # Manager coordinates everything + manager_llm="gpt-4o", # Specify LLM for manager + verbose=True +) +``` + +## Best Practices for Collaboration + +### 1. **Clear Role Definition** +```python +# ✅ Good: Specific, complementary roles +researcher = Agent(role="Market Research Analyst", ...) +writer = Agent(role="Technical Content Writer", ...) + +# ❌ Avoid: Overlapping or vague roles +agent1 = Agent(role="General Assistant", ...) +agent2 = Agent(role="Helper", ...) +``` + +### 2. **Strategic Delegation Enabling** +```python +# ✅ Enable delegation for coordinators and generalists +lead_agent = Agent( + role="Content Lead", + allow_delegation=True, # Can delegate to specialists + ... +) + +# ✅ Disable for focused specialists (optional) +specialist_agent = Agent( + role="Data Analyst", + allow_delegation=False, # Focuses on core expertise + ... +) +``` + +### 3. **Context Sharing** +```python +# ✅ Use context parameter for task dependencies +writing_task = Task( + description="Write article based on research", + agent=writer, + context=[research_task], # Shares research results + ... +) +``` + +### 4. **Clear Task Descriptions** +```python +# ✅ Specific, actionable descriptions +Task( + description="""Research competitors in the AI chatbot space. + Focus on: pricing models, key features, target markets. + Provide data in a structured format.""", + ... +) + +# ❌ Vague descriptions that don't guide collaboration +Task(description="Do some research about chatbots", ...) +``` + +## Troubleshooting Collaboration + +### Issue: Agents Not Collaborating +**Symptoms:** Agents work in isolation, no delegation occurs +```python +# ✅ Solution: Ensure delegation is enabled +agent = Agent( + role="...", + allow_delegation=True, # This is required! + ... +) +``` + +### Issue: Too Much Back-and-Forth +**Symptoms:** Agents ask excessive questions, slow progress +```python +# ✅ Solution: Provide better context and specific roles +Task( + description="""Write a technical blog post about machine learning. + + Context: Target audience is software developers with basic ML knowledge. + Length: 1200 words + Include: code examples, practical applications, best practices + + If you need specific technical details, delegate research to the researcher.""", + ... +) +``` + +### Issue: Delegation Loops +**Symptoms:** Agents delegate back and forth indefinitely +```python +# ✅ Solution: Clear hierarchy and responsibilities +manager = Agent(role="Manager", allow_delegation=True) +specialist1 = Agent(role="Specialist A", allow_delegation=False) # No re-delegation +specialist2 = Agent(role="Specialist B", allow_delegation=False) +``` + +## Advanced Collaboration Features + +### Custom Collaboration Rules +```python +# Set specific collaboration guidelines in agent backstory +agent = Agent( + role="Senior Developer", + backstory="""You lead development projects and coordinate with team members. + + Collaboration guidelines: + - Delegate research tasks to the Research Analyst + - Ask the Designer for UI/UX guidance + - Consult the QA Engineer for testing strategies + - Only escalate blocking issues to the Project Manager""", + allow_delegation=True +) +``` + +### Monitoring Collaboration +```python +def track_collaboration(output): + """Track collaboration patterns""" + if "Delegate work to coworker" in output.raw: + print("🤝 Delegation occurred") + if "Ask question to coworker" in output.raw: + print("❓ Question asked") + +crew = Crew( + agents=[...], + tasks=[...], + step_callback=track_collaboration, # Monitor collaboration + verbose=True +) +``` + +## Memory and Learning + +Enable agents to remember past collaborations: + +```python +agent = Agent( + role="Content Lead", + memory=True, # Remembers past interactions + allow_delegation=True, + verbose=True +) +``` + +With memory enabled, agents learn from previous collaborations and improve their delegation decisions over time. + +## Next Steps + +- **Try the examples**: Start with the basic collaboration example +- **Experiment with roles**: Test different agent role combinations +- **Monitor interactions**: Use `verbose=True` to see collaboration in action +- **Optimize task descriptions**: Clear tasks lead to better collaboration +- **Scale up**: Try hierarchical processes for complex projects + +Collaboration transforms individual AI agents into powerful teams that can tackle complex, multi-faceted challenges together. diff --git a/docs/v1.15.13/en/concepts/crews.mdx b/docs/v1.15.13/en/concepts/crews.mdx new file mode 100644 index 0000000000..2e4f210324 --- /dev/null +++ b/docs/v1.15.13/en/concepts/crews.mdx @@ -0,0 +1,460 @@ +--- +title: Crews +description: Understanding and utilizing crews in the crewAI framework with comprehensive attributes and functionalities. +icon: people-group +mode: "wide" +--- + +## Overview + +A crew in crewAI represents a collaborative group of agents working together to achieve a set of tasks. Each crew defines the strategy for task execution, agent collaboration, and the overall workflow. + +## Crew Attributes + +| Attribute | Parameters | Description | +| :------------------------------------ | :--------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Tasks** | `tasks` | A list of tasks assigned to the crew. | +| **Agents** | `agents` | A list of agents that are part of the crew. | +| **Process** _(optional)_ | `process` | The process flow (e.g., sequential, hierarchical) the crew follows. Default is `sequential`. | +| **Verbose** _(optional)_ | `verbose` | The verbosity level for logging during execution. Defaults to `False`. | +| **Manager LLM** _(optional)_ | `manager_llm` | The language model used by the manager agent in a hierarchical process. **Required when using a hierarchical process.** | +| **Function Calling LLM** _(optional)_ | `function_calling_llm` | If passed, the crew will use this LLM to do function calling for tools for all agents in the crew. Each agent can have its own LLM, which overrides the crew's LLM for function calling. | +| **Config** _(optional)_ | `config` | Optional configuration settings for the crew, in `Json` or `Dict[str, Any]` format. | +| **Max RPM** _(optional)_ | `max_rpm` | Maximum requests per minute the crew adheres to during execution. Defaults to `None`. | +| **Memory** _(optional)_ | `memory` | Utilized for storing execution memories (short-term, long-term, entity memory). | | +| **Cache** _(optional)_ | `cache` | Specifies whether to use a cache for storing the results of tools' execution. Defaults to `True`. | +| **Embedder** _(optional)_ | `embedder` | Configuration for the embedder to be used by the crew. Mostly used by memory for now. Default is `{"provider": "openai"}`. | +| **Step Callback** _(optional)_ | `step_callback` | A function that is called after each step of every agent. This can be used to log the agent's actions or to perform other operations; it won't override the agent-specific `step_callback`. | +| **Task Callback** _(optional)_ | `task_callback` | A function that is called after the completion of each task. Useful for monitoring or additional operations post-task execution. | +| **Share Crew** _(optional)_ | `share_crew` | Whether you want to share the complete crew information and execution with the crewAI team to make the library better, and allow us to train models. | +| **Output Log File** _(optional)_ | `output_log_file` | Set to True to save logs as logs.txt in the current directory or provide a file path. Logs will be in JSON format if the filename ends in .json, otherwise .txt. Defaults to `None`. | +| **Manager Agent** _(optional)_ | `manager_agent` | `manager` sets a custom agent that will be used as a manager. | +| **Prompt File** _(optional)_ | `prompt_file` | Path to the prompt JSON file to be used for the crew. | +| **Planning** *(optional)* | `planning` | Adds planning ability to the Crew. When activated before each Crew iteration, all Crew data is sent to an AgentPlanner that will plan the tasks and this plan will be added to each task description. | +| **Planning LLM** *(optional)* | `planning_llm` | The language model used by the AgentPlanner in a planning process. | +| **Knowledge Sources** _(optional)_ | `knowledge_sources` | Knowledge sources available at the crew level, accessible to all the agents. | +| **Stream** _(optional)_ | `stream` | Enable streaming output to receive real-time updates during crew execution. Returns a `CrewStreamingOutput` object that can be iterated for chunks. Defaults to `False`. | +| **Chat LLM** _(optional)_ | `chat_llm` | The language model used to orchestrate `crewai chat` CLI interactions with the crew. Accepts a model name string or `LLM` instance. Defaults to `None`. | +| **Before Kickoff Callbacks** _(optional)_ | `before_kickoff_callbacks` | A list of callable functions executed **before** the crew starts. Each callback receives and can modify the inputs dict. Distinct from the `@before_kickoff` decorator. Defaults to `[]`. | +| **After Kickoff Callbacks** _(optional)_ | `after_kickoff_callbacks` | A list of callable functions executed **after** the crew finishes. Each callback receives and can modify the `CrewOutput`. Distinct from the `@after_kickoff` decorator. Defaults to `[]`. | +| **Tracing** _(optional)_ | `tracing` | Controls OpenTelemetry tracing for the crew. `True` = always enable, `False` = always disable, `None` = inherit from environment / user settings. Defaults to `None`. | +| **Skills** _(optional)_ | `skills` | A list of `Path` objects (skill search directories) or pre-loaded `Skill` objects applied to all agents in the crew. Defaults to `None`. | +| **Security Config** _(optional)_ | `security_config` | A `SecurityConfig` instance managing crew fingerprinting and identity. Defaults to `SecurityConfig()`. | +| **Checkpoint** _(optional)_ | `checkpoint` | Enables automatic checkpointing. Pass `True` for sensible defaults, a `CheckpointConfig` for full control, `False` to opt out, or `None` to inherit. See the [Checkpointing](#checkpointing) section below. Defaults to `None`. | + + +**Crew Max RPM**: The `max_rpm` attribute sets the maximum number of requests per minute the crew can perform to avoid rate limits and will override individual agents' `max_rpm` settings if you set it. + + +## Creating Crews + +There are two common ways to create crews in CrewAI: using **JSONC project configuration (recommended for new crews)** or defining them **directly in code**. + +### JSONC Configuration (Recommended) + +New projects created with `crewai create crew ` use `crew.jsonc` for crew-level settings and tasks, plus one file per agent in `agents/`. + +`crewai run` automatically detects `crew.jsonc` or `crew.json`, loads the referenced agents, prompts for missing placeholders, and kicks off the crew. + +#### Example `crew.jsonc` + +```jsonc crew.jsonc +{ + "name": "Market Research Crew", + "agents": ["researcher", "analyst"], + "tasks": [ + { + "name": "research", + "description": "Research {topic} and collect the most relevant facts.", + "expected_output": "Structured research notes about {topic}.", + "agent": "researcher" + }, + { + "name": "analysis", + "description": "Analyze the research and write a concise report.", + "expected_output": "A markdown report with findings and recommendations.", + "agent": "analyst", + "context": ["research"], + "output_file": "output/report.md" + } + ], + "process": "sequential", + "verbose": true, + "memory": true, + "inputs": { + "topic": "AI Agents" + } +} +``` + +Each string in `agents` resolves to `agents/.jsonc` first, then `agents/.json`. + +```jsonc agents/researcher.jsonc +{ + "role": "{topic} Senior Researcher", + "goal": "Find accurate and current information about {topic}.", + "backstory": "You are a careful researcher who cites clear evidence.", + "llm": "openai/gpt-4o", + "tools": ["SerperDevTool"] +} +``` + + +Tasks run in the order they appear in `tasks` when `process` is `"sequential"`. + + +For hierarchical crews, set `"process": "hierarchical"` and provide either `manager_llm` or `manager_agent`. A `manager_agent` can reference an `agents/.jsonc` file that is not included in the top-level `agents` list. + +JSON crew definitions support crew-level fields such as `process`, `verbose`, `memory`, `cache`, `max_rpm`, `planning`, `planning_llm`, `manager_llm`, `manager_agent`, `function_calling_llm`, `output_log_file`, `stream`, `tracing`, `before_kickoff_callbacks`, and `after_kickoff_callbacks`. + +Python callbacks and custom classes use `{"python": "module.attribute"}`. Custom tools use `"custom:"` and load `tools/.py` at runtime. + + +Only run JSON crew projects from sources you trust. `custom:` tools and `{"python": "module.attribute"}` references execute local Python code when the crew loads. + + +### Classic Python/YAML Configuration + +Classic projects created with `crewai create crew --classic` use `crew.py`, `config/agents.yaml`, `config/tasks.yaml`, and the `@CrewBase`, `@agent`, `@task`, and `@crew` decorators. That pattern remains supported and is documented in [Using Annotations](/en/learn/using-annotations). + +### Direct Code Definition (Alternative) + +Alternatively, you can define the crew directly in code without using YAML configuration files. + +```python code +from crewai import Agent, Crew, Task, Process +from crewai_tools import YourCustomTool + +class YourCrewName: + def agent_one(self) -> Agent: + return Agent( + role="Data Analyst", + goal="Analyze data trends in the market", + backstory="An experienced data analyst with a background in economics", + verbose=True, + tools=[YourCustomTool()] + ) + + def agent_two(self) -> Agent: + return Agent( + role="Market Researcher", + goal="Gather information on market dynamics", + backstory="A diligent researcher with a keen eye for detail", + verbose=True + ) + + def task_one(self) -> Task: + return Task( + description="Collect recent market data and identify trends.", + expected_output="A report summarizing key trends in the market.", + agent=self.agent_one() + ) + + def task_two(self) -> Task: + return Task( + description="Research factors affecting market dynamics.", + expected_output="An analysis of factors influencing the market.", + agent=self.agent_two() + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.agent_one(), self.agent_two()], + tasks=[self.task_one(), self.task_two()], + process=Process.sequential, + verbose=True + ) +``` +How to run the above code: + +```python code +YourCrewName().crew().kickoff(inputs={}) +``` + +In this example: + +- Agents and tasks are defined directly within the class without decorators. +- We manually create and manage the list of agents and tasks. +- This approach provides more control but can be less maintainable for larger projects. + +## Crew Output + +The output of a crew in the CrewAI framework is encapsulated within the `CrewOutput` class. +This class provides a structured way to access results of the crew's execution, including various formats such as raw strings, JSON, and Pydantic models. +The `CrewOutput` includes the results from the final task output, token usage, and individual task outputs. + +### Crew Output Attributes + +| Attribute | Parameters | Type | Description | +| :--------------- | :------------- | :------------------------- | :--------------------------------------------------------------------------------------------------- | +| **Raw** | `raw` | `str` | The raw output of the crew. This is the default format for the output. | +| **Pydantic** | `pydantic` | `Optional[BaseModel]` | A Pydantic model object representing the structured output of the crew. | +| **JSON Dict** | `json_dict` | `Optional[Dict[str, Any]]` | A dictionary representing the JSON output of the crew. | +| **Tasks Output** | `tasks_output` | `List[TaskOutput]` | A list of `TaskOutput` objects, each representing the output of a task in the crew. | +| **Token Usage** | `token_usage` | `Dict[str, Any]` | A summary of token usage, providing insights into the language model's performance during execution. | + +### Crew Output Methods and Properties + +| Method/Property | Description | +| :-------------- | :------------------------------------------------------------------------------------------------ | +| **json** | Returns the JSON string representation of the crew output if the output format is JSON. | +| **to_dict** | Converts the JSON and Pydantic outputs to a dictionary. | +| \***\*str\*\*** | Returns the string representation of the crew output, prioritizing Pydantic, then JSON, then raw. | + +### Accessing Crew Outputs + +Once a crew has been executed, its output can be accessed through the `output` attribute of the `Crew` object. The `CrewOutput` class provides various ways to interact with and present this output. + +#### Example + +```python Code +# Example crew execution +crew = Crew( + agents=[research_agent, writer_agent], + tasks=[research_task, write_article_task], + verbose=True +) + +crew_output = crew.kickoff() + +# Accessing the crew output +print(f"Raw Output: {crew_output.raw}") +if crew_output.json_dict: + print(f"JSON Output: {json.dumps(crew_output.json_dict, indent=2)}") +if crew_output.pydantic: + print(f"Pydantic Output: {crew_output.pydantic}") +print(f"Tasks Output: {crew_output.tasks_output}") +print(f"Token Usage: {crew_output.token_usage}") +``` + +## Accessing Crew Logs + +You can see real time log of the crew execution, by setting `output_log_file` as a `True(Boolean)` or a `file_name(str)`. Supports logging of events as both `file_name.txt` and `file_name.json`. +In case of `True(Boolean)` will save as `logs.txt`. + +In case of `output_log_file` is set as `False(Boolean)` or `None`, the logs will not be populated. + +```python Code +# Save crew logs +crew = Crew(output_log_file = True) # Logs will be saved as logs.txt +crew = Crew(output_log_file = file_name) # Logs will be saved as file_name.txt +crew = Crew(output_log_file = file_name.txt) # Logs will be saved as file_name.txt +crew = Crew(output_log_file = file_name.json) # Logs will be saved as file_name.json +``` + + + +## Checkpointing + +Checkpointing lets a crew automatically save its state after key events (e.g. task completion) so that long-running or interrupted runs can be resumed exactly where they left off without re-executing completed tasks. + +### Quick Start + +Pass `checkpoint=True` to enable checkpointing with sensible defaults (saves to `.checkpoints/` after every task): + +```python Code +from crewai import Crew, Process + +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, write_task], + process=Process.sequential, + checkpoint=True, # saves to .checkpoints/ after every task +) + +crew.kickoff(inputs={"topic": "AI trends"}) +``` + +### Full Control with `CheckpointConfig` + +Use `CheckpointConfig` for fine-grained control over location, trigger events, storage backend, and retention: + +```python Code +from crewai import Crew, Process +from crewai.state.checkpoint_config import CheckpointConfig + +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, write_task], + process=Process.sequential, + checkpoint=CheckpointConfig( + location="./.checkpoints", # directory for JSON files (default) + on_events=["task_completed"], # trigger after each task (default) + max_checkpoints=5, # keep only the 5 most recent checkpoints + ), +) + +crew.kickoff(inputs={"topic": "AI trends"}) +``` + +### Resuming from a Checkpoint + +Use `Crew.from_checkpoint()` to restore a crew from a saved checkpoint file, then call `kickoff()` to resume: + +```python Code +# Resume from the most recent checkpoint +crew = Crew.from_checkpoint(".checkpoints/latest.json") +crew.kickoff() +``` + + +When restoring from a checkpoint, `checkpoint_inputs`, `checkpoint_train`, and `checkpoint_kickoff_event_id` are automatically reconstructed — you do not need to set these manually. + + +### `CheckpointConfig` Attributes + +| Attribute | Type | Default | Description | +| :----------------- | :------------------------------------- | :------------------- | :-------------------------------------------------------------------------------------------- | +| `location` | `str` | `"./.checkpoints"` | Storage destination. For `JsonProvider` this is a directory path; for `SqliteProvider` a database file path. | +| `on_events` | `list[str]` | `["task_completed"]` | Event types that trigger a checkpoint write. Use `["*"]` to checkpoint on every event. | +| `provider` | `JsonProvider \| SqliteProvider` | `JsonProvider()` | Storage backend. Defaults to `JsonProvider` (plain JSON files). | +| `max_checkpoints` | `int \| None` | `None` | Maximum checkpoints to keep. Oldest are pruned after each write. `None` keeps all. | + +## Memory Utilization + +Crews can utilize memory (short-term, long-term, and entity memory) to enhance their execution and learning over time. This feature allows crews to store and recall execution memories, aiding in decision-making and task execution strategies. + +## Cache Utilization + +Caches can be employed to store the results of tools' execution, making the process more efficient by reducing the need to re-execute identical tasks. + +## Crew Usage Metrics + +After the crew execution, you can access the `usage_metrics` attribute to view the language model (LLM) usage metrics for all tasks executed by the crew. This provides insights into operational efficiency and areas for improvement. + +`total_tokens` is the billed total (`prompt_tokens + completion_tokens`). Breakdown fields such as `cached_prompt_tokens` and `cache_creation_tokens` describe subsets already included in those totals and are not added on top of `total_tokens`. See the **UsageMetrics field semantics** section in the Flows concept documentation for the full contract. + +```python Code +# Access the crew's usage metrics +crew = Crew(agents=[agent1, agent2], tasks=[task1, task2]) +crew.kickoff() +print(crew.usage_metrics) +``` + +## Crew Execution Process + +- **Sequential Process**: Tasks are executed one after another, allowing for a linear flow of work. +- **Hierarchical Process**: A manager agent coordinates the crew, delegating tasks and validating outcomes before proceeding. **Note**: A `manager_llm` or `manager_agent` is required for this process and it's essential for validating the process flow. + +### Kicking Off a Crew + +Once your crew is assembled, initiate the workflow with the `kickoff()` method. This starts the execution process according to the defined process flow. + +```python Code +# Start the crew's task execution +result = my_crew.kickoff() +print(result) +``` + +### Different Ways to Kick Off a Crew + +Once your crew is assembled, initiate the workflow with the appropriate kickoff method. CrewAI provides several methods for better control over the kickoff process. + +#### Synchronous Methods + +- `kickoff()`: Starts the execution process according to the defined process flow. +- `kickoff_for_each()`: Executes tasks sequentially for each provided input event or item in the collection. + +#### Asynchronous Methods + +CrewAI offers two approaches for async execution: + +| Method | Type | Description | +|--------|------|-------------| +| `akickoff()` | Native async | True async/await throughout the entire execution chain | +| `akickoff_for_each()` | Native async | Native async execution for each input in a list | +| `kickoff_async()` | Thread-based | Wraps synchronous execution in `asyncio.to_thread` | +| `kickoff_for_each_async()` | Thread-based | Thread-based async for each input in a list | + + +For high-concurrency workloads, `akickoff()` and `akickoff_for_each()` are recommended as they use native async for task execution, memory operations, and knowledge retrieval. + + +```python Code +# Start the crew's task execution +result = my_crew.kickoff() +print(result) + +# Example of using kickoff_for_each +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +results = my_crew.kickoff_for_each(inputs=inputs_array) +for result in results: + print(result) + +# Example of using native async with akickoff +inputs = {'topic': 'AI in healthcare'} +async_result = await my_crew.akickoff(inputs=inputs) +print(async_result) + +# Example of using native async with akickoff_for_each +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +async_results = await my_crew.akickoff_for_each(inputs=inputs_array) +for async_result in async_results: + print(async_result) + +# Example of using thread-based kickoff_async +inputs = {'topic': 'AI in healthcare'} +async_result = await my_crew.kickoff_async(inputs=inputs) +print(async_result) + +# Example of using thread-based kickoff_for_each_async +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +async_results = await my_crew.kickoff_for_each_async(inputs=inputs_array) +for async_result in async_results: + print(async_result) +``` + +These methods provide flexibility in how you manage and execute tasks within your crew, allowing for both synchronous and asynchronous workflows tailored to your needs. For detailed async examples, see the [Kickoff Crew Asynchronously](/en/learn/kickoff-async) guide. + +### Streaming Crew Execution + +For real-time visibility into crew execution, you can enable streaming to receive output as it's generated: + +```python Code +# Enable streaming +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True +) + +# Iterate over streaming output +streaming = crew.kickoff(inputs={"topic": "AI"}) +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# Access final result +result = streaming.result +``` + +Learn more about streaming in the [Streaming Crew Execution](/en/learn/streaming-crew-execution) guide. + +### Replaying from a Specific Task + +You can now replay from a specific task using our CLI command `replay`. + +The replay feature in CrewAI allows you to replay from a specific task using the command-line interface (CLI). By running the command `crewai replay -t `, you can specify the `task_id` for the replay process. + +Kickoffs will now save the latest kickoffs returned task outputs locally for you to be able to replay from. + +### Replaying from a Specific Task Using the CLI + +To use the replay feature, follow these steps: + +1. Open your terminal or command prompt. +2. Navigate to the directory where your CrewAI project is located. +3. Run the following command: + +To view the latest kickoff task IDs, use: + +```shell +crewai log-tasks-outputs +``` + +Then, to replay from a specific task, use: + +```shell +crewai replay -t +``` + +These commands let you replay from your latest kickoff tasks, still retaining context from previously executed tasks. diff --git a/docs/v1.15.13/en/concepts/event-listener.mdx b/docs/v1.15.13/en/concepts/event-listener.mdx new file mode 100644 index 0000000000..403a2ff59a --- /dev/null +++ b/docs/v1.15.13/en/concepts/event-listener.mdx @@ -0,0 +1,415 @@ +--- +title: "Event Listeners" +description: "Tap into CrewAI events to build custom integrations and monitoring" +icon: spinner +mode: "wide" +--- + +## Overview + +CrewAI provides a powerful event system that allows you to listen for and react to various events that occur during the execution of your Crew. This feature enables you to build custom integrations, monitoring solutions, logging systems, or any other functionality that needs to be triggered based on CrewAI's internal events. + +## How It Works + +CrewAI uses an event bus architecture to emit events throughout the execution lifecycle. The event system is built on the following components: + +1. **CrewAIEventsBus**: A singleton event bus that manages event registration and emission +2. **BaseEvent**: Base class for all events in the system +3. **BaseEventListener**: Abstract base class for creating custom event listeners + +When specific actions occur in CrewAI (like a Crew starting execution, an Agent completing a task, or a tool being used), the system emits corresponding events. You can register handlers for these events to execute custom code when they occur. + + +CrewAI AMP provides a built-in Prompt Tracing feature that leverages the event system to track, store, and visualize all prompts, completions, and associated metadata. This provides powerful debugging capabilities and transparency into your agent operations. + +![Prompt Tracing Dashboard](/images/enterprise/traces-overview.png) + +With Prompt Tracing you can: + +- View the complete history of all prompts sent to your LLM +- Track token usage and costs +- Debug agent reasoning failures +- Share prompt sequences with your team +- Compare different prompt strategies +- Export traces for compliance and auditing + + +## Creating a Custom Event Listener + +To create a custom event listener, you need to: + +1. Create a class that inherits from `BaseEventListener` +2. Implement the `setup_listeners` method +3. Register handlers for the events you're interested in +4. Create an instance of your listener in the appropriate file + +Here's a simple example of a custom event listener class: + +```python +from crewai.events import ( + CrewKickoffStartedEvent, + CrewKickoffCompletedEvent, + AgentExecutionCompletedEvent, +) +from crewai.events import BaseEventListener + +class MyCustomListener(BaseEventListener): + def __init__(self): + super().__init__() + + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(CrewKickoffStartedEvent) + def on_crew_started(source, event): + print(f"Crew '{event.crew_name}' has started execution!") + + @crewai_event_bus.on(CrewKickoffCompletedEvent) + def on_crew_completed(source, event): + print(f"Crew '{event.crew_name}' has completed execution!") + print(f"Output: {event.output}") + + @crewai_event_bus.on(AgentExecutionCompletedEvent) + def on_agent_execution_completed(source, event): + print(f"Agent '{event.agent.role}' completed task") + print(f"Output: {event.output}") +``` + +## Properly Registering Your Listener + +Simply defining your listener class isn't enough. You need to create an instance of it and ensure it's imported in your application. This ensures that: + +1. The event handlers are registered with the event bus +2. The listener instance remains in memory (not garbage collected) +3. The listener is active when events are emitted + +### Option 1: Import and Instantiate in Your Crew or Flow Implementation + +The most important thing is to create an instance of your listener in the file where your Crew or Flow is defined and executed: + +#### For Crew-based Applications + +Create and import your listener at the top of your Crew implementation file: + +```python +# In your crew.py file +from crewai import Agent, Crew, Task +from my_listeners import MyCustomListener + +# Create an instance of your listener +my_listener = MyCustomListener() + +class MyCustomCrew: + # Your crew implementation... + + def crew(self): + return Crew( + agents=[...], + tasks=[...], + # ... + ) +``` + +#### For Flow-based Applications + +Create and import your listener at the top of your Flow implementation file: + +```python +# In your main.py or flow.py file +from crewai.flow import Flow, listen, start +from my_listeners import MyCustomListener + +# Create an instance of your listener +my_listener = MyCustomListener() + +class MyCustomFlow(Flow): + # Your flow implementation... + + @start() + def first_step(self): + # ... +``` + +This ensures that your listener is loaded and active when your Crew or Flow is executed. + +### Option 2: Create a Package for Your Listeners + +For a more structured approach, especially if you have multiple listeners: + +1. Create a package for your listeners: + +``` +my_project/ + ├── listeners/ + │ ├── __init__.py + │ ├── my_custom_listener.py + │ └── another_listener.py +``` + +2. In `my_custom_listener.py`, define your listener class and create an instance: + +```python +# my_custom_listener.py +from crewai.events import BaseEventListener +# ... import events ... + +class MyCustomListener(BaseEventListener): + # ... implementation ... + +# Create an instance of your listener +my_custom_listener = MyCustomListener() +``` + +3. In `__init__.py`, import the listener instances to ensure they're loaded: + +```python +# __init__.py +from .my_custom_listener import my_custom_listener +from .another_listener import another_listener + +# Optionally export them if you need to access them elsewhere +__all__ = ['my_custom_listener', 'another_listener'] +``` + +4. Import your listeners package in your Crew or Flow file: + +```python +# In your crew.py or flow.py file +import my_project.listeners # This loads all your listeners + +class MyCustomCrew: + # Your crew implementation... +``` + +This is how third-party event listeners are registered in the CrewAI codebase. + +## Available Event Types + +CrewAI provides a wide range of events that you can listen for: + +### Crew Events + +- **CrewKickoffStartedEvent**: Emitted when a Crew starts execution +- **CrewKickoffCompletedEvent**: Emitted when a Crew completes execution +- **CrewKickoffFailedEvent**: Emitted when a Crew fails to complete execution +- **CrewTestStartedEvent**: Emitted when a Crew starts testing +- **CrewTestCompletedEvent**: Emitted when a Crew completes testing +- **CrewTestFailedEvent**: Emitted when a Crew fails to complete testing +- **CrewTrainStartedEvent**: Emitted when a Crew starts training +- **CrewTrainCompletedEvent**: Emitted when a Crew completes training +- **CrewTrainFailedEvent**: Emitted when a Crew fails to complete training +- **CrewTestResultEvent**: Emitted when a Crew test result is available. Contains the quality score, execution duration, and model used. + +### Agent Events + +- **AgentExecutionStartedEvent**: Emitted when an Agent starts executing a task +- **AgentExecutionCompletedEvent**: Emitted when an Agent completes executing a task +- **AgentExecutionErrorEvent**: Emitted when an Agent encounters an error during execution +- **LiteAgentExecutionStartedEvent**: Emitted when a LiteAgent starts executing. Contains the agent info, tools, and messages. +- **LiteAgentExecutionCompletedEvent**: Emitted when a LiteAgent completes execution. Contains the agent info and output. +- **LiteAgentExecutionErrorEvent**: Emitted when a LiteAgent encounters an error during execution. Contains the agent info and error message. +- **AgentEvaluationStartedEvent**: Emitted when an agent evaluation starts. Contains the agent ID, agent role, optional task ID, and iteration number. +- **AgentEvaluationCompletedEvent**: Emitted when an agent evaluation completes. Contains the agent ID, agent role, optional task ID, iteration number, metric category, and score. +- **AgentEvaluationFailedEvent**: Emitted when an agent evaluation fails. Contains the agent ID, agent role, optional task ID, iteration number, and error message. + +### Task Events + +- **TaskStartedEvent**: Emitted when a Task starts execution +- **TaskCompletedEvent**: Emitted when a Task completes execution +- **TaskFailedEvent**: Emitted when a Task fails to complete execution +- **TaskEvaluationEvent**: Emitted when a Task is evaluated + +### Tool Usage Events + +- **ToolUsageStartedEvent**: Emitted when a tool execution is started +- **ToolUsageFinishedEvent**: Emitted when a tool execution is completed +- **ToolUsageErrorEvent**: Emitted when a tool execution encounters an error +- **ToolValidateInputErrorEvent**: Emitted when a tool input validation encounters an error +- **ToolExecutionErrorEvent**: Emitted when a tool execution encounters an error +- **ToolSelectionErrorEvent**: Emitted when there's an error selecting a tool + +### MCP Events + +- **MCPConnectionStartedEvent**: Emitted when starting to connect to an MCP server. Contains the server name, URL, transport type, connection timeout, and whether it's a reconnection attempt. +- **MCPConnectionCompletedEvent**: Emitted when successfully connected to an MCP server. Contains the server name, connection duration in milliseconds, and whether it was a reconnection. +- **MCPConnectionFailedEvent**: Emitted when connection to an MCP server fails. Contains the server name, error message, and error type (`timeout`, `authentication`, `network`, etc.). +- **MCPToolExecutionStartedEvent**: Emitted when starting to execute an MCP tool. Contains the server name, tool name, and tool arguments. +- **MCPToolExecutionCompletedEvent**: Emitted when MCP tool execution completes successfully. Contains the server name, tool name, result, and execution duration in milliseconds. +- **MCPToolExecutionFailedEvent**: Emitted when MCP tool execution fails. Contains the server name, tool name, error message, and error type (`timeout`, `validation`, `server_error`, etc.). +- **MCPConfigFetchFailedEvent**: Emitted when fetching an MCP server configuration fails (e.g., the MCP is not connected in your account, API error, or connection failure after config was fetched). Contains the slug, error message, and error type (`not_connected`, `api_error`, `connection_failed`). + +### Knowledge Events + +- **KnowledgeRetrievalStartedEvent**: Emitted when a knowledge retrieval is started +- **KnowledgeRetrievalCompletedEvent**: Emitted when a knowledge retrieval is completed +- **KnowledgeQueryStartedEvent**: Emitted when a knowledge query is started +- **KnowledgeQueryCompletedEvent**: Emitted when a knowledge query is completed +- **KnowledgeQueryFailedEvent**: Emitted when a knowledge query fails +- **KnowledgeSearchQueryFailedEvent**: Emitted when a knowledge search query fails + +### LLM Guardrail Events + +- **LLMGuardrailStartedEvent**: Emitted when a guardrail validation starts. Contains details about the guardrail being applied and retry count. +- **LLMGuardrailCompletedEvent**: Emitted when a guardrail validation completes. Contains details about validation success/failure, results, and error messages if any. +- **LLMGuardrailFailedEvent**: Emitted when a guardrail validation fails. Contains the error message and retry count. + +### Flow Events + +- **FlowCreatedEvent**: Emitted when a Flow is created +- **FlowStartedEvent**: Emitted when a Flow starts execution +- **FlowFinishedEvent**: Emitted when a Flow completes execution +- **FlowFailedEvent**: Emitted when a Flow execution fails. Contains the flow name and the exception that ended the execution. +- **FlowPausedEvent**: Emitted when a Flow is paused waiting for human feedback. Contains the flow name, flow ID, method name, current state, message shown when requesting feedback, and optional list of possible outcomes for routing. +- **FlowPlotEvent**: Emitted when a Flow is plotted +- **MethodExecutionStartedEvent**: Emitted when a Flow method starts execution +- **MethodExecutionFinishedEvent**: Emitted when a Flow method completes execution +- **MethodExecutionFailedEvent**: Emitted when a Flow method fails to complete execution +- **MethodExecutionPausedEvent**: Emitted when a Flow method is paused waiting for human feedback. Contains the flow name, method name, current state, flow ID, message shown when requesting feedback, and optional list of possible outcomes for routing. + +### Human In The Loop Events + +- **FlowInputRequestedEvent**: Emitted when a Flow requests user input via `Flow.ask()`. Contains the flow name, method name, the question or prompt being shown to the user, and optional metadata (e.g., user ID, channel, session context). +- **FlowInputReceivedEvent**: Emitted when user input is received after `Flow.ask()`. Contains the flow name, method name, the original question, the user's response (or `None` if timed out), optional request metadata, and optional response metadata from the provider (e.g., who responded, thread ID, timestamps). +- **HumanFeedbackRequestedEvent**: Emitted when a `@human_feedback` decorated method requires input from a human reviewer. Contains the flow name, method name, the method output shown to the human for review, the message displayed when requesting feedback, and optional list of possible outcomes for routing. +- **HumanFeedbackReceivedEvent**: Emitted when a human provides feedback in response to a `@human_feedback` decorated method. Contains the flow name, method name, the raw text feedback provided by the human, and the collapsed outcome string (if emit was specified). + +### LLM Events + +- **LLMCallStartedEvent**: Emitted when an LLM call starts +- **LLMCallCompletedEvent**: Emitted when an LLM call completes +- **LLMCallFailedEvent**: Emitted when an LLM call fails +- **LLMStreamChunkEvent**: Emitted for each chunk received during streaming LLM responses +- **LLMThinkingChunkEvent**: Emitted when a thinking/reasoning chunk is received from a thinking model. Contains the chunk text and optional response ID. + +### Memory Events + +- **MemoryQueryStartedEvent**: Emitted when a memory query is started. Contains the query, limit, and optional score threshold. +- **MemoryQueryCompletedEvent**: Emitted when a memory query is completed successfully. Contains the query, results, limit, score threshold, and query execution time. +- **MemoryQueryFailedEvent**: Emitted when a memory query fails. Contains the query, limit, score threshold, and error message. +- **MemorySaveStartedEvent**: Emitted when a memory save operation is started. Contains the value to be saved, metadata, and optional agent role. +- **MemorySaveCompletedEvent**: Emitted when a memory save operation is completed successfully. Contains the saved value, metadata, agent role, and save execution time. +- **MemorySaveFailedEvent**: Emitted when a memory save operation fails. Contains the value, metadata, agent role, and error message. +- **MemoryRetrievalStartedEvent**: Emitted when memory retrieval for a task prompt starts. Contains the optional task ID. +- **MemoryRetrievalCompletedEvent**: Emitted when memory retrieval for a task prompt completes successfully. Contains the task ID, memory content, and retrieval execution time. +- **MemoryRetrievalFailedEvent**: Emitted when memory retrieval for a task prompt fails. Contains the optional task ID and error message. + +### Reasoning Events + +- **AgentReasoningStartedEvent**: Emitted when an agent starts reasoning about a task. Contains the agent role, task ID, and attempt number. +- **AgentReasoningCompletedEvent**: Emitted when an agent finishes its reasoning process. Contains the agent role, task ID, the plan produced, and whether the agent is ready to proceed. +- **AgentReasoningFailedEvent**: Emitted when the reasoning process fails. Contains the agent role, task ID, and error message. + +### Observation Events + +- **StepObservationStartedEvent**: Emitted when the Planner begins observing a step's result. Fires after every step execution, before the observation LLM call. Contains the agent role, step number, and step description. +- **StepObservationCompletedEvent**: Emitted when the Planner finishes observing a step's result. Contains whether the step completed successfully, key information learned, whether the remaining plan is still valid, whether a full replan is needed, and suggested refinements. +- **StepObservationFailedEvent**: Emitted when the observation LLM call itself fails. The system defaults to continuing the plan. Contains the error message. +- **PlanRefinementEvent**: Emitted when the Planner refines upcoming step descriptions without a full replan. Contains the number of refined steps and the refinements applied. +- **PlanReplanTriggeredEvent**: Emitted when the Planner triggers a full replan because the remaining plan was deemed fundamentally wrong. Contains the replan reason, replan count, and number of completed steps preserved. +- **GoalAchievedEarlyEvent**: Emitted when the Planner detects the goal was achieved early and remaining steps will be skipped. Contains the number of steps remaining and steps completed. + +### A2A (Agent-to-Agent) Events + +#### Delegation Events + +- **A2ADelegationStartedEvent**: Emitted when A2A delegation starts. Contains the endpoint URL, task description, agent ID, context ID, whether it's multiturn, turn number, agent card metadata, protocol version, provider info, and optional skill ID. +- **A2ADelegationCompletedEvent**: Emitted when A2A delegation completes. Contains the completion status (`completed`, `input_required`, `failed`, etc.), result, error message, context ID, and agent card metadata. +- **A2AParallelDelegationStartedEvent**: Emitted when parallel delegation to multiple A2A agents begins. Contains the list of endpoints and the task description. +- **A2AParallelDelegationCompletedEvent**: Emitted when parallel delegation to multiple A2A agents completes. Contains the list of endpoints, success count, failure count, and results summary. + +#### Conversation Events + +- **A2AConversationStartedEvent**: Emitted once at the beginning of a multiturn A2A conversation, before the first message exchange. Contains the agent ID, endpoint, context ID, agent card metadata, protocol version, and provider info. +- **A2AMessageSentEvent**: Emitted when a message is sent to the A2A agent. Contains the message content, turn number, context ID, message ID, and whether it's multiturn. +- **A2AResponseReceivedEvent**: Emitted when a response is received from the A2A agent. Contains the response content, turn number, context ID, message ID, status, and whether it's the final response. +- **A2AConversationCompletedEvent**: Emitted once at the end of a multiturn A2A conversation. Contains the final status (`completed` or `failed`), final result, error message, context ID, and total number of turns. + +#### Streaming Events + +- **A2AStreamingStartedEvent**: Emitted when streaming mode begins for A2A delegation. Contains the task ID, context ID, endpoint, turn number, and whether it's multiturn. +- **A2AStreamingChunkEvent**: Emitted when a streaming chunk is received. Contains the chunk text, chunk index, whether it's the final chunk, task ID, context ID, and turn number. + +#### Polling & Push Notification Events + +- **A2APollingStartedEvent**: Emitted when polling mode begins for A2A delegation. Contains the task ID, context ID, polling interval in seconds, and endpoint. +- **A2APollingStatusEvent**: Emitted on each polling iteration. Contains the task ID, context ID, current task state, elapsed seconds, and poll count. +- **A2APushNotificationRegisteredEvent**: Emitted when a push notification callback is registered. Contains the task ID, context ID, callback URL, and endpoint. +- **A2APushNotificationReceivedEvent**: Emitted when a push notification is received from the remote A2A agent. Contains the task ID, context ID, and current state. +- **A2APushNotificationSentEvent**: Emitted when a push notification is sent to a callback URL. Contains the task ID, context ID, callback URL, state, whether delivery succeeded, and optional error message. +- **A2APushNotificationTimeoutEvent**: Emitted when push notification wait times out. Contains the task ID, context ID, and timeout duration in seconds. + +#### Connection & Authentication Events + +- **A2AAgentCardFetchedEvent**: Emitted when an agent card is successfully fetched. Contains the endpoint, agent name, agent card metadata, protocol version, provider info, whether it was cached, and fetch time in milliseconds. +- **A2AAuthenticationFailedEvent**: Emitted when authentication to an A2A agent fails. Contains the endpoint, auth type attempted (e.g., `bearer`, `oauth2`, `api_key`), error message, and HTTP status code. +- **A2AConnectionErrorEvent**: Emitted when a connection error occurs during A2A communication. Contains the endpoint, error message, error type (e.g., `timeout`, `connection_refused`, `dns_error`), HTTP status code, and the operation being attempted. +- **A2ATransportNegotiatedEvent**: Emitted when transport protocol is negotiated with an A2A agent. Contains the negotiated transport, negotiated URL, selection source (`client_preferred`, `server_preferred`, `fallback`), and client/server supported transports. +- **A2AContentTypeNegotiatedEvent**: Emitted when content types are negotiated with an A2A agent. Contains the client/server input/output modes, negotiated input/output modes, and whether negotiation succeeded. + +#### Artifact Events + +- **A2AArtifactReceivedEvent**: Emitted when an artifact is received from a remote A2A agent. Contains the task ID, artifact ID, artifact name, description, MIME type, size in bytes, and whether content should be appended. + +#### Server Task Events + +- **A2AServerTaskStartedEvent**: Emitted when an A2A server task execution starts. Contains the task ID and context ID. +- **A2AServerTaskCompletedEvent**: Emitted when an A2A server task execution completes. Contains the task ID, context ID, and result. +- **A2AServerTaskCanceledEvent**: Emitted when an A2A server task execution is canceled. Contains the task ID and context ID. +- **A2AServerTaskFailedEvent**: Emitted when an A2A server task execution fails. Contains the task ID, context ID, and error message. + +#### Context Lifecycle Events + +- **A2AContextCreatedEvent**: Emitted when an A2A context is created. Contexts group related tasks in a conversation or workflow. Contains the context ID and creation timestamp. +- **A2AContextExpiredEvent**: Emitted when an A2A context expires due to TTL. Contains the context ID, creation timestamp, age in seconds, and task count. +- **A2AContextIdleEvent**: Emitted when an A2A context becomes idle (no activity for the configured threshold). Contains the context ID, idle time in seconds, and task count. +- **A2AContextCompletedEvent**: Emitted when all tasks in an A2A context complete. Contains the context ID, total tasks, and duration in seconds. +- **A2AContextPrunedEvent**: Emitted when an A2A context is pruned (deleted). Contains the context ID, task count, and age in seconds. + +## Event Handler Structure + +Each event handler receives two parameters: + +1. **source**: The object that emitted the event +2. **event**: The event instance, containing event-specific data + +The structure of the event object depends on the event type, but all events inherit from `BaseEvent` and include: + +- **timestamp**: The time when the event was emitted +- **type**: A string identifier for the event type + +Additional fields vary by event type. For example, `CrewKickoffCompletedEvent` includes `crew_name` and `output` fields. + +## Advanced Usage: Scoped Handlers + +For temporary event handling (useful for testing or specific operations), you can use the `scoped_handlers` context manager: + +```python +from crewai.events import crewai_event_bus, CrewKickoffStartedEvent + +with crewai_event_bus.scoped_handlers(): + @crewai_event_bus.on(CrewKickoffStartedEvent) + def temp_handler(source, event): + print("This handler only exists within this context") + + # Do something that emits events + +# Outside the context, the temporary handler is removed +``` + +## Use Cases + +Event listeners can be used for a variety of purposes: + +1. **Logging and Monitoring**: Track the execution of your Crew and log important events +2. **Analytics**: Collect data about your Crew's performance and behavior +3. **Debugging**: Set up temporary listeners to debug specific issues +4. **Integration**: Connect CrewAI with external systems like monitoring platforms, databases, or notification services +5. **Custom Behavior**: Trigger custom actions based on specific events + +## Best Practices + +1. **Keep Handlers Light**: Event handlers should be lightweight and avoid blocking operations +2. **Error Handling**: Include proper error handling in your event handlers to prevent exceptions from affecting the main execution +3. **Cleanup**: If your listener allocates resources, ensure they're properly cleaned up +4. **Selective Listening**: Only listen for events you actually need to handle +5. **Testing**: Test your event listeners in isolation to ensure they behave as expected + +By leveraging CrewAI's event system, you can extend its functionality and integrate it seamlessly with your existing infrastructure. diff --git a/docs/v1.15.13/en/concepts/files.mdx b/docs/v1.15.13/en/concepts/files.mdx new file mode 100644 index 0000000000..af86baabe2 --- /dev/null +++ b/docs/v1.15.13/en/concepts/files.mdx @@ -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. + + +File support requires the optional `crewai-files` package. Install it with: + +```bash +uv add 'crewai[file-processing]' +``` + + + +The file processing API is currently in early access. + + +## 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) | ✓ | | ✓ | | | + + +Google Gemini models support all file types including video (up to 1 hour, 2GB). Use Gemini when you need to process video content. + + + +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. + + +## 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** | ✓ | | ✓ | + + +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. + + +## 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"), + } +) +``` diff --git a/docs/v1.15.13/en/concepts/flows.mdx b/docs/v1.15.13/en/concepts/flows.mdx new file mode 100644 index 0000000000..f4f0a95ff9 --- /dev/null +++ b/docs/v1.15.13/en/concepts/flows.mdx @@ -0,0 +1,1183 @@ +--- +title: Flows +description: Learn how to create and manage AI workflows using CrewAI Flows. +icon: arrow-progress +mode: "wide" +--- + +## Overview + +CrewAI Flows is a powerful feature designed to streamline the creation and management of AI workflows. Flows allow developers to combine and coordinate coding tasks and Crews efficiently, providing a robust framework for building sophisticated AI automations. + +Flows allow you to create structured, event-driven workflows. They provide a seamless way to connect multiple tasks, manage state, and control the flow of execution in your AI applications. With Flows, you can easily design and implement multi-step processes that leverage the full potential of CrewAI's capabilities. + +1. **Simplified Workflow Creation**: Easily chain together multiple Crews and tasks to create complex AI workflows. + +2. **State Management**: Flows make it super easy to manage and share state between different tasks in your workflow. + +3. **Event-Driven Architecture**: Built on an event-driven model, allowing for dynamic and responsive workflows. + +4. **Flexible Control Flow**: Implement conditional logic, loops, and branching within your workflows. + +## Getting Started + +Let's create a simple Flow where you will use OpenAI to generate a random city in one task and then use that city to generate a fun fact in another task. + +```python Code + +from crewai.flow.flow import Flow, listen, start +from dotenv import load_dotenv +from litellm import completion + +load_dotenv() + +class ExampleFlow(Flow): + model = "gpt-4o-mini" + + @start() + def generate_city(self): + print("Starting flow") + # Each flow state automatically gets a unique ID + print(f"Flow State ID: {self.state['id']}") + + response = completion( + model=self.model, + messages=[ + { + "role": "user", + "content": "Return the name of a random city in the world.", + }, + ], + ) + + random_city = response["choices"][0]["message"]["content"] + # Store the city in our state + self.state["city"] = random_city + print(f"Random City: {random_city}") + + return random_city + + @listen(generate_city) + def generate_fun_fact(self, random_city): + response = completion( + model=self.model, + messages=[ + { + "role": "user", + "content": f"Tell me a fun fact about {random_city}", + }, + ], + ) + + fun_fact = response["choices"][0]["message"]["content"] + # Store the fun fact in our state + self.state["fun_fact"] = fun_fact + return fun_fact + + + +flow = ExampleFlow() +flow.plot() +result = flow.kickoff() + +print(f"Generated fun fact: {result}") +``` +![Flow Visual image](/images/crewai-flow-1.png) +In the above example, we have created a simple Flow that generates a random city using OpenAI and then generates a fun fact about that city. The Flow consists of two tasks: `generate_city` and `generate_fun_fact`. The `generate_city` task is the starting point of the Flow, and the `generate_fun_fact` task listens for the output of the `generate_city` task. + +Each Flow instance automatically receives a unique identifier (UUID) in its state, which helps track and manage flow executions. The state can also store additional data (like the generated city and fun fact) that persists throughout the flow's execution. + +When you run the Flow, it will: +1. Generate a unique ID for the flow state +2. Generate a random city and store it in the state +3. Generate a fun fact about that city and store it in the state +4. Print the results to the console + +The state's unique ID and stored data can be useful for tracking flow executions and maintaining context between tasks. + +**Note:** Ensure you have set up your `.env` file to store your `OPENAI_API_KEY`. This key is necessary for authenticating requests to the OpenAI API. + +### @start() + +The `@start()` decorator marks entry points for a Flow. You can: + +- Declare multiple unconditional starts: `@start()` +- Gate a start on a prior method or router label: `@start("method_or_label")` +- Provide a callable condition to control when a start should fire + +All satisfied `@start()` methods will execute (often in parallel) when the Flow begins or resumes. + +### @listen() + +The `@listen()` decorator is used to mark a method as a listener for the output of another task in the Flow. The method decorated with `@listen()` will be executed when the specified task emits an output. The method can access the output of the task it is listening to as an argument. + +#### Usage + +The `@listen()` decorator can be used in several ways: + +1. **Listening to a Method by Name**: You can pass the name of the method you want to listen to as a string. When that method completes, the listener method will be triggered. + + ```python Code + @listen("generate_city") + def generate_fun_fact(self, random_city): + # Implementation + ``` + +2. **Listening to a Method Directly**: You can pass the method itself. When that method completes, the listener method will be triggered. + ```python Code + @listen(generate_city) + def generate_fun_fact(self, random_city): + # Implementation + ``` + +### Flow Output + +Accessing and handling the output of a Flow is essential for integrating your AI workflows into larger applications or systems. CrewAI Flows provide straightforward mechanisms to retrieve the final output, access intermediate results, and manage the overall state of your Flow. + +#### Retrieving the Final Output + +When you run a Flow, the final output is determined by the last method that completes. The `kickoff()` method returns the output of this final method. + +Here's how you can access the final output: + + +```python Code +from crewai.flow.flow import Flow, listen, start + +class OutputExampleFlow(Flow): + @start() + def first_method(self): + return "Output from first_method" + + @listen(first_method) + def second_method(self, first_output): + return f"Second method received: {first_output}" + + +flow = OutputExampleFlow() +flow.plot("my_flow_plot") +final_output = flow.kickoff() + +print("---- Final Output ----") +print(final_output) +``` + +```text Output +---- Final Output ---- +Second method received: Output from first_method +``` + + +![Flow Visual image](/images/crewai-flow-2.png) + +In this example, the `second_method` is the last method to complete, so its output will be the final output of the Flow. +The `kickoff()` method will return the final output, which is then printed to the console. The `plot()` method will generate the HTML file, which will help you understand the flow. + +#### Accessing and Updating State + +In addition to retrieving the final output, you can also access and update the state within your Flow. The state can be used to store and share data between different methods in the Flow. After the Flow has run, you can access the state to retrieve any information that was added or updated during the execution. + +Here's an example of how to update and access the state: + + + +```python Code +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + counter: int = 0 + message: str = "" + +class StateExampleFlow(Flow[ExampleState]): + + @start() + def first_method(self): + self.state.message = "Hello from first_method" + self.state.counter += 1 + + @listen(first_method) + def second_method(self): + self.state.message += " - updated by second_method" + self.state.counter += 1 + return self.state.message + +flow = StateExampleFlow() +flow.plot("my_flow_plot") +final_output = flow.kickoff() +print(f"Final Output: {final_output}") +print("Final State:") +print(flow.state) +``` + +```text Output +Final Output: Hello from first_method - updated by second_method +Final State: +counter=2 message='Hello from first_method - updated by second_method' +``` + + + +![Flow Visual image](/images/crewai-flow-2.png) + +In this example, the state is updated by both `first_method` and `second_method`. +After the Flow has run, you can access the final state to see the updates made by these methods. + +By ensuring that the final method's output is returned and providing access to the state, CrewAI Flows make it easy to integrate the results of your AI workflows into larger applications or systems, +while also maintaining and accessing the state throughout the Flow's execution. + +## Flow Usage Metrics + +After a Flow execution completes, you can access the `usage_metrics` property to view aggregated token usage across **every LLM call** made during the run — including calls from every Crew the Flow orchestrated, calls inside Agent tools, and bare `LLM.call(...)` invocations from Flow methods. This is the SDK-side equivalent of the totals shown in the CrewAI Enterprise UI. + +```python Code +from crewai import LLM +from crewai.flow.flow import Flow, listen, start + +class UsageMetricsFlow(Flow): + @start() + def run_first_crew(self): + self.state.first_result = FirstCrew().crew().kickoff() + + @listen(run_first_crew) + def call_llm_directly(self): + # Bare LLM call — still counted by flow.usage_metrics + llm = LLM(model="openai/gpt-4o-mini") + self.state.summary = llm.call("Summarize the key takeaways.") + + @listen(call_llm_directly) + def run_second_crew(self): + self.state.second_result = SecondCrew().crew().kickoff() + +flow = UsageMetricsFlow() +flow.kickoff() + +print(flow.usage_metrics) +# UsageMetrics(total_tokens=8579, prompt_tokens=6210, completion_tokens=2369, +# cached_prompt_tokens=0, reasoning_tokens=0, +# cache_creation_tokens=0, successful_requests=5) +``` + + + `flow.usage_metrics` is **not** the same as `flow.kickoff().token_usage`. The + latter returns the `CrewOutput.token_usage` of the **last** `@listen` method + that returned a `CrewOutput`, which means it only reflects the final Crew and + ignores prior Crews and bare `LLM.call(...)` invocations entirely. Use + `flow.usage_metrics` whenever you need the **full** token rollup for the Flow + execution. + + +### UsageMetrics field semantics + +The returned [`UsageMetrics`](https://github.com/crewAIInc/crewAI/blob/main/lib/crewai/src/crewai/types/usage_metrics.py) object uses a provider-neutral contract: + +| Field | Meaning | +| --- | --- | +| `total_tokens` | Billed total: `prompt_tokens + completion_tokens` | +| `prompt_tokens` | Full input/prompt tokens billed for the request | +| `completion_tokens` | Output/completion tokens billed for the request | +| `cached_prompt_tokens` | Cache-read subset of prompt tokens (breakdown only) | +| `cache_creation_tokens` | Cache-write subset of prompt tokens (breakdown only, Anthropic) | +| `reasoning_tokens` | Reasoning/thinking subset where the provider reports it separately (breakdown only) | +| `successful_requests` | Number of LLM calls aggregated | + +Breakdown fields such as `cached_prompt_tokens`, `cache_creation_tokens`, and +`reasoning_tokens` are **not** added on top of `total_tokens` — they describe +portions already included in `prompt_tokens` or `completion_tokens`. + +For Anthropic, cache read and cache write counters are folded into `prompt_tokens`, so cached workloads are fully reflected in `total_tokens`. OpenAI-style providers already include cached input inside `prompt_tokens`; CrewAI surfaces the cached portion separately for visibility. + +Each entry in the returned `UsageMetrics` is the sum across all LLM calls made within a single `flow.kickoff()` invocation. Counters reset on the next `kickoff()` call (or on each iteration of `kickoff_for_each`), so successive runs don't double-count. The property is safe to read at any point after `kickoff()` completes; reading it during execution returns the partial total accumulated so far. + +## Flow State Management + +Managing state effectively is crucial for building reliable and maintainable AI workflows. CrewAI Flows provides robust mechanisms for both unstructured and structured state management, +allowing developers to choose the approach that best fits their application's needs. + +### Unstructured State Management + +In unstructured state management, all state is stored in the `state` attribute of the `Flow` class. +This approach offers flexibility, enabling developers to add or modify state attributes on the fly without defining a strict schema. +Even with unstructured states, CrewAI Flows automatically generates and maintains a unique identifier (UUID) for each state instance. + +```python Code +from crewai.flow.flow import Flow, listen, start + +class UnstructuredExampleFlow(Flow): + + @start() + def first_method(self): + # The state automatically includes an 'id' field + print(f"State ID: {self.state['id']}") + self.state['counter'] = 0 + self.state['message'] = "Hello from structured flow" + + @listen(first_method) + def second_method(self): + self.state['counter'] += 1 + self.state['message'] += " - updated" + + @listen(second_method) + def third_method(self): + self.state['counter'] += 1 + self.state['message'] += " - updated again" + + print(f"State after third_method: {self.state}") + + +flow = UnstructuredExampleFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +![Flow Visual image](/images/crewai-flow-3.png) + +**Note:** The `id` field is automatically generated and preserved throughout the flow's execution. You don't need to manage or set it manually, and it will be maintained even when updating the state with new data. + +**Key Points:** + +- **Flexibility:** You can dynamically add attributes to `self.state` without predefined constraints. +- **Simplicity:** Ideal for straightforward workflows where state structure is minimal or varies significantly. + +### Structured State Management + +Structured state management leverages predefined schemas to ensure consistency and type safety across the workflow. +By using models like Pydantic's `BaseModel`, developers can define the exact shape of the state, enabling better validation and auto-completion in development environments. + +Each state in CrewAI Flows automatically receives a unique identifier (UUID) to help track and manage state instances. This ID is automatically generated and managed by the Flow system. + +```python Code +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + + +class ExampleState(BaseModel): + # Note: 'id' field is automatically added to all states + counter: int = 0 + message: str = "" + + +class StructuredExampleFlow(Flow[ExampleState]): + + @start() + def first_method(self): + # Access the auto-generated ID if needed + print(f"State ID: {self.state.id}") + self.state.message = "Hello from structured flow" + + @listen(first_method) + def second_method(self): + self.state.counter += 1 + self.state.message += " - updated" + + @listen(second_method) + def third_method(self): + self.state.counter += 1 + self.state.message += " - updated again" + + print(f"State after third_method: {self.state}") + + +flow = StructuredExampleFlow() +flow.kickoff() +``` + +![Flow Visual image](/images/crewai-flow-3.png) + +**Key Points:** + +- **Defined Schema:** `ExampleState` clearly outlines the state structure, enhancing code readability and maintainability. +- **Type Safety:** Leveraging Pydantic ensures that state attributes adhere to the specified types, reducing runtime errors. +- **Auto-Completion:** IDEs can provide better auto-completion and error checking based on the defined state model. + +### Choosing Between Unstructured and Structured State Management + +- **Use Unstructured State Management when:** + + - The workflow's state is simple or highly dynamic. + - Flexibility is prioritized over strict state definitions. + - Rapid prototyping is required without the overhead of defining schemas. + +- **Use Structured State Management when:** + - The workflow requires a well-defined and consistent state structure. + - Type safety and validation are important for your application's reliability. + - You want to leverage IDE features like auto-completion and type checking for better developer experience. + +By providing both unstructured and structured state management options, CrewAI Flows empowers developers to build AI workflows that are both flexible and robust, catering to a wide range of application requirements. + +## Flow Persistence + +The @persist decorator enables automatic state persistence in CrewAI Flows, allowing you to maintain flow state across restarts or different workflow executions. This decorator can be applied at either the class level or method level, providing flexibility in how you manage state persistence. + +### Class-Level Persistence + +When applied at the class level, the @persist decorator automatically persists all flow method states: + +```python +@persist # Using SQLiteFlowPersistence by default +class MyFlow(Flow[MyState]): + @start() + def initialize_flow(self): + # This method will automatically have its state persisted + self.state.counter = 1 + print("Initialized flow. State ID:", self.state.id) + + @listen(initialize_flow) + def next_step(self): + # The state (including self.state.id) is automatically reloaded + self.state.counter += 1 + print("Flow state is persisted. Counter:", self.state.counter) +``` + +### Method-Level Persistence + +For more granular control, you can apply @persist to specific methods: + +```python +class AnotherFlow(Flow[dict]): + @persist # Persists only this method's state + @start() + def begin(self): + if "runs" not in self.state: + self.state["runs"] = 0 + self.state["runs"] += 1 + print("Method-level persisted runs:", self.state["runs"]) +``` + +### Forking Persisted State + +`@persist` supports two distinct hydration modes on `kickoff` / `kickoff_async`: + +- `kickoff(inputs={"id": })` — **resume**: load the latest snapshot for the supplied UUID and continue writing under the same `flow_uuid`. The history extends. +- `kickoff(restore_from_state_id=)` — **fork**: load the latest snapshot for the supplied UUID, hydrate the new run's state from it, and assign a fresh `state.id` (auto-generated, or `inputs["id"]` if pinned). The new run's `@persist` writes land under the new `state.id`; the source flow's history is preserved. + +```python +from crewai.flow.flow import Flow, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + id: str = "" + counter: int = 0 + +@persist +class CounterFlow(Flow[CounterState]): + @start() + def step(self): + self.state.counter += 1 + print(f"[id={self.state.id}] counter={self.state.counter}") + +# Run 1: fresh state, counter 0 -> 1, persisted under flow_1.state.id +flow_1 = CounterFlow() +flow_1.kickoff() + +# Fork: hydrate from flow_1's latest snapshot, but use a NEW state.id +flow_2 = CounterFlow() +flow_2.kickoff(restore_from_state_id=flow_1.state.id) +# flow_2.state.counter starts at 1 (hydrated), then step() bumps it to 2. +# flow_2.state.id != flow_1.state.id; flow_1's history is unchanged. +``` + +If the supplied `restore_from_state_id` does not match any persisted state, the kickoff falls back silently — same as the existing `inputs["id"]` resume not-found behavior. Combining `restore_from_state_id` with `from_checkpoint` raises a `ValueError`; pick one hydration source. Pinning `inputs["id"]` while forking shares a persistence key with another flow — usually you want only `restore_from_state_id`. + +### How It Works + +1. **Unique State Identification** + - Each flow state automatically receives a unique UUID + - The ID is preserved across state updates and method calls + - Supports both structured (Pydantic BaseModel) and unstructured (dictionary) states + +2. **Default SQLite Backend** + - SQLiteFlowPersistence is the default storage backend + - States are automatically saved to a local SQLite database + - Robust error handling ensures clear messages if database operations fail + +3. **Error Handling** + - Comprehensive error messages for database operations + - Automatic state validation during save and load + - Clear feedback when persistence operations encounter issues + +### Important Considerations + +- **State Types**: Both structured (Pydantic BaseModel) and unstructured (dictionary) states are supported +- **Automatic ID**: The `id` field is automatically added if not present +- **State Recovery**: Failed or restarted flows can automatically reload their previous state +- **Custom Implementation**: You can provide your own FlowPersistence implementation for specialized storage needs + +### Technical Advantages + +1. **Precise Control Through Low-Level Access** + - Direct access to persistence operations for advanced use cases + - Fine-grained control via method-level persistence decorators + - Built-in state inspection and debugging capabilities + - Full visibility into state changes and persistence operations + +2. **Enhanced Reliability** + - Automatic state recovery after system failures or restarts + - Transaction-based state updates for data integrity + - Comprehensive error handling with clear error messages + - Robust validation during state save and load operations + +3. **Extensible Architecture** + - Customizable persistence backend through FlowPersistence interface + - Support for specialized storage solutions beyond SQLite + - Compatible with both structured (Pydantic) and unstructured (dict) states + - Seamless integration with existing CrewAI flow patterns + +The persistence system's architecture emphasizes technical precision and customization options, allowing developers to maintain full control over state management while benefiting from built-in reliability features. + +## Flow Control + +### Conditional Logic: `or` + +The `or_` function in Flows allows you to listen to multiple methods and trigger the listener method when any of the specified methods emit an output. + + + +```python Code +from crewai.flow.flow import Flow, listen, or_, start + +class OrExampleFlow(Flow): + + @start() + def start_method(self): + return "Hello from the start method" + + @listen(start_method) + def second_method(self): + return "Hello from the second method" + + @listen(or_(start_method, second_method)) + def logger(self, result): + print(f"Logger: {result}") + + + +flow = OrExampleFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +```text Output +Logger: Hello from the start method +Logger: Hello from the second method +``` + + + +![Flow Visual image](/images/crewai-flow-4.png) + +When you run this Flow, the `logger` method will be triggered by the output of either the `start_method` or the `second_method`. +The `or_` function is used to listen to multiple methods and trigger the listener method when any of the specified methods emit an output. + +### Conditional Logic: `and` + +The `and_` function in Flows allows you to listen to multiple methods and trigger the listener method only when all the specified methods emit an output. + + + +```python Code +from crewai.flow.flow import Flow, and_, listen, start + +class AndExampleFlow(Flow): + + @start() + def start_method(self): + self.state["greeting"] = "Hello from the start method" + + @listen(start_method) + def second_method(self): + self.state["joke"] = "What do computers eat? Microchips." + + @listen(and_(start_method, second_method)) + def logger(self): + print("---- Logger ----") + print(self.state) + +flow = AndExampleFlow() +flow.plot() +flow.kickoff() +``` + +```text Output +---- Logger ---- +{'greeting': 'Hello from the start method', 'joke': 'What do computers eat? Microchips.'} +``` + + + +![Flow Visual image](/images/crewai-flow-5.png) + +When you run this Flow, the `logger` method will be triggered only when both the `start_method` and the `second_method` emit an output. +The `and_` function is used to listen to multiple methods and trigger the listener method only when all the specified methods emit an output. + +### Router + +The `@router()` decorator in Flows allows you to define conditional routing logic based on the output of a method. +You can specify different routes based on the output of the method, allowing you to control the flow of execution dynamically. + + + +```python Code +import random +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + success_flag: bool = False + +class RouterFlow(Flow[ExampleState]): + + @start() + def start_method(self): + print("Starting the structured flow") + random_boolean = random.choice([True, False]) + self.state.success_flag = random_boolean + + @router(start_method) + def second_method(self): + if self.state.success_flag: + return "success" + else: + return "failed" + + @listen("success") + def third_method(self): + print("Third method running") + + @listen("failed") + def fourth_method(self): + print("Fourth method running") + + +flow = RouterFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +```text Output +Starting the structured flow +Third method running +Fourth method running +``` + + + +![Flow Visual image](/images/crewai-flow-6.png) + +In the above example, the `start_method` generates a random boolean value and sets it in the state. +The `second_method` uses the `@router()` decorator to define conditional routing logic based on the value of the boolean. +If the boolean is `True`, the method returns `"success"`, and if it is `False`, the method returns `"failed"`. +The `third_method` and `fourth_method` listen to the output of the `second_method` and execute based on the returned value. + +When you run this Flow, the output will change based on the random boolean value generated by the `start_method`. + +### Human in the Loop (human feedback) + + +The `@human_feedback` decorator requires **CrewAI version 1.8.0 or higher**. + + +The `@human_feedback` decorator enables human-in-the-loop workflows by pausing flow execution to collect feedback from a human. This is useful for approval gates, quality review, and decision points that require human judgment. + +```python Code +from crewai.flow.flow import Flow, start, listen +from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult + +class ReviewFlow(Flow): + @start() + @human_feedback( + message="Do you approve this content?", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + def generate_content(self): + return "Content to be reviewed..." + + @listen("approved") + def on_approval(self, result: HumanFeedbackResult): + print(f"Approved! Feedback: {result.feedback}") + + @listen("rejected") + def on_rejection(self, result: HumanFeedbackResult): + print(f"Rejected. Reason: {result.feedback}") +``` + +When `emit` is specified, the human's free-form feedback is interpreted by an LLM and collapsed into one of the specified outcomes, which then triggers the corresponding `@listen` decorator. + +You can also use `@human_feedback` without routing to simply collect feedback: + +```python Code +@start() +@human_feedback(message="Any comments on this output?") +def my_method(self): + return "Output for review" + +@listen(my_method) +def next_step(self, result: HumanFeedbackResult): + # Access feedback via result.feedback + # Access original output via result.output + pass +``` + +Access all feedback collected during a flow via `self.last_human_feedback` (most recent) or `self.human_feedback_history` (all feedback as a list). + +For a complete guide on human feedback in flows, including **async/non-blocking feedback** with custom providers (Slack, webhooks, etc.), see [Human Feedback in Flows](/en/learn/human-feedback-in-flows). + +## Adding Agents to Flows + +Agents can be seamlessly integrated into your flows, providing a lightweight alternative to full Crews when you need simpler, focused task execution. Here's an example of how to use an Agent within a flow to perform market research: + +```python +import asyncio +from typing import Any, Dict, List + +from crewai_tools import SerperDevTool +from pydantic import BaseModel, Field + +from crewai.agent import Agent +from crewai.flow.flow import Flow, listen, start + + +# Define a structured output format +class MarketAnalysis(BaseModel): + key_trends: List[str] = Field(description="List of identified market trends") + market_size: str = Field(description="Estimated market size") + competitors: List[str] = Field(description="Major competitors in the space") + + +# Define flow state +class MarketResearchState(BaseModel): + product: str = "" + analysis: MarketAnalysis | None = None + + +# Create a flow class +class MarketResearchFlow(Flow[MarketResearchState]): + @start() + def initialize_research(self) -> Dict[str, Any]: + print(f"Starting market research for {self.state.product}") + return {"product": self.state.product} + + @listen(initialize_research) + async def analyze_market(self) -> Dict[str, Any]: + # Create an Agent for market research + analyst = Agent( + role="Market Research Analyst", + goal=f"Analyze the market for {self.state.product}", + backstory="You are an experienced market analyst with expertise in " + "identifying market trends and opportunities.", + tools=[SerperDevTool()], + verbose=True, + ) + + # Define the research query + query = f""" + Research the market for {self.state.product}. Include: + 1. Key market trends + 2. Market size + 3. Major competitors + + Format your response according to the specified structure. + """ + + # Execute the analysis with structured output format + result = await analyst.kickoff_async(query, response_format=MarketAnalysis) + if result.pydantic: + print("result", result.pydantic) + else: + print("result", result) + + # Return the analysis to update the state + return {"analysis": result.pydantic} + + @listen(analyze_market) + def present_results(self, analysis) -> None: + print("\nMarket Analysis Results") + print("=====================") + + if isinstance(analysis, dict): + # If we got a dict with 'analysis' key, extract the actual analysis object + market_analysis = analysis.get("analysis") + else: + market_analysis = analysis + + if market_analysis and isinstance(market_analysis, MarketAnalysis): + print("\nKey Market Trends:") + for trend in market_analysis.key_trends: + print(f"- {trend}") + + print(f"\nMarket Size: {market_analysis.market_size}") + + print("\nMajor Competitors:") + for competitor in market_analysis.competitors: + print(f"- {competitor}") + else: + print("No structured analysis data available.") + print("Raw analysis:", analysis) + + +# Usage example +async def run_flow(): + flow = MarketResearchFlow() + flow.plot("MarketResearchFlowPlot") + result = await flow.kickoff_async(inputs={"product": "AI-powered chatbots"}) + return result + + +# Run the flow +if __name__ == "__main__": + asyncio.run(run_flow()) +``` + +![Flow Visual image](/images/crewai-flow-7.png) + +This example demonstrates several key features of using Agents in flows: + +1. **Structured Output**: Using Pydantic models to define the expected output format (`MarketAnalysis`) ensures type safety and structured data throughout the flow. + +2. **State Management**: The flow state (`MarketResearchState`) maintains context between steps and stores both inputs and outputs. + +3. **Tool Integration**: Agents can use tools (like `WebsiteSearchTool`) to enhance their capabilities. + +## Adding Crews to Flows + +Creating a flow with multiple crews in CrewAI is straightforward. + +You can generate a new CrewAI project that includes all the scaffolding needed to create a flow with multiple crews by running the following command: + +```bash +crewai create flow name_of_flow +``` + +This command will generate a new CrewAI project with the necessary folder structure. The generated project includes a prebuilt crew called `poem_crew` that is already working. The starter embedded crew uses the classic Python/YAML layout; new standalone crews created with `crewai create crew` use the JSON-first layout. + +### Folder Structure + +After running the `crewai create flow name_of_flow` command, you will see a folder structure similar to the following: + +| Directory/File | Description | +| :--------------------- | :----------------------------------------------------------------- | +| `name_of_flow/` | Root directory for the flow. | +| ├── `crews/` | Contains directories for specific crews. | +| │ └── `poem_crew/` | Directory for the "poem_crew" with its configurations and scripts. | +| │ ├── `config/` | Configuration files directory for the "poem_crew". | +| │ │ ├── `agents.yaml` | YAML file defining the agents for "poem_crew". | +| │ │ └── `tasks.yaml` | YAML file defining the tasks for "poem_crew". | +| │ ├── `poem_crew.py` | Script for "poem_crew" functionality. | +| ├── `tools/` | Directory for additional tools used in the flow. | +| │ └── `custom_tool.py` | Custom tool implementation. | +| ├── `main.py` | Main script for running the flow. | +| ├── `README.md` | Project description and instructions. | +| ├── `pyproject.toml` | Configuration file for project dependencies and settings. | +| └── `.gitignore` | Specifies files and directories to ignore in version control. | + +### Building Your Crews + +In the `crews` folder, you can define multiple crews. The generated `poem_crew` uses the classic embedded-crew structure: + +- `config/agents.yaml`: Defines the agents for the crew. +- `config/tasks.yaml`: Defines the tasks for the crew. +- `poem_crew.py`: Contains the crew definition, including agents, tasks, and the crew itself. + +You can copy, paste, and edit the `poem_crew` to create other classic embedded crews. + +For JSON-first embedded crews, use a folder with `crew.jsonc` and `agents/*.jsonc` instead: + +```text +crews/ +└── research_crew/ + ├── agents/ + │ └── researcher.jsonc + └── crew.jsonc +``` + +Then load it from a Flow step: + +```python +from pathlib import Path +from crewai.project import load_crew + +crew, default_inputs = load_crew( + Path(__file__).parent / "crews" / "research_crew" / "crew.jsonc" +) +result = crew.kickoff(inputs={**default_inputs, "topic": "AI Agents"}) +``` + +### Connecting Crews in `main.py` + +The `main.py` file is where you create your flow and connect the crews together. You can define your flow by using the `Flow` class and the decorators `@start` and `@listen` to specify the flow of execution. + +Here's an example of how you can connect the `poem_crew` in the `main.py` file: + +```python Code +#!/usr/bin/env python +from random import randint + +from pydantic import BaseModel +from crewai.flow.flow import Flow, listen, start +from .crews.poem_crew.poem_crew import PoemCrew + +class PoemState(BaseModel): + sentence_count: int = 1 + poem: str = "" + +class PoemFlow(Flow[PoemState]): + + @start() + def generate_sentence_count(self): + print("Generating sentence count") + self.state.sentence_count = randint(1, 5) + + @listen(generate_sentence_count) + def generate_poem(self): + print("Generating poem") + result = PoemCrew().crew().kickoff(inputs={"sentence_count": self.state.sentence_count}) + + print("Poem generated", result.raw) + self.state.poem = result.raw + + @listen(generate_poem) + def save_poem(self): + print("Saving poem") + with open("poem.txt", "w") as f: + f.write(self.state.poem) + +def kickoff(): + poem_flow = PoemFlow() + poem_flow.kickoff() + + +def plot(): + poem_flow = PoemFlow() + poem_flow.plot("PoemFlowPlot") + +if __name__ == "__main__": + kickoff() + plot() +``` + +In this example, the `PoemFlow` class defines a flow that generates a sentence count, uses the `PoemCrew` to generate a poem, and then saves the poem to a file. The flow is kicked off by calling the `kickoff()` method. The PoemFlowPlot will be generated by `plot()` method. + +![Flow Visual image](/images/crewai-flow-8.png) + +### Running the Flow + +(Optional) Before running the flow, you can install the dependencies by running: + +```bash +crewai install +``` + +Once all of the dependencies are installed, you need to activate the virtual environment by running: + +```bash +source .venv/bin/activate +``` + +After activating the virtual environment, you can run the flow with the CrewAI CLI: + +```bash +crewai run +``` + +You can also run the project script directly: + +```bash +uv run kickoff +``` + +The flow will execute, and you should see the output in the console. + +## Plot Flows + +Visualizing your AI workflows can provide valuable insights into the structure and execution paths of your flows. CrewAI offers a powerful visualization tool that allows you to generate interactive plots of your flows, making it easier to understand and optimize your AI workflows. + +### What are Plots? + +Plots in CrewAI are graphical representations of your AI workflows. They display the various tasks, their connections, and the flow of data between them. This visualization helps in understanding the sequence of operations, identifying bottlenecks, and ensuring that the workflow logic aligns with your expectations. + +### How to Generate a Plot + +CrewAI provides two convenient methods to generate plots of your flows: + +#### Option 1: Using the `plot()` Method + +If you are working directly with a flow instance, you can generate a plot by calling the `plot()` method on your flow object. This method will create an HTML file containing the interactive plot of your flow. + +```python Code +# Assuming you have a flow instance +flow.plot("my_flow_plot") +``` + +This will generate a file named `my_flow_plot.html` in your current directory. You can open this file in a web browser to view the interactive plot. + +#### Option 2: Using the Command Line + +If you are working within a structured CrewAI project, you can generate a plot using the command line. This is particularly useful for larger projects where you want to visualize the entire flow setup. + +```bash +crewai flow plot +``` + +This command will generate an HTML file with the plot of your flow, similar to the `plot()` method. The file will be saved in your project directory, and you can open it in a web browser to explore the flow. + +### Understanding the Plot + +The generated plot will display nodes representing the tasks in your flow, with directed edges indicating the flow of execution. The plot is interactive, allowing you to zoom in and out, and hover over nodes to see additional details. + +By visualizing your flows, you can gain a clearer understanding of the workflow's structure, making it easier to debug, optimize, and communicate your AI processes to others. + +### Conclusion + +Plotting your flows is a powerful feature of CrewAI that enhances your ability to design and manage complex AI workflows. Whether you choose to use the `plot()` method or the command line, generating plots will provide you with a visual representation of your workflows, aiding in both development and presentation. + +## Next Steps + +If you're interested in exploring additional examples of flows, we have a variety of recommendations in our examples repository. Here are four specific flow examples, each showcasing unique use cases to help you match your current problem type to a specific example: + +1. **Email Auto Responder Flow**: This example demonstrates an infinite loop where a background job continually runs to automate email responses. It's a great use case for tasks that need to be performed repeatedly without manual intervention. [View Example](https://github.com/crewAIInc/crewAI-examples/tree/main/email_auto_responder_flow) + +2. **Lead Score Flow**: This flow showcases adding human-in-the-loop feedback and handling different conditional branches using the router. It's an excellent example of how to incorporate dynamic decision-making and human oversight into your workflows. [View Example](https://github.com/crewAIInc/crewAI-examples/tree/main/lead-score-flow) + +3. **Write a Book Flow**: This example excels at chaining multiple crews together, where the output of one crew is used by another. Specifically, one crew outlines an entire book, and another crew generates chapters based on the outline. Eventually, everything is connected to produce a complete book. This flow is perfect for complex, multi-step processes that require coordination between different tasks. [View Example](https://github.com/crewAIInc/crewAI-examples/tree/main/write_a_book_with_flows) + +4. **Meeting Assistant Flow**: This flow demonstrates how to broadcast one event to trigger multiple follow-up actions. For instance, after a meeting is completed, the flow can update a Trello board, send a Slack message, and save the results. It's a great example of handling multiple outcomes from a single event, making it ideal for comprehensive task management and notification systems. [View Example](https://github.com/crewAIInc/crewAI-examples/tree/main/meeting_assistant_flow) + +By exploring these examples, you can gain insights into how to leverage CrewAI Flows for various use cases, from automating repetitive tasks to managing complex, multi-step processes with dynamic decision-making and human feedback. + +Also, check out our YouTube video on how to use flows in CrewAI below! + + + +## Running Flows + +There are two ways to run a flow: + +### Using the Flow API + +You can run a flow programmatically by creating an instance of your flow class and calling the `kickoff()` method: + +```python +flow = ExampleFlow() +result = flow.kickoff() +``` + +### Streaming Flow Execution + +For real-time visibility into flow execution, you can enable streaming to receive output as it's generated: + +```python +class StreamingFlow(Flow): + stream = True # Enable streaming + + @start() + def research(self): + # Your flow implementation + pass + +# Iterate over streaming output +flow = StreamingFlow() +streaming = flow.kickoff() +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# Access final result +result = streaming.result +``` + +Learn more about streaming in the [Streaming Flow Execution](/en/learn/streaming-flow-execution) guide. + +## Memory in Flows + +Every Flow automatically has access to CrewAI's unified [Memory](/concepts/memory) system. You can store, recall, and extract memories directly inside any flow method using three built-in convenience methods. + +### Built-in Methods + +| Method | Description | +| :--- | :--- | +| `self.remember(content, **kwargs)` | Store content in memory. Accepts optional `scope`, `categories`, `metadata`, `importance`. | +| `self.recall(query, **kwargs)` | Retrieve relevant memories. Accepts optional `scope`, `categories`, `limit`, `depth`. | +| `self.extract_memories(content)` | Break raw text into discrete, self-contained memory statements. | + +A default `Memory()` instance is created automatically when the Flow initializes. You can also pass a custom one: + +```python +from crewai.flow.flow import Flow +from crewai import Memory + +custom_memory = Memory( + recency_weight=0.5, + recency_half_life_days=7, + embedder={"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}, +) + +flow = MyFlow(memory=custom_memory) +``` + +### Example: Research and Analyze Flow + +```python +from crewai.flow.flow import Flow, listen, start + + +class ResearchAnalysisFlow(Flow): + @start() + def gather_data(self): + # Simulate research findings + findings = ( + "PostgreSQL handles 10k concurrent connections with connection pooling. " + "MySQL caps at around 5k. MongoDB scales horizontally but adds complexity." + ) + + # Extract atomic facts and remember each one + memories = self.extract_memories(findings) + for mem in memories: + self.remember(mem, scope="/research/databases") + + return findings + + @listen(gather_data) + def analyze(self, raw_findings): + # Recall relevant past research (from this run or previous runs) + past = self.recall("database performance and scaling", limit=10, depth="shallow") + + context_lines = [f"- {m.record.content}" for m in past] + context = "\n".join(context_lines) if context_lines else "No prior context." + + return { + "new_findings": raw_findings, + "prior_context": context, + "total_memories": len(past), + } + + +flow = ResearchAnalysisFlow() +result = flow.kickoff() +print(result) +``` + +Because memory persists across runs (backed by LanceDB on disk), the `analyze` step will recall findings from previous executions too -- enabling flows that learn and accumulate knowledge over time. + +See the [Memory documentation](/concepts/memory) for details on scopes, slices, composite scoring, embedder configuration, and more. + +### Using the CLI + +Starting from version 0.103.0, you can run flows using the `crewai run` command: + +```shell +crewai run +``` + +This command automatically detects if your project is a flow (based on the `type = "flow"` setting in your pyproject.toml) and runs it accordingly. This is the recommended way to run flows from the command line. + +The legacy `crewai flow kickoff` command is deprecated. Use `crewai run` for both crews and flows. diff --git a/docs/v1.15.13/en/concepts/knowledge.mdx b/docs/v1.15.13/en/concepts/knowledge.mdx new file mode 100644 index 0000000000..937cca1fda --- /dev/null +++ b/docs/v1.15.13/en/concepts/knowledge.mdx @@ -0,0 +1,1097 @@ +--- +title: Knowledge +description: What is knowledge in CrewAI and how to use it. +icon: book +mode: "wide" +--- + +## Overview + +Knowledge in CrewAI is a powerful system that allows AI agents to access and utilize external information sources during their tasks. +Think of it as giving your agents a reference library they can consult while working. + + + Key benefits of using Knowledge: + - Enhance agents with domain-specific information + - Support decisions with real-world data + - Maintain context across conversations + - Ground responses in factual information + + +## Quickstart Examples + + +For file-based Knowledge Sources, make sure to place your files in a `knowledge` directory at the root of your project. +Also, use relative paths from the `knowledge` directory when creating the source. + + +### Vector store (RAG) client configuration + +CrewAI exposes a provider-neutral RAG client abstraction for vector stores. The default provider is ChromaDB, and Qdrant is supported as well. You can switch providers using configuration utilities. + +Supported today: +- ChromaDB (default) +- Qdrant + +```python Code +from crewai.rag.config.utils import set_rag_config, get_rag_client, clear_rag_config + +# ChromaDB (default) +from crewai.rag.chromadb.config import ChromaDBConfig +set_rag_config(ChromaDBConfig()) +chromadb_client = get_rag_client() + +# Qdrant +from crewai.rag.qdrant.config import QdrantConfig +set_rag_config(QdrantConfig()) +qdrant_client = get_rag_client() + +# Example operations (same API for any provider) +client = qdrant_client # or chromadb_client +client.create_collection(collection_name="docs") +client.add_documents( + collection_name="docs", + documents=[{"id": "1", "content": "CrewAI enables collaborative AI agents."}], +) +results = client.search(collection_name="docs", query="collaborative agents", limit=3) + +clear_rag_config() # optional reset +``` + +This RAG client is separate from Knowledge’s built-in storage. Use it when you need direct vector-store control or custom retrieval pipelines. + +### Basic String Knowledge Example + +```python Code +from crewai import Agent, Task, Crew, Process, LLM +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create a knowledge source +content = "Users name is John. He is 30 years old and lives in San Francisco." +string_source = StringKnowledgeSource(content=content) + +# Create an LLM with a temperature of 0 to ensure deterministic outputs +llm = LLM(model="gpt-4o-mini", temperature=0) + +# Create an agent with the knowledge store +agent = Agent( + role="About User", + goal="You know everything about the user.", + backstory="You are a master at understanding people and their preferences.", + verbose=True, + allow_delegation=False, + llm=llm, +) + +task = Task( + description="Answer the following questions about the user: {question}", + expected_output="An answer to the question.", + agent=agent, +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True, + process=Process.sequential, + knowledge_sources=[string_source], # Enable knowledge by adding the sources here +) + +result = crew.kickoff(inputs={"question": "What city does John live in and how old is he?"}) +``` + +### Web Content Knowledge Example + + + You need to install `docling` for the following example to work: `uv add docling` + + +```python Code +from crewai import LLM, Agent, Crew, Process, Task +from crewai.knowledge.source.crew_docling_source import CrewDoclingSource + +# Create a knowledge source from web content +content_source = CrewDoclingSource( + file_paths=[ + "https://lilianweng.github.io/posts/2024-11-28-reward-hacking", + "https://lilianweng.github.io/posts/2024-07-07-hallucination", + ], +) + +# Create an LLM with a temperature of 0 to ensure deterministic outputs +llm = LLM(model="gpt-4o-mini", temperature=0) + +# Create an agent with the knowledge store +agent = Agent( + role="About papers", + goal="You know everything about the papers.", + backstory="You are a master at understanding papers and their content.", + verbose=True, + allow_delegation=False, + llm=llm, +) + +task = Task( + description="Answer the following questions about the papers: {question}", + expected_output="An answer to the question.", + agent=agent, +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True, + process=Process.sequential, + knowledge_sources=[content_source], +) + +result = crew.kickoff( + inputs={"question": "What is the reward hacking paper about? Be sure to provide sources."} +) +``` + +## Supported Knowledge Sources + +CrewAI supports various types of knowledge sources out of the box: + + + + - Raw strings + - Text files (.txt) + - PDF documents + + + - CSV files + - Excel spreadsheets + - JSON documents + + + +### Text File Knowledge Source +```python +from crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource + +text_source = TextFileKnowledgeSource( + file_paths=["document.txt", "another.txt"] +) +``` + +### PDF Knowledge Source +```python +from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource + +pdf_source = PDFKnowledgeSource( + file_paths=["document.pdf", "another.pdf"] +) +``` + +### CSV Knowledge Source +```python +from crewai.knowledge.source.csv_knowledge_source import CSVKnowledgeSource + +csv_source = CSVKnowledgeSource( + file_paths=["data.csv"] +) +``` + +### Excel Knowledge Source +```python +from crewai.knowledge.source.excel_knowledge_source import ExcelKnowledgeSource + +excel_source = ExcelKnowledgeSource( + file_paths=["spreadsheet.xlsx"] +) +``` + +### JSON Knowledge Source +```python +from crewai.knowledge.source.json_knowledge_source import JSONKnowledgeSource + +json_source = JSONKnowledgeSource( + file_paths=["data.json"] +) +``` + + + Please ensure that you create the ./knowledge folder. All source files (e.g., .txt, .pdf, .xlsx, .json) should be placed in this folder for centralized management. + + +## Agent vs Crew Knowledge: Complete Guide + + +**Understanding Knowledge Levels**: CrewAI supports knowledge at both agent and crew levels. This section clarifies exactly how each works, when they're initialized, and addresses common misconceptions about dependencies. + + +### How Knowledge Initialization Actually Works + +Here's exactly what happens when you use knowledge: + +#### Agent-Level Knowledge (Independent) +```python +from crewai import Agent, Task, Crew +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Agent with its own knowledge - NO crew knowledge needed +specialist_knowledge = StringKnowledgeSource( + content="Specialized technical information for this agent only" +) + +specialist_agent = Agent( + role="Technical Specialist", + goal="Provide technical expertise", + backstory="Expert in specialized technical domains", + knowledge_sources=[specialist_knowledge] # Agent-specific knowledge +) + +task = Task( + description="Answer technical questions", + agent=specialist_agent, + expected_output="Technical answer" +) + +# No crew-level knowledge required +crew = Crew( + agents=[specialist_agent], + tasks=[task] +) + +result = crew.kickoff() # Agent knowledge works independently +``` + +#### What Happens During `crew.kickoff()` + +When you call `crew.kickoff()`, here's the exact sequence: + +```python +# During kickoff +for agent in self.agents: + agent.crew = self # Agent gets reference to crew + agent.set_knowledge(crew_embedder=self.embedder) # Agent knowledge initialized + agent.create_agent_executor() +``` + +#### Storage Independence + +Each knowledge level uses independent storage collections: + +```python +# Agent knowledge storage +agent_collection_name = agent.role # e.g., "Technical Specialist" + +# Crew knowledge storage +crew_collection_name = "crew" + +# Both stored in same ChromaDB instance but different collections +# Path: ~/.local/share/CrewAI/{project}/knowledge/ +# ├── crew/ # Crew knowledge collection +# ├── Technical Specialist/ # Agent knowledge collection +# └── Another Agent Role/ # Another agent's collection +``` + +### Complete Working Examples + +#### Example 1: Agent-Only Knowledge +```python +from crewai import Agent, Task, Crew +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Agent-specific knowledge +agent_knowledge = StringKnowledgeSource( + content="Agent-specific information that only this agent needs" +) + +agent = Agent( + role="Specialist", + goal="Use specialized knowledge", + backstory="Expert with specific knowledge", + knowledge_sources=[agent_knowledge], + embedder={ # Agent can have its own embedder + "provider": "openai", + "config": {"model": "text-embedding-3-small"} + } +) + +task = Task( + description="Answer using your specialized knowledge", + agent=agent, + expected_output="Answer based on agent knowledge" +) + +# No crew knowledge needed +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() # Works perfectly +``` + +#### Example 2: Both Agent and Crew Knowledge +```python +# Crew-wide knowledge (shared by all agents) +crew_knowledge = StringKnowledgeSource( + content="Company policies and general information for all agents" +) + +# Agent-specific knowledge +specialist_knowledge = StringKnowledgeSource( + content="Technical specifications only the specialist needs" +) + +specialist = Agent( + role="Technical Specialist", + goal="Provide technical expertise", + backstory="Technical expert", + knowledge_sources=[specialist_knowledge] # Agent-specific +) + +generalist = Agent( + role="General Assistant", + goal="Provide general assistance", + backstory="General helper" + # No agent-specific knowledge +) + +crew = Crew( + agents=[specialist, generalist], + tasks=[...], + knowledge_sources=[crew_knowledge] # Crew-wide knowledge +) + +# Result: +# - specialist gets: crew_knowledge + specialist_knowledge +# - generalist gets: crew_knowledge only +``` + +#### Example 3: Multiple Agents with Different Knowledge +```python +# Different knowledge for different agents +sales_knowledge = StringKnowledgeSource(content="Sales procedures and pricing") +tech_knowledge = StringKnowledgeSource(content="Technical documentation") +support_knowledge = StringKnowledgeSource(content="Support procedures") + +sales_agent = Agent( + role="Sales Representative", + knowledge_sources=[sales_knowledge], + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}} +) + +tech_agent = Agent( + role="Technical Expert", + knowledge_sources=[tech_knowledge], + embedder={"provider": "ollama", "config": {"model": "mxbai-embed-large"}} +) + +support_agent = Agent( + role="Support Specialist", + knowledge_sources=[support_knowledge] + # Will use crew embedder as fallback +) + +crew = Crew( + agents=[sales_agent, tech_agent, support_agent], + tasks=[...], + embedder={ # Fallback embedder for agents without their own + "provider": "google-generativeai", + "config": {"model_name": "gemini-embedding-001"} + } +) + +# Each agent gets only their specific knowledge +# Each can use different embedding providers +``` + + +Unlike retrieval from a vector database using a tool, agents preloaded with knowledge will not need a retrieval persona or task. +Simply add the relevant knowledge sources your agent or crew needs to function. + +Knowledge sources can be added at the agent or crew level. +Crew level knowledge sources will be used by **all agents** in the crew. +Agent level knowledge sources will be used by the **specific agent** that is preloaded with the knowledge. + + +## Knowledge Configuration + +You can configure the knowledge configuration for the crew or agent. + +```python Code +from crewai.knowledge.knowledge_config import KnowledgeConfig + +knowledge_config = KnowledgeConfig(results_limit=10, score_threshold=0.5) + +agent = Agent( + ... + knowledge_config=knowledge_config +) +``` + + + `results_limit`: is the number of relevant documents to return. Default is 3. + `score_threshold`: is the minimum score for a document to be considered relevant. Default is 0.35. + + +## Supported Knowledge Parameters + + + List of knowledge sources that provide content to be stored and queried. Can include PDF, CSV, Excel, JSON, text files, or string content. + + + Name of the collection where the knowledge will be stored. Used to identify different sets of knowledge. Defaults to \"knowledge\" if not provided. + + +Custom storage configuration for managing how the knowledge is stored and retrieved. If not provided, a default storage will be created. + + +## Knowledge Storage Transparency + + +**Understanding Knowledge Storage**: CrewAI automatically stores knowledge sources in platform-specific directories using ChromaDB for vector storage. Understanding these locations and defaults helps with production deployments, debugging, and storage management. + + +### Where CrewAI Stores Knowledge Files + +By default, CrewAI uses the same storage system as memory, storing knowledge in platform-specific directories: + +#### Default Storage Locations by Platform + +**macOS:** +``` +~/Library/Application Support/CrewAI/{project_name}/ +└── knowledge/ # Knowledge ChromaDB files + ├── chroma.sqlite3 # ChromaDB metadata + ├── {collection_id}/ # Vector embeddings + └── knowledge_{collection}/ # Named collections +``` + +**Linux:** +``` +~/.local/share/CrewAI/{project_name}/ +└── knowledge/ + ├── chroma.sqlite3 + ├── {collection_id}/ + └── knowledge_{collection}/ +``` + +**Windows:** +``` +C:\Users\{username}\AppData\Local\CrewAI\{project_name}\ +└── knowledge\ + ├── chroma.sqlite3 + ├── {collection_id}\ + └── knowledge_{collection}\ +``` + +### Finding Your Knowledge Storage Location + +To see exactly where CrewAI is storing your knowledge files: + +```python +from crewai.utilities.paths import db_storage_path +import os + +# Get the knowledge storage path +knowledge_path = os.path.join(db_storage_path(), "knowledge") +print(f"Knowledge storage location: {knowledge_path}") + +# List knowledge collections and files +if os.path.exists(knowledge_path): + print("\nKnowledge storage contents:") + for item in os.listdir(knowledge_path): + item_path = os.path.join(knowledge_path, item) + if os.path.isdir(item_path): + print(f"📁 Collection: {item}/") + # Show collection contents + try: + for subitem in os.listdir(item_path): + print(f" └── {subitem}") + except PermissionError: + print(f" └── (permission denied)") + else: + print(f"📄 {item}") +else: + print("No knowledge storage found yet.") +``` + +### Controlling Knowledge Storage Locations + +#### Option 1: Environment Variable (Recommended) +```python +import os +from crewai import Crew + +# Set custom storage location for all CrewAI data +os.environ["CREWAI_STORAGE_DIR"] = "./my_project_storage" + +# All knowledge will now be stored in ./my_project_storage/knowledge/ +crew = Crew( + agents=[...], + tasks=[...], + knowledge_sources=[...] +) +``` + +#### Option 2: Custom Knowledge Storage +```python +from crewai.knowledge.storage.knowledge_storage import KnowledgeStorage +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create custom storage with specific embedder +custom_storage = KnowledgeStorage( + embedder={ + "provider": "ollama", + "config": {"model": "mxbai-embed-large"} + }, + collection_name="my_custom_knowledge" +) + +# Use with knowledge sources +knowledge_source = StringKnowledgeSource( + content="Your knowledge content here" +) +knowledge_source.storage = custom_storage +``` + +#### Option 3: Project-Specific Knowledge Storage +```python +import os +from pathlib import Path + +# Store knowledge in project directory +project_root = Path(__file__).parent +knowledge_dir = project_root / "knowledge_storage" + +os.environ["CREWAI_STORAGE_DIR"] = str(knowledge_dir) + +# Now all knowledge will be stored in your project directory +``` + +### Default Embedding Provider Behavior + + +**Default Embedding Provider**: CrewAI defaults to OpenAI embeddings (`text-embedding-3-small`) for knowledge storage, even when using different LLM providers. You can easily customize this to match your setup. + + +#### Understanding Default Behavior +```python +from crewai import Agent, Crew, LLM +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# When using Claude as your LLM... +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + llm=LLM(provider="anthropic", model="claude-3-sonnet") # Using Claude +) + +# CrewAI will still use OpenAI embeddings by default for knowledge +# This ensures consistency but may not match your LLM provider preference +knowledge_source = StringKnowledgeSource(content="Research data...") + +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source] + # Default: Uses OpenAI embeddings even with Claude LLM +) +``` + +#### Customizing Knowledge Embedding Providers +```python +# Option 1: Use Voyage AI (recommended by Anthropic for Claude users) +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source], + embedder={ + "provider": "voyageai", # Recommended for Claude users + "config": { + "api_key": "your-voyage-api-key", + "model": "voyage-3" # or "voyage-3-large" for best quality + } + } +) + +# Option 2: Use local embeddings (no external API calls) +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source], + embedder={ + "provider": "ollama", + "config": { + "model": "mxbai-embed-large", + "url": "http://localhost:11434/api/embeddings" + } + } +) + +# Option 3: Agent-level embedding customization +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + knowledge_sources=[knowledge_source], + embedder={ + "provider": "google-generativeai", + "config": { + "model_name": "gemini-embedding-001", + "api_key": "your-google-key" + } + } +) +``` + +#### Configuring Azure OpenAI Embeddings + +When using Azure OpenAI embeddings: +1. Make sure you deploy the embedding model in Azure platform first +2. Then you need to use the following configuration: + +```python +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + knowledge_sources=[knowledge_source], + embedder={ + "provider": "azure", + "config": { + "api_key": "your-azure-api-key", + "model": "text-embedding-ada-002", # change to the model you are using and is deployed in Azure + "api_base": "https://your-azure-endpoint.openai.azure.com/", + "api_version": "2024-02-01" + } + } +) +``` + +## Advanced Features + +### Query Rewriting + +CrewAI implements an intelligent query rewriting mechanism to optimize knowledge retrieval. When an agent needs to search through knowledge sources, the raw task prompt is automatically transformed into a more effective search query. + +#### How Query Rewriting Works + +1. When an agent executes a task with knowledge sources available, the `_get_knowledge_search_query` method is triggered +2. The agent's LLM is used to transform the original task prompt into an optimized search query +3. This optimized query is then used to retrieve relevant information from knowledge sources + +#### Benefits of Query Rewriting + + + + By focusing on key concepts and removing irrelevant content, query rewriting helps retrieve more relevant information. + + + The rewritten queries are designed to be more specific and context-aware for vector database retrieval. + + + +#### Example + +```python +# Original task prompt +task_prompt = "Answer the following questions about the user's favorite movies: What movie did John watch last week? Format your answer in JSON." + +# Behind the scenes, this might be rewritten as: +rewritten_query = "What movies did John watch last week?" +``` + +The rewritten query is more focused on the core information need and removes irrelevant instructions about output formatting. + + + This mechanism is fully automatic and requires no configuration from users. The agent's LLM is used to perform the query rewriting, so using a more capable LLM can improve the quality of rewritten queries. + + +### Knowledge Events + +CrewAI emits events during the knowledge retrieval process that you can listen for using the event system. These events allow you to monitor, debug, and analyze how knowledge is being retrieved and used by your agents. + +#### Available Knowledge Events + +- **KnowledgeRetrievalStartedEvent**: Emitted when an agent starts retrieving knowledge from sources +- **KnowledgeRetrievalCompletedEvent**: Emitted when knowledge retrieval is completed, including the query used and the retrieved content +- **KnowledgeQueryStartedEvent**: Emitted when a query to knowledge sources begins +- **KnowledgeQueryCompletedEvent**: Emitted when a query completes successfully +- **KnowledgeQueryFailedEvent**: Emitted when a query to knowledge sources fails +- **KnowledgeSearchQueryFailedEvent**: Emitted when a search query fails + +#### Example: Monitoring Knowledge Retrieval + +```python +from crewai.events import ( + KnowledgeRetrievalStartedEvent, + KnowledgeRetrievalCompletedEvent, + BaseEventListener, +) + +class KnowledgeMonitorListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(KnowledgeRetrievalStartedEvent) + def on_knowledge_retrieval_started(source, event): + print(f"Agent '{event.agent.role}' started retrieving knowledge") + + @crewai_event_bus.on(KnowledgeRetrievalCompletedEvent) + def on_knowledge_retrieval_completed(source, event): + print(f"Agent '{event.agent.role}' completed knowledge retrieval") + print(f"Query: {event.query}") + print(f"Retrieved {len(event.retrieved_knowledge)} knowledge chunks") + +# Create an instance of your listener +knowledge_monitor = KnowledgeMonitorListener() +``` + +For more information on using events, see the [Event Listeners](/en/concepts/event-listener) documentation. + +### Custom Knowledge Sources + +CrewAI allows you to create custom knowledge sources for any type of data by extending the `BaseKnowledgeSource` class. Let's create a practical example that fetches and processes space news articles. + +#### Space News Knowledge Source Example + + + +```python Code +from crewai import Agent, Task, Crew, Process, LLM +from crewai.knowledge.source.base_knowledge_source import BaseKnowledgeSource +import requests +from datetime import datetime +from typing import Dict, Any +from pydantic import BaseModel, Field + +class SpaceNewsKnowledgeSource(BaseKnowledgeSource): + """Knowledge source that fetches data from Space News API.""" + + api_endpoint: str = Field(description="API endpoint URL") + limit: int = Field(default=10, description="Number of articles to fetch") + + def load_content(self) -> Dict[Any, str]: + """Fetch and format space news articles.""" + try: + response = requests.get( + f"{self.api_endpoint}?limit={self.limit}" + ) + response.raise_for_status() + + data = response.json() + articles = data.get('results', []) + + formatted_data = self.validate_content(articles) + return {self.api_endpoint: formatted_data} + except Exception as e: + raise ValueError(f"Failed to fetch space news: {str(e)}") + + def validate_content(self, articles: list) -> str: + """Format articles into readable text.""" + formatted = "Space News Articles:\n\n" + for article in articles: + formatted += f""" + Title: {article['title']} + Published: {article['published_at']} + Summary: {article['summary']} + News Site: {article['news_site']} + URL: {article['url']} + -------------------""" + return formatted + + def add(self) -> None: + """Process and store the articles.""" + content = self.load_content() + for _, text in content.items(): + chunks = self._chunk_text(text) + self.chunks.extend(chunks) + + self._save_documents() + +# Create knowledge source +recent_news = SpaceNewsKnowledgeSource( + api_endpoint="https://api.spaceflightnewsapi.net/v4/articles", + limit=10, +) + +# Create specialized agent +space_analyst = Agent( + role="Space News Analyst", + goal="Answer questions about space news accurately and comprehensively", + backstory="""You are a space industry analyst with expertise in space exploration, + satellite technology, and space industry trends. You excel at answering questions + about space news and providing detailed, accurate information.""", + knowledge_sources=[recent_news], + llm=LLM(model="gpt-4", temperature=0.0) +) + +# Create task that handles user questions +analysis_task = Task( + description="Answer this question about space news: {user_question}", + expected_output="A detailed answer based on the recent space news articles", + agent=space_analyst +) + +# Create and run the crew +crew = Crew( + agents=[space_analyst], + tasks=[analysis_task], + verbose=True, + process=Process.sequential +) + +# Example usage +result = crew.kickoff( + inputs={"user_question": "What are the latest developments in space exploration?"} +) +``` + +```output Output +# Agent: Space News Analyst +## Task: Answer this question about space news: What are the latest developments in space exploration? + + +# Agent: Space News Analyst +## Final Answer: +The latest developments in space exploration, based on recent space news articles, include the following: + +1. SpaceX has received the final regulatory approvals to proceed with the second integrated Starship/Super Heavy launch, scheduled for as soon as the morning of Nov. 17, 2023. This is a significant step in SpaceX's ambitious plans for space exploration and colonization. [Source: SpaceNews](https://spacenews.com/starship-cleared-for-nov-17-launch/) + +2. SpaceX has also informed the US Federal Communications Commission (FCC) that it plans to begin launching its first next-generation Starlink Gen2 satellites. This represents a major upgrade to the Starlink satellite internet service, which aims to provide high-speed internet access worldwide. [Source: Teslarati](https://www.teslarati.com/spacex-first-starlink-gen2-satellite-launch-2022/) + +3. AI startup Synthetaic has raised $15 million in Series B funding. The company uses artificial intelligence to analyze data from space and air sensors, which could have significant applications in space exploration and satellite technology. [Source: SpaceNews](https://spacenews.com/ai-startup-synthetaic-raises-15-million-in-series-b-funding/) + +4. The Space Force has formally established a unit within the U.S. Indo-Pacific Command, marking a permanent presence in the Indo-Pacific region. This could have significant implications for space security and geopolitics. [Source: SpaceNews](https://spacenews.com/space-force-establishes-permanent-presence-in-indo-pacific-region/) + +5. Slingshot Aerospace, a space tracking and data analytics company, is expanding its network of ground-based optical telescopes to increase coverage of low Earth orbit. This could improve our ability to track and analyze objects in low Earth orbit, including satellites and space debris. [Source: SpaceNews](https://spacenews.com/slingshots-space-tracking-network-to-extend-coverage-of-low-earth-orbit/) + +6. The National Natural Science Foundation of China has outlined a five-year project for researchers to study the assembly of ultra-large spacecraft. This could lead to significant advancements in spacecraft technology and space exploration capabilities. [Source: SpaceNews](https://spacenews.com/china-researching-challenges-of-kilometer-scale-ultra-large-spacecraft/) + +7. The Center for AEroSpace Autonomy Research (CAESAR) at Stanford University is focusing on spacecraft autonomy. The center held a kickoff event on May 22, 2024, to highlight the industry, academia, and government collaboration it seeks to foster. This could lead to significant advancements in autonomous spacecraft technology. [Source: SpaceNews](https://spacenews.com/stanford-center-focuses-on-spacecraft-autonomy/) +``` + + + +## Debugging and Troubleshooting + +### Debugging Knowledge Issues + +#### Check Agent Knowledge Initialization +```python +from crewai import Agent, Crew, Task +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +knowledge_source = StringKnowledgeSource(content="Test knowledge") + +agent = Agent( + role="Test Agent", + goal="Test knowledge", + backstory="Testing", + knowledge_sources=[knowledge_source] +) + +crew = Crew(agents=[agent], tasks=[Task(...)]) + +# Before kickoff - knowledge not initialized +print(f"Before kickoff - Agent knowledge: {getattr(agent, 'knowledge', None)}") + +crew.kickoff() + +# After kickoff - knowledge initialized +print(f"After kickoff - Agent knowledge: {agent.knowledge}") +print(f"Agent knowledge collection: {agent.knowledge.storage.collection_name}") +print(f"Number of sources: {len(agent.knowledge.sources)}") +``` + +#### Verify Knowledge Storage Locations +```python +import os +from crewai.utilities.paths import db_storage_path + +# Check storage structure +storage_path = db_storage_path() +knowledge_path = os.path.join(storage_path, "knowledge") + +if os.path.exists(knowledge_path): + print("Knowledge collections found:") + for collection in os.listdir(knowledge_path): + collection_path = os.path.join(knowledge_path, collection) + if os.path.isdir(collection_path): + print(f" - {collection}/") + # Show collection contents + for item in os.listdir(collection_path): + print(f" └── {item}") +``` + +#### Test Knowledge Retrieval +```python +# Test agent knowledge retrieval +if hasattr(agent, 'knowledge') and agent.knowledge: + test_query = ["test query"] + results = agent.knowledge.query(test_query) + print(f"Agent knowledge results: {len(results)} documents found") + + # Test crew knowledge retrieval (if exists) + if hasattr(crew, 'knowledge') and crew.knowledge: + crew_results = crew.query_knowledge(test_query) + print(f"Crew knowledge results: {len(crew_results)} documents found") +``` + +#### Inspect Knowledge Collections +```python +import chromadb +from crewai.utilities.paths import db_storage_path +import os + +# Connect to CrewAI's knowledge ChromaDB +knowledge_path = os.path.join(db_storage_path(), "knowledge") + +if os.path.exists(knowledge_path): + client = chromadb.PersistentClient(path=knowledge_path) + collections = client.list_collections() + + print("Knowledge Collections:") + for collection in collections: + print(f" - {collection.name}: {collection.count()} documents") + + # Sample a few documents to verify content + if collection.count() > 0: + sample = collection.peek(limit=2) + print(f" Sample content: {sample['documents'][0][:100]}...") +else: + print("No knowledge storage found") +``` + +#### Check Knowledge Processing +```python +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create a test knowledge source +test_source = StringKnowledgeSource( + content="Test knowledge content for debugging", + chunk_size=100, # Small chunks for testing + chunk_overlap=20 +) + +# Check chunking behavior +print(f"Original content length: {len(test_source.content)}") +print(f"Chunk size: {test_source.chunk_size}") +print(f"Chunk overlap: {test_source.chunk_overlap}") + +# Process and inspect chunks +test_source.add() +print(f"Number of chunks created: {len(test_source.chunks)}") +for i, chunk in enumerate(test_source.chunks[:3]): # Show first 3 chunks + print(f"Chunk {i+1}: {chunk[:50]}...") +``` + +### Common Knowledge Storage Issues + +**"File not found" errors:** +```python +# Ensure files are in the correct location +from crewai.utilities.constants import KNOWLEDGE_DIRECTORY +import os + +knowledge_dir = KNOWLEDGE_DIRECTORY # Usually "knowledge" +file_path = os.path.join(knowledge_dir, "your_file.pdf") + +if not os.path.exists(file_path): + print(f"File not found: {file_path}") + print(f"Current working directory: {os.getcwd()}") + print(f"Expected knowledge directory: {os.path.abspath(knowledge_dir)}") +``` + +**"Embedding dimension mismatch" errors:** +```python +# This happens when switching embedding providers +# Reset knowledge storage to clear old embeddings +crew.reset_memories(command_type='knowledge') + +# Or use consistent embedding providers +crew = Crew( + agents=[...], + tasks=[...], + knowledge_sources=[...], + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}} +) +``` + +**"ChromaDB permission denied" errors:** +```bash +# Fix storage permissions +chmod -R 755 ~/.local/share/CrewAI/ +``` + +**Knowledge not persisting between runs:** +```python +# Verify storage location consistency +import os +from crewai.utilities.paths import db_storage_path + +print("CREWAI_STORAGE_DIR:", os.getenv("CREWAI_STORAGE_DIR")) +print("Computed storage path:", db_storage_path()) +print("Knowledge path:", os.path.join(db_storage_path(), "knowledge")) +``` + +### Knowledge Reset Commands + +```python +# Reset only agent-specific knowledge +crew.reset_memories(command_type='agent_knowledge') + +# Reset both crew and agent knowledge +crew.reset_memories(command_type='knowledge') + +# CLI commands +# crewai reset-memories --agent-knowledge # Agent knowledge only +# crewai reset-memories --knowledge # All knowledge +``` + +### Clearing Knowledge + +If you need to clear the knowledge stored in CrewAI, you can use the `crewai reset-memories` command with the `--knowledge` option. + +```bash Command +crewai reset-memories --knowledge +``` + +This is useful when you've updated your knowledge sources and want to ensure that the agents are using the most recent information. + +## Best Practices + + + + - Keep chunk sizes appropriate for your content type + - Consider content overlap for context preservation + - Organize related information into separate knowledge sources + + + + - Adjust chunk sizes based on content complexity + - Configure appropriate embedding models + - Consider using local embedding providers for faster processing + + + + - With the typical file structure provided by CrewAI, knowledge sources are embedded every time the kickoff is triggered. + - If the knowledge sources are large, this leads to inefficiency and increased latency, as the same data is embedded each time. + - To resolve this, directly initialize the knowledge parameter instead of the knowledge_sources parameter. + - Link to the issue to get complete idea [Github Issue](https://github.com/crewAIInc/crewAI/issues/2755) + + + + - Use agent-level knowledge for role-specific information + - Use crew-level knowledge for shared information all agents need + - Set embedders at agent level if you need different embedding strategies + - Use consistent collection naming by keeping agent roles descriptive + - Test knowledge initialization by checking agent.knowledge after kickoff + - Monitor storage locations to understand where knowledge is stored + - Reset knowledge appropriately using the correct command types + + + + - Set `CREWAI_STORAGE_DIR` to a known location in production + - Choose explicit embedding providers to match your LLM setup and avoid API key conflicts + - Monitor knowledge storage size as it grows with document additions + - Organize knowledge sources by domain or purpose using collection names + - Include knowledge directories in your backup and deployment strategies + - Set appropriate file permissions for knowledge files and storage directories + - Use environment variables for API keys and sensitive configuration + + + + diff --git a/docs/v1.15.13/en/concepts/llms.mdx b/docs/v1.15.13/en/concepts/llms.mdx new file mode 100644 index 0000000000..02fb973140 --- /dev/null +++ b/docs/v1.15.13/en/concepts/llms.mdx @@ -0,0 +1,1500 @@ +--- +title: 'LLMs' +description: 'A comprehensive guide to configuring and using Large Language Models (LLMs) in your CrewAI projects' +icon: 'microchip-ai' +mode: "wide" +--- + +## Overview + +CrewAI integrates with multiple LLM providers through providers native sdks, giving you the flexibility to choose the right model for your specific use case. This guide will help you understand how to configure and use different LLM providers in your CrewAI projects. + + +## What are LLMs? + +Large Language Models (LLMs) are the core intelligence behind CrewAI agents. They enable agents to understand context, make decisions, and generate human-like responses. Here's what you need to know: + + + + Large Language Models are AI systems trained on vast amounts of text data. They power the intelligence of your CrewAI agents, enabling them to understand and generate human-like text. + + + The context window determines how much text an LLM can process at once. Larger windows (e.g., 128K tokens) allow for more context but may be more expensive and slower. + + + Temperature is a sampling control supported by some models. Lower values + generally make sampling more focused, while higher values increase + variability. Some newer reasoning models ignore, deprecate, or reject this + parameter, so check the selected model's documentation before setting it. + + + Each LLM provider (e.g., OpenAI, Anthropic, Google) offers different models with varying capabilities, pricing, and features. Choose based on your needs for accuracy, speed, and cost. + + + +## Setting up your LLM + +There are different places in CrewAI code where you can specify the model to use. Once you specify the model you are using, you will need to provide the configuration (like an API key) for each of the model providers you use. See the [provider configuration examples](#provider-configuration-examples) section for your provider. + + + + The simplest way to get started. Set the model in your environment directly, through an `.env` file or in your app code. If you used `crewai create` to bootstrap your project, it will be set already. + + ```bash .env + MODEL=provider/model-id # e.g. openai/gpt-5.6-terra + + # Be sure to set your API keys here too. See the Provider + # section below. + ``` + + + Never commit API keys to version control. Use environment files (.env) or your system's secret management. + + + + Create a YAML file to define your agent configurations. This method is great for version control and team collaboration: + + ```yaml agents.yaml {6} + researcher: + role: Research Specialist + goal: Conduct comprehensive research and analysis + backstory: A dedicated research professional with years of experience + verbose: true + llm: provider/model-id # e.g. anthropic/claude-sonnet-4-6 + # (see provider configuration examples below for more) + ``` + + + The YAML configuration allows you to: + - Version control your agent settings + - Easily switch between different models + - Share configurations across team members + - Document model choices and their purposes + + + + For maximum flexibility, configure LLMs directly in your Python code: + + ```python {4,8} + from crewai import LLM + + # Basic configuration + llm = LLM(model="provider/model-id") # e.g. gemini/gemini-3.6-flash + + # Advanced configuration with detailed parameters + llm = LLM( + model="provider/model-id", + timeout=120, + max_tokens=4000, + response_format={"type": "json"}, # For structured outputs + ) + ``` + + + Parameter explanations: + - `timeout`: Maximum wait time for response + - `max_tokens`: Limits response length + - `response_format`: Specifies output structure + + Sampling controls such as `temperature` and `top_p`, penalty parameters, + token-limit names, and reasoning controls are model-specific. Add them + only when the selected provider and model support them. See the provider + examples below and the provider's model documentation. + + + + + + CrewAI provides native SDK integrations for OpenAI, Anthropic, Google (Gemini API), Azure, AWS Bedrock, and Snowflake Cortex — no extra install needed beyond the provider-specific extras (e.g. `uv add "crewai[openai]"`). + + All other providers are powered by **LiteLLM**. If you plan to use any of them, add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + +## Provider Configuration Examples + +CrewAI supports a multitude of LLM providers, each offering unique features, authentication methods, and model capabilities. +In this section, you'll find detailed examples that help you select, configure, and optimize the LLM that best fits your project's needs. + + + Model availability changes frequently and can vary by account, region, and + cloud platform. The examples below use models that are current at the time of + writing, but they are not exhaustive support lists. Before deploying, verify + the model ID and lifecycle status in the provider's linked model catalog. + + + + + CrewAI provides native integration with OpenAI through the OpenAI Python SDK. + + ```toml Code + # Required + OPENAI_API_KEY=sk-... + + # Optional + OPENAI_BASE_URL= + ``` + + **Basic Usage:** + ```python Code + from crewai import LLM + + llm = LLM( + model="openai/gpt-5.6-terra", + api_key="your-api-key", # Or set OPENAI_API_KEY + reasoning_effort="medium", + max_completion_tokens=4000 + ) + ``` + + **Custom OpenAI-Compatible Endpoint:** + ```python Code + from crewai import LLM + + llm = LLM( + model="anthropic/claude-sonnet-4-6", + custom_openai=True, + base_url="https://your-gateway.example.com/v1", + api_key="your-gateway-api-key", + ) + ``` + + **Advanced Configuration:** + ```python Code + from crewai import LLM + + llm = LLM( + model="openai/gpt-5.6-terra", + api_key="your-api-key", + base_url="https://api.openai.com/v1", # Optional custom endpoint + organization="org-...", # Optional organization ID + project="proj_...", # Optional project ID + max_completion_tokens=4000, + reasoning_effort="medium", + stream=True, # Enable streaming + timeout=60.0, # Request timeout in seconds + max_retries=3 # Maximum retry attempts + ) + ``` + + **Structured Outputs:** + ```python Code + from pydantic import BaseModel + from crewai import LLM + + class ResponseFormat(BaseModel): + name: str + age: int + summary: str + + llm = LLM( + model="openai/gpt-5.6-terra", + ) + ``` + + **Supported Environment Variables:** + - `OPENAI_API_KEY`: Your OpenAI API key (required) + - `OPENAI_BASE_URL`: Custom base URL for OpenAI API (optional) + + **Features:** + - Native function calling support + - Structured outputs with JSON schema + - Streaming support for real-time responses + - Token usage tracking + - Provider-specific generation controls + - Log probabilities for token-level insights + - Reasoning effort control for supported models + + OpenAI regularly adds models and retires older snapshots. See the + [OpenAI model catalog](https://developers.openai.com/api/docs/models) for + current model IDs, context windows, endpoint compatibility, and lifecycle + information. + + **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 + + + 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). + + + **Note:** To use OpenAI, install the required dependencies: + ```bash + uv add "crewai[openai]" + ``` + + + + Meta's Llama API provides access to Meta's family of large language models. + The API is available through the [Meta Llama API](https://llama.developer.meta.com?utm_source=partner-crewai&utm_medium=website). + Set the following environment variables in your `.env` file: + + ```toml Code + # Meta Llama API Key Configuration + LLAMA_API_KEY=LLM|your_api_key_here + ``` + + Example usage in your CrewAI project: + ```python Code + from crewai import LLM + + # Initialize Meta Llama LLM + llm = LLM( + model="meta_llama/Llama-4-Scout-17B-16E-Instruct-FP8", + temperature=0.8, + stop=["END"], + seed=42 + ) + ``` + + See the [Meta Llama model overview](https://ai.meta.com/llama/get-started/) + for current model families, modalities, and context guidance. + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + CrewAI provides native integration with the Snowflake Cortex REST API through its OpenAI-compatible Chat Completions endpoint. This avoids LiteLLM fallback for `snowflake/...` models. Snowflake Cortex currently supports Chat Completions only in CrewAI, so use the default `api` mode and do not set `api="responses"`. + + ```toml Code + # Required + SNOWFLAKE_PAT= + SNOWFLAKE_ACCOUNT_URL=https://.snowflakecomputing.com + + # Alternative account configuration + SNOWFLAKE_ACCOUNT= + ``` + + **Basic Usage:** + ```python Code + from crewai import LLM + + llm = LLM( + model="snowflake/openai-gpt-4.1", + temperature=0.7, + max_completion_tokens=1024, + ) + ``` + + **Claude Models on Cortex:** + ```python Code + from crewai import LLM + + llm = LLM( + model="snowflake/claude-sonnet-4-5", + max_completion_tokens=1024, + stream=True, + ) + ``` + + **Supported Environment Variables:** + - `SNOWFLAKE_PAT`, `SNOWFLAKE_TOKEN`, or `SNOWFLAKE_JWT`: token used as the Bearer credential + - `SNOWFLAKE_ACCOUNT_URL`: full Snowflake account URL + - `SNOWFLAKE_ACCOUNT`, `SNOWFLAKE_ACCOUNT_ID`, or `SNOWFLAKE_ACCOUNT_IDENTIFIER`: account identifier used to build the account URL + + Snowflake REST requests use the user's default Snowflake role. Make sure that role has `SNOWFLAKE.CORTEX_USER` or `SNOWFLAKE.CORTEX_REST_API_USER`. Database, schema, warehouse, and explicit role parameters are not required by the Cortex REST Chat Completions endpoint. + + **Features:** + - Native provider selection with `model="snowflake/"` + - Streaming and non-streaming Chat Completions only; `api="responses"` is not supported + - Token usage tracking + - Function calling for Snowflake-hosted OpenAI and Claude models + - Automatic removal of invalid trailing assistant prefill for Snowflake Claude models + + + + CrewAI provides native integration with Anthropic through the Anthropic Python SDK. + + ```toml Code + # Required + ANTHROPIC_API_KEY=sk-ant-... + ``` + + **Basic Usage:** + ```python Code + from crewai import LLM + + llm = LLM( + model="anthropic/claude-sonnet-4-6", + api_key="your-api-key", # Or set ANTHROPIC_API_KEY + max_tokens=4096 # Required for Anthropic + ) + ``` + + **Advanced Configuration:** + ```python Code + from crewai import LLM + + llm = LLM( + model="anthropic/claude-sonnet-4-6", + api_key="your-api-key", + base_url="https://api.anthropic.com", # Optional custom endpoint + max_tokens=4096, # Required parameter + stop_sequences=["END", "STOP"], # Anthropic uses stop_sequences + stream=True, # Enable streaming + timeout=60.0, # Request timeout in seconds + max_retries=3 # Maximum retry attempts + ) + ``` + + **Extended Thinking:** + + CrewAI supports Anthropic's Extended Thinking feature, which allows Claude to think through problems in a more human-like way before responding. This is particularly useful for complex reasoning, analysis, and problem-solving tasks. + + ```python Code + from crewai import LLM + + # Enable extended thinking with default settings + llm = LLM( + model="anthropic/claude-sonnet-4-6", + thinking={"type": "enabled"}, + max_tokens=10000 + ) + + # Configure thinking with budget control + llm = LLM( + model="anthropic/claude-sonnet-4-6", + thinking={ + "type": "enabled", + "budget_tokens": 5000 # Limit thinking tokens + }, + max_tokens=10000 + ) + ``` + + **Thinking Configuration Options:** + - `type`: Set to `"enabled"` to activate extended thinking mode + - `budget_tokens` (optional): Maximum tokens to use for thinking (helps control costs) + + Thinking modes and accepted parameters vary across Claude generations. + Check the selected model's capabilities before enabling `thinking`. + + **When to Use Extended Thinking:** + - Complex reasoning and multi-step problem solving + - Mathematical calculations and proofs + - Code analysis and debugging + - Strategic planning and decision making + - Research and analytical tasks + + **Note:** Extended thinking consumes additional tokens but can significantly improve response quality for complex tasks. + + **Supported Environment Variables:** + - `ANTHROPIC_API_KEY`: Your Anthropic API key (required) + + **Features:** + - Native tool use support for Claude 3+ models + - Extended Thinking support for compatible Claude models + - Streaming support for real-time responses + - Automatic system message handling + - Stop sequences for controlled output + - Token usage tracking + - Multi-turn tool use conversations + + **Token usage and prompt caching:** + + Anthropic reports billed input in separate counters — `input_tokens` (uncached), + `cache_read_input_tokens`, and `cache_creation_input_tokens`. CrewAI folds all + three into `prompt_tokens` (and native `input_tokens` in provider responses) so + `total_tokens` reflects full billed usage on cached workloads. + + `cached_prompt_tokens` records the cache-read portion as a breakdown only; it is + already included in `prompt_tokens` and must not be added again to + `total_tokens`. `cache_creation_tokens` records cache writes the same way. + + ```python Code + usage = llm.get_token_usage_summary() + # total_tokens == prompt_tokens + completion_tokens + # prompt_tokens includes cache read + cache write for Anthropic + ``` + + See the **UsageMetrics field semantics** section in the Flows concept + documentation for the provider-neutral contract used by `crew.usage_metrics` + and `flow.usage_metrics`. + + **Important Notes:** + - `max_tokens` is a **required** parameter for all Anthropic models + - Claude uses `stop_sequences` instead of `stop` + - System messages are handled separately from conversation messages + - First message must be from the user (automatically handled) + - Messages must alternate between user and assistant + + See Anthropic's [models overview](https://platform.claude.com/docs/en/about-claude/models/overview) + for current model IDs and capabilities, and review the + [model deprecation table](https://platform.claude.com/docs/en/about-claude/model-deprecations) + before pinning a model in production. + + **Note:** To use Anthropic, install the required dependencies: + ```bash + uv add "crewai[anthropic]" + ``` + + + + CrewAI provides native integration with Google Gemini through the Google Gen AI Python SDK. + + Set your API key in your `.env` file. If you need a key, check [AI Studio](https://aistudio.google.com/apikey). + + ```toml .env + # Required (one of the following) + GOOGLE_API_KEY= + GEMINI_API_KEY= + + # For Vertex AI Express mode (API key authentication) + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_API_KEY= + + # For Vertex AI with service account + GOOGLE_CLOUD_PROJECT= + GOOGLE_CLOUD_LOCATION= # Defaults to us-central1 + ``` + + **Basic Usage:** + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash", + api_key="your-api-key", # Or set GOOGLE_API_KEY/GEMINI_API_KEY + ) + ``` + + **Advanced Configuration:** + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash", + api_key="your-api-key", + max_output_tokens=8192, + stop_sequences=["END", "STOP"], + stream=True, # Enable streaming + safety_settings={ + "HARM_CATEGORY_HARASSMENT": "BLOCK_NONE", + "HARM_CATEGORY_HATE_SPEECH": "BLOCK_NONE" + } + ) + ``` + + **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= + ``` + + Then use the LLM as usual: + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash" + ) + ``` + + + 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). + + + **Vertex AI Configuration (Service Account):** + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash", + project="your-gcp-project-id", + location="us-central1" # GCP region + ) + ``` + + **Supported Environment Variables:** + - `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`) + + **Features:** + - Native function calling support for compatible Gemini models + - Streaming support for real-time responses + - Multimodal capabilities (text, images, video) + - Safety settings configuration + - Support for both Gemini API and Vertex AI + - Automatic system instruction handling + - Token usage tracking + + Google publishes current Gemini IDs, capabilities, and lifecycle stages in + the [Gemini model catalog](https://ai.google.dev/gemini-api/docs/models). + Check the [deprecation schedule](https://ai.google.dev/gemini-api/docs/deprecations) + before choosing a stable or preview model. The Gemini API also hosts + [Gemma models](https://ai.google.dev/gemma/docs). + + **Note:** To use Google Gemini, install the required dependencies: + ```bash + uv add "crewai[google-genai]" + ``` + + + + Authenticate with [Application Default Credentials](https://cloud.google.com/docs/authentication/provide-credentials-adc), then configure the native Gemini provider for Vertex AI: + ```toml .env + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_CLOUD_PROJECT= + GOOGLE_CLOUD_LOCATION= + ``` + + Example usage in your CrewAI project: + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash" + ) + ``` + + Vertex AI availability varies by region. Use the + [Vertex AI model catalog](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models) + to verify the model ID and location before deployment. + + **Note:** This route uses CrewAI's native Gemini integration. Add it as a dependency to your project: + ```bash + uv add "crewai[google-genai]" + ``` + + + + CrewAI provides native integration with Azure AI Inference and Azure OpenAI through the Azure AI Inference Python SDK. + + ```toml Code + # Required + AZURE_API_KEY= + AZURE_ENDPOINT= + + # Optional + AZURE_API_VERSION= # Defaults to 2024-06-01 + ``` + + **Endpoint URL Formats:** + + For Azure OpenAI deployments: + ``` + https://.openai.azure.com/openai/deployments/ + ``` + + For Azure AI Inference endpoints: + ``` + https://.inference.azure.com + ``` + + **Basic Usage:** + ```python Code + llm = LLM( + model="azure/gpt-4", + api_key="", # Or set AZURE_API_KEY + endpoint="", + api_version="2024-06-01" + ) + ``` + + **Advanced Configuration:** + ```python Code + llm = LLM( + model="azure/gpt-4o", + temperature=0.7, + max_tokens=4000, + top_p=0.9, + frequency_penalty=0.0, + presence_penalty=0.0, + stop=["END"], + stream=True, + timeout=60.0, + max_retries=3 + ) + ``` + + **Supported Environment Variables:** + - `AZURE_API_KEY`: Your Azure API key (required) + - `AZURE_ENDPOINT`: Your Azure endpoint URL (required, also checks `AZURE_OPENAI_ENDPOINT` and `AZURE_API_BASE`) + - `AZURE_API_VERSION`: API version (optional, defaults to `2024-06-01`) + + **Features:** + - Native function calling support for Azure OpenAI models (gpt-4, gpt-4o, gpt-3.5-turbo, etc.) + - Streaming support for real-time responses + - Automatic endpoint URL validation and correction + - Comprehensive error handling with retry logic + - Token usage tracking + + **Note:** To use Azure AI Inference, install the required dependencies: + ```bash + uv add "crewai[azure-ai-inference]" + ``` + + + + CrewAI provides native integration with AWS Bedrock through the boto3 SDK using the Converse API. + + ```toml Code + # Required + AWS_ACCESS_KEY_ID= + AWS_SECRET_ACCESS_KEY= + + # Optional + AWS_SESSION_TOKEN= # For temporary credentials + AWS_DEFAULT_REGION= # Defaults to us-east-1 + AWS_REGION_NAME= # Alternative configuration for backwards compatibility with LiteLLM. Defaults to us-east-1 + ``` + + **Basic Usage:** + ```python Code + from crewai import LLM + + llm = LLM( + model="bedrock/us.anthropic.claude-sonnet-4-6", + region_name="us-east-1" + ) + ``` + + **Advanced Configuration:** + ```python Code + from crewai import LLM + + llm = LLM( + model="bedrock/us.anthropic.claude-sonnet-4-6", + aws_access_key_id="your-access-key", # Or set AWS_ACCESS_KEY_ID + aws_secret_access_key="your-secret-key", # Or set AWS_SECRET_ACCESS_KEY + aws_session_token="your-session-token", # For temporary credentials + region_name="us-east-1", + temperature=0.7, + max_tokens=4096, + top_p=0.9, + top_k=250, # For Claude models + stop_sequences=["END", "STOP"], + stream=True, # Enable streaming + guardrail_config={ # Optional content filtering + "guardrailIdentifier": "your-guardrail-id", + "guardrailVersion": "1" + }, + additional_model_request_fields={ # Model-specific parameters + "top_k": 250 + } + ) + ``` + + **Supported Environment Variables:** + - `AWS_ACCESS_KEY_ID`: AWS access key (required) + - `AWS_SECRET_ACCESS_KEY`: AWS secret key (required) + - `AWS_SESSION_TOKEN`: AWS session token for temporary credentials (optional) + - `AWS_DEFAULT_REGION`: AWS region (defaults to `us-east-1`) + - `AWS_REGION_NAME`: AWS region (defaults to `us-east-1`). Alternative configuration for backwards compatibility with LiteLLM + + **Features:** + - Native tool calling support via Converse API + - Streaming and non-streaming responses + - Comprehensive error handling with retry logic + - Guardrail configuration for content filtering + - Model-specific parameters via `additional_model_request_fields` + - Token usage tracking and stop reason logging + - Support for all Bedrock foundation models + - Automatic conversation format handling + + **Important Notes:** + - Uses the modern Converse API for unified model access + - Automatic handling of model-specific conversation requirements + - System messages are handled separately from conversation + - First message must be from user (automatically handled) + - Some models (like Cohere) require conversation to end with user message + + Amazon Bedrock model access and IDs vary by region. Use AWS's + [supported models and regions](https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html) + reference to select a model and verify Converse API support. + **Note:** To use AWS Bedrock, install the required dependencies: + ```bash + uv add "crewai[bedrock]" + ``` + + + + ```toml Code + AWS_ACCESS_KEY_ID= + AWS_SECRET_ACCESS_KEY= + AWS_DEFAULT_REGION= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="sagemaker/" + ) + ``` + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + MISTRAL_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="mistral/mistral-large-latest", + temperature=0.7 + ) + ``` + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + NVIDIA_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="nvidia_nim/nvidia/nvidia-nemotron-3-ultra-550b-a55b", + temperature=0.7 + ) + ``` + + NVIDIA NIM's hosted catalog changes frequently. Use the + [NVIDIA NIM model catalog](https://build.nvidia.com/models) to select a + current endpoint and verify its model ID, modalities, and context limits. + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + NVIDIA Nemotron models are designed for demanding agentic workloads, including complex reasoning, long-context analysis, tool use, multilingual tasks, and high-stakes RAG. + + The `NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4` model is a frontier-scale open-weight model from NVIDIA with 550B total parameters and 55B active parameters. It uses a LatentMoE architecture that combines Mamba-2, MoE, Attention, and Multi-Token Prediction (MTP), and supports context lengths up to 1M tokens. + + + `NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4` is a very large model. NVIDIA lists minimum serving requirements of 4x GB200, 4x B200, 4x GB300, 4x B300, or 8x H100 GPUs. For most CrewAI users, the recommended path is to use NVIDIA NIM or another OpenAI-compatible hosted endpoint rather than running it locally. + + + **Hosted NVIDIA NIM usage:** + ```toml Code + NVIDIA_API_KEY= + ``` + + ```python Code + from crewai import LLM + + llm = LLM( + model="nvidia_nim/nvidia/nvidia-nemotron-3-ultra-550b-a55b", + temperature=0.2, + max_tokens=4096, + ) + ``` + + **Self-hosted OpenAI-compatible endpoint:** + ```python Code + from crewai import LLM + + llm = LLM( + model="openai/nvidia-nemotron-3-ultra-550b-a55b-nvfp4", + base_url="https://your-nemotron-endpoint.example.com/v1", + api_key="your-api-key", + temperature=0.2, + max_tokens=4096, + ) + ``` + + **Model details:** + + | Model | Context Window | Best For | + |-------|----------------|----------| + | `nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4` | Up to 1M tokens | Frontier reasoning, complex agentic workflows, long-context analysis, tool use, multilingual reasoning, and high-stakes RAG | + + **Supported languages:** English, French, Spanish, Italian, German, Japanese, Korean, Hindi, Brazilian Portuguese, and Chinese. + + **Reasoning mode:** Nemotron 3 Ultra supports configurable reasoning via its chat template using `enable_thinking=True` or `enable_thinking=False`. If you are using a hosted endpoint, check your provider's documentation for how that flag is exposed. + + For model details, license, and deployment guidance, see the [NVIDIA Nemotron 3 Ultra model card](https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B-NVFP4). + + **Note:** Hosted NVIDIA NIM usage uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + + NVIDIA NIM enables you to run powerful LLMs locally on your Windows machine using WSL2 (Windows Subsystem for Linux). + This approach allows you to leverage your NVIDIA GPU for private, secure, and cost-effective AI inference without relying on cloud services. + Perfect for development, testing, or production scenarios where data privacy or offline capabilities are required. + + Here is a step-by-step guide to setting up a local NVIDIA NIM model: + + 1. Follow installation instructions from [NVIDIA Website](https://docs.nvidia.com/nim/wsl2/latest/getting-started.html) + + 2. Install the local model. For Llama 3.1-8b follow [instructions](https://build.nvidia.com/meta/llama-3_1-8b-instruct/deploy) + + 3. Configure your crewai local models: + + ```python Code + from crewai.llm import LLM + + local_nvidia_nim_llm = LLM( + model="openai/meta/llama-3.1-8b-instruct", # it's an openai-api compatible model + base_url="http://localhost:8000/v1", + api_key="", # api_key is required, but you can use any text + ) + + # Then you can use it in your crew: + + @CrewBase + class MyCrew(): + # ... + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], # type: ignore[index] + llm=local_nvidia_nim_llm + ) + + # ... + ``` + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + + ```toml Code + GROQ_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="groq/qwen/qwen3.6-27b", + temperature=0.7 + ) + ``` + + Groq distinguishes production and preview models and retires model IDs + regularly. Check the [Groq model catalog](https://console.groq.com/docs/models) + and [deprecation page](https://console.groq.com/docs/deprecations) before + selecting a model for production. + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + # Required + WATSONX_URL= + WATSONX_APIKEY= + WATSONX_PROJECT_ID= + + # Optional + WATSONX_TOKEN= + WATSONX_DEPLOYMENT_SPACE_ID= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="watsonx/meta-llama/llama-3-1-70b-instruct", + base_url="https://api.watsonx.ai/v1" + ) + ``` + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + 1. Install Ollama: [ollama.ai](https://ollama.ai/) + 2. Run a model: `ollama run llama3` + 3. Configure: + + ```python Code + llm = LLM( + model="ollama/llama3:70b", + base_url="http://localhost:11434" + ) + ``` + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + FIREWORKS_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="fireworks_ai/accounts/fireworks/models/llama-v3-70b-instruct", + temperature=0.7 + ) + ``` + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + PERPLEXITY_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="perplexity/sonar-pro" + ) + ``` + + See the [Perplexity model catalog](https://docs.perplexity.ai/getting-started/models) + and [changelog](https://docs.perplexity.ai/docs/resources/changelog) for + current model IDs and deprecation notices. + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + HF_TOKEN= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct" + ) + ``` + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + + ```toml Code + SAMBANOVA_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="sambanova/Meta-Llama-3.3-70B-Instruct", + temperature=0.7 + ) + ``` + SambaNova Cloud's hosted models can change independently of CrewAI. Query + the [models endpoint](https://docs.sambanova.ai/docs/api-reference/models/get-environments-available-model-list-metadata) + and check the [deprecation guide](https://docs.sambanova.ai/docs/en/models/deprecations) + before deployment. + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + # Required + CEREBRAS_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="cerebras/gpt-oss-120b", + temperature=0.7, + max_tokens=8192 + ) + ``` + + + Cerebras features: + - Fast inference speeds + - Competitive pricing + - Good balance of speed and quality + - Support for long context windows + + + See the [Cerebras model catalog](https://inference-docs.cerebras.ai/models/overview) + and [deprecation notices](https://inference-docs.cerebras.ai/support/deprecation) + for current public endpoint IDs. + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + OPENROUTER_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="openrouter/deepseek/deepseek-r1", + base_url="https://openrouter.ai/api/v1", + api_key=OPENROUTER_API_KEY + ) + ``` + + + Open Router models: + - openrouter/deepseek/deepseek-r1 + - openrouter/deepseek/deepseek-chat + + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Set the following environment variables in your `.env` file: + ```toml Code + NEBIUS_API_KEY= + ``` + + Example usage in your CrewAI project: + ```python Code + llm = LLM( + model="nebius/Qwen/Qwen3-30B-A3B" + ) + ``` + + + Nebius AI Studio features: + - Large collection of open source models + - Higher rate limits + - Competitive pricing + - Good balance of speed and quality + + + **Note:** This provider uses LiteLLM. Add it as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + + + +## Streaming Responses + +CrewAI supports streaming responses from LLMs, allowing your application to receive and process outputs in real-time as they're generated. + + + + Enable streaming by setting the `stream` parameter to `True` when initializing your LLM: + + ```python + from crewai import LLM + + # Create an LLM with streaming enabled + llm = LLM( + model="openai/gpt-5.6-terra", + stream=True # Enable streaming + ) + ``` + + When streaming is enabled, responses are delivered in chunks as they're generated, creating a more responsive user experience. + + + + CrewAI emits events for each chunk received during streaming: + + ```python + from crewai.events import ( + LLMStreamChunkEvent + ) + from crewai.events import BaseEventListener + + class MyCustomListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(LLMStreamChunkEvent) + def on_llm_stream_chunk(self, event: LLMStreamChunkEvent): + # Process each chunk as it arrives + print(f"Received chunk: {event.chunk}") + + my_listener = MyCustomListener() + ``` + + + [Click here](/en/concepts/event-listener#event-listeners) for more details + + + + + All LLM events in CrewAI include agent and task information, allowing you to track and filter LLM interactions by specific agents or tasks: + + ```python + from crewai import LLM, Agent, Task, Crew + from crewai.events import LLMStreamChunkEvent + from crewai.events import BaseEventListener + + class MyCustomListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(LLMStreamChunkEvent) + def on_llm_stream_chunk(source, event): + if researcher.id == event.agent_id: + print("\n==============\n Got event:", event, "\n==============\n") + + + my_listener = MyCustomListener() + + llm = LLM(model="openai/gpt-5.6-terra", stream=True) + + researcher = Agent( + role="About User", + goal="You know everything about the user.", + backstory="""You are a master at understanding people and their preferences.""", + llm=llm, + ) + + search = Task( + description="Answer the following questions about the user: {question}", + expected_output="An answer to the question.", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[search]) + + result = crew.kickoff( + inputs={"question": "..."} + ) + ``` + + + This feature is particularly useful for: + - Debugging specific agent behaviors + - Logging LLM usage by task type + - Auditing which agents are making what types of LLM calls + - Performance monitoring of specific tasks + + + + +## Async LLM Calls + +CrewAI supports asynchronous LLM calls for improved performance and concurrency in your AI workflows. Async calls allow you to run multiple LLM requests concurrently without blocking, making them ideal for high-throughput applications and parallel agent operations. + + + + Use the `acall` method for asynchronous LLM requests: + + ```python + import asyncio + from crewai import LLM + + async def main(): + llm = LLM(model="openai/gpt-4o") + + # Single async call + response = await llm.acall("What is the capital of France?") + print(response) + + asyncio.run(main()) + ``` + + The `acall` method supports all the same parameters as the synchronous `call` method, including messages, tools, and callbacks. + + + + Combine async calls with streaming for real-time concurrent responses: + + ```python + import asyncio + from crewai import LLM + + async def stream_async(): + llm = LLM(model="openai/gpt-4o", stream=True) + + response = await llm.acall("Write a short story about AI") + + print(response) + + asyncio.run(stream_async()) + ``` + + + +## Structured LLM Calls + +CrewAI supports structured responses from LLM calls by allowing you to define a `response_format` using a Pydantic model. This enables the framework to automatically parse and validate the output, making it easier to integrate the response into your application without manual post-processing. + +Structured output support varies by provider and model. Test your chosen model before relying on structured responses in production. + +For example, you can define a Pydantic model to represent the expected response structure and pass it as the `response_format` when instantiating the LLM. The model will then be used to convert the LLM output into a structured Python object. + +```python Code +from crewai import LLM + +class Dog(BaseModel): + name: str + age: int + breed: str + + +llm = LLM(model="openai/gpt-5.6-terra", response_format=Dog) + +response = llm.call( + "Analyze the following messages and return the name, age, and breed. " + "Meet Kona! She is 3 years old and is a black german shepherd." +) +print(response) + +# Output: +# Dog(name='Kona', age=3, breed='black german shepherd') +``` + +## Advanced Features and Optimization + +Learn how to get the most out of your LLM configuration: + + + + CrewAI includes smart context management features: + + ```python + from crewai import LLM + + # CrewAI automatically handles: + # 1. Token counting and tracking + # 2. Content summarization when needed + # 3. Task splitting for large contexts + + llm = LLM( + model="openai/gpt-5.6-terra", + max_completion_tokens=4000, # Limit response length + ) + ``` + + + Best practices for context management: + 1. Choose models with appropriate context windows + 2. Pre-process long inputs when possible + 3. Use chunking for large documents + 4. Monitor token usage to optimize costs + + + + + + + Choose the right context window for your task: + - Small tasks (up to 4K tokens): Standard models + - Medium tasks (between 4K-32K): Enhanced models + - Large tasks (over 32K): Large context models + + ```python + # Configure model with appropriate settings + llm = LLM( + model="openai/gpt-5.6-terra", + reasoning_effort="medium", + max_completion_tokens=4096, + timeout=300 + ) + ``` + + Use the controls supported by your selected model. Depending on the + provider, this may be `temperature`, a reasoning or thinking level, + or prompt instructions that define the desired style and variability. + + + + + 1. Monitor token usage + 2. Implement rate limiting + 3. Use caching when possible + 4. Set appropriate max_tokens limits + + + + + Remember to regularly monitor your token usage and adjust your configuration as needed to optimize costs and performance. + + + + + CrewAI internally uses native sdks for LLM calls, which allows you to drop additional parameters that are not needed for your specific use case. This can help simplify your code and reduce the complexity of your LLM configuration. + For example, if you don't need to send the stop parameter, you can simply omit it from your LLM call: + + ```python + from crewai import LLM + import os + + os.environ["OPENAI_API_KEY"] = "" + + o3_llm = LLM( + model="o3", + drop_params=True, + additional_drop_params=["stop"] + ) + ``` + + + + CrewAI provides message interceptors for several providers, allowing you to hook into request/response cycles at the transport layer. + + **Supported Providers:** + - ✅ OpenAI + - ✅ Anthropic + + **Basic Usage:** + ```python +import httpx +from crewai import LLM +from crewai.llms.hooks import BaseInterceptor + +class CustomInterceptor(BaseInterceptor[httpx.Request, httpx.Response]): + """Custom interceptor to modify requests and responses.""" + + def on_outbound(self, request: httpx.Request) -> httpx.Request: + """Print request before sending to the LLM provider.""" + print(request) + return request + + def on_inbound(self, response: httpx.Response) -> httpx.Response: + """Process response after receiving from the LLM provider.""" + print(f"Status: {response.status_code}") + print(f"Response time: {response.elapsed}") + return response + +# Use the interceptor with an LLM +llm = LLM( + model="openai/gpt-4o", + interceptor=CustomInterceptor() +) + ``` + + **Important Notes:** + - Both methods must return the received object or type of object. + - Modifying received objects may result in unexpected behavior or application crashes. + - Not all providers support interceptors - check the supported providers list above + + + Interceptors operate at the transport layer. This is particularly useful for: + - Message transformation and filtering + - Debugging API interactions + + + + +## Common Issues and Solutions + + + + + Most authentication issues can be resolved by checking API key format and environment variable names. + + + ```bash + # OpenAI + OPENAI_API_KEY=sk-... + + # Anthropic + ANTHROPIC_API_KEY=sk-ant-... + ``` + + + + Always include the provider prefix in model names + + + ```python + # Correct + llm = LLM(model="openai/gpt-4") + + # Incorrect + llm = LLM(model="gpt-4") + ``` + + + + Use larger context models for extensive tasks + + + ```python + # Large context model + llm = LLM(model="openai/gpt-4o") # 128K tokens + ``` + + diff --git a/docs/v1.15.13/en/concepts/memory.mdx b/docs/v1.15.13/en/concepts/memory.mdx new file mode 100644 index 0000000000..349546d1c0 --- /dev/null +++ b/docs/v1.15.13/en/concepts/memory.mdx @@ -0,0 +1,885 @@ +--- +title: Memory +description: Leveraging the unified memory system in CrewAI to enhance agent capabilities. +icon: database +mode: "wide" +--- + +## Overview + +CrewAI provides a **unified memory system** -- a single `Memory` class that replaces separate short-term, long-term, entity, and external memory types with one intelligent API. Memory uses an LLM to analyze content when saving (inferring scope, categories, and importance) and supports adaptive-depth recall with composite scoring that blends semantic similarity, recency, and importance. + +You can use memory four ways: **standalone** (scripts, notebooks), **with Crews**, **with Agents**, or **inside Flows**. + +## Quick Start + +```python +from crewai import Memory + +memory = Memory() + +# Store -- the LLM infers scope, categories, and importance +memory.remember("We decided to use PostgreSQL for the user database.") + +# Retrieve -- results ranked by composite score (semantic + recency + importance) +matches = memory.recall("What database did we choose?") +for m in matches: + print(f"[{m.score:.2f}] {m.record.content}") + +# Tune scoring for a fast-moving project +memory = Memory(recency_weight=0.5, recency_half_life_days=7) + +# Forget +memory.forget(scope="/project/old") + +# Explore the self-organized scope tree +print(memory.tree()) +print(memory.info("/")) +``` + +## Four Ways to Use Memory + +### Standalone + +Use memory in scripts, notebooks, CLI tools, or as a standalone knowledge base -- no agents or crews required. + +```python +from crewai import Memory + +memory = Memory() + +# Build up knowledge +memory.remember("The API rate limit is 1000 requests per minute.") +memory.remember("Our staging environment uses port 8080.") +memory.remember("The team agreed to use feature flags for all new releases.") + +# Later, recall what you need +matches = memory.recall("What are our API limits?", limit=5) +for m in matches: + print(f"[{m.score:.2f}] {m.record.content}") + +# Extract atomic facts from a longer text +raw = """Meeting notes: We decided to migrate from MySQL to PostgreSQL +next quarter. The budget is $50k. Sarah will lead the migration.""" + +facts = memory.extract_memories(raw) +# ["Migration from MySQL to PostgreSQL planned for next quarter", +# "Database migration budget is $50k", +# "Sarah will lead the database migration"] + +for fact in facts: + memory.remember(fact) +``` + +### With Crews + +Pass `memory=True` for default settings, or pass a configured `Memory` instance for custom behavior. + +```python +from crewai import Crew, Agent, Task, Process, Memory + +# Option 1: Default memory +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + memory=True, + verbose=True, +) + +# Option 2: Custom memory with tuned scoring +memory = Memory( + recency_weight=0.4, + semantic_weight=0.4, + importance_weight=0.2, + recency_half_life_days=14, +) +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + memory=memory, +) +``` + +When `memory=True`, the crew creates a default `Memory()` and passes the crew's `embedder` configuration through automatically. All agents in the crew share the crew's memory unless an agent has its own. Without a custom `embedder`, memory uses OpenAI `text-embedding-3-large` embeddings. + +After each task, the crew automatically extracts discrete facts from the task output and stores them. Before each task, the agent recalls relevant context from memory and injects it into the task prompt. + +### With Agents + +Agents can use the crew's shared memory (default) or receive a scoped view for private context. + +```python +from crewai import Agent, Memory + +memory = Memory() + +# Researcher gets a private scope -- only sees /agent/researcher +researcher = Agent( + role="Researcher", + goal="Find and analyze information", + backstory="Expert researcher with attention to detail", + memory=memory.scope("/agent/researcher"), +) + +# Writer uses crew shared memory (no agent-level memory set) +writer = Agent( + role="Writer", + goal="Produce clear, well-structured content", + backstory="Experienced technical writer", + # memory not set -- uses crew._memory when crew has memory enabled +) +``` + +This pattern gives the researcher private findings while the writer reads from the shared crew memory. + +### With Flows + +Every Flow has built-in memory. Use `self.remember()`, `self.recall()`, and `self.extract_memories()` inside any flow method. + +```python +from crewai.flow.flow import Flow, listen, start + +class ResearchFlow(Flow): + @start() + def gather_data(self): + findings = "PostgreSQL handles 10k concurrent connections. MySQL caps at 5k." + self.remember(findings, scope="/research/databases") + return findings + + @listen(gather_data) + def write_report(self, findings): + # Recall past research to provide context + past = self.recall("database performance benchmarks") + context = "\n".join(f"- {m.record.content}" for m in past) + return f"Report:\nNew findings: {findings}\nPrevious context:\n{context}" +``` + +See the [Flows documentation](/concepts/flows) for more on memory in Flows. + + +## Hierarchical Scopes + +### What Scopes Are + +Memories are organized into a hierarchical tree of scopes, similar to a filesystem. Each scope is a path like `/`, `/project/alpha`, or `/agent/researcher/findings`. + +``` +/ + /company + /company/engineering + /company/product + /project + /project/alpha + /project/beta + /agent + /agent/researcher + /agent/writer +``` + +Scopes provide **context-dependent memory** -- when you recall within a scope, you only search that branch of the tree, which improves both precision and performance. + +### How Scope Inference Works + +When you call `remember()` without specifying a scope, the LLM analyzes the content and the existing scope tree, then suggests the best placement. If no existing scope fits, it creates a new one. Over time, the scope tree grows organically from the content itself -- you don't need to design a schema upfront. + +```python +memory = Memory() + +# LLM infers scope from content +memory.remember("We chose PostgreSQL for the user database.") +# -> might be placed under /project/decisions or /engineering/database + +# You can also specify scope explicitly +memory.remember("Sprint velocity is 42 points", scope="/team/metrics") +``` + +### Visualizing the Scope Tree + +```python +print(memory.tree()) +# / (15 records) +# /project (8 records) +# /project/alpha (5 records) +# /project/beta (3 records) +# /agent (7 records) +# /agent/researcher (4 records) +# /agent/writer (3 records) + +print(memory.info("/project/alpha")) +# ScopeInfo(path='/project/alpha', record_count=5, +# categories=['architecture', 'database'], +# oldest_record=datetime(...), newest_record=datetime(...), +# child_scopes=[]) +``` + +### MemoryScope: Subtree Views + +A `MemoryScope` restricts all operations to a branch of the tree. The agent or code using it can only see and write within that subtree. + +```python +memory = Memory() + +# Create a scope for a specific agent +agent_memory = memory.scope("/agent/researcher") + +# Everything is relative to /agent/researcher +agent_memory.remember("Found three relevant papers on LLM memory.") +# -> stored under /agent/researcher + +agent_memory.recall("relevant papers") +# -> searches only under /agent/researcher + +# Narrow further with subscope +project_memory = agent_memory.subscope("project-alpha") +# -> /agent/researcher/project-alpha +``` + +### Best Practices for Scope Design + +- **Start flat, let the LLM organize.** Don't over-engineer your scope hierarchy upfront. Begin with `memory.remember(content)` and let the LLM's scope inference create structure as content accumulates. + +- **Use `/{entity_type}/{identifier}` patterns.** Natural hierarchies emerge from patterns like `/project/alpha`, `/agent/researcher`, `/company/engineering`, `/customer/acme-corp`. + +- **Scope by concern, not by data type.** Use `/project/alpha/decisions` rather than `/decisions/project/alpha`. This keeps related content together. + +- **Keep depth shallow (2-3 levels).** Deeply nested scopes become too sparse. `/project/alpha/architecture` is good; `/project/alpha/architecture/decisions/databases/postgresql` is too deep. + +- **Use explicit scopes when you know, let the LLM infer when you don't.** If you're storing a known project decision, pass `scope="/project/alpha/decisions"`. If you're storing freeform agent output, omit the scope and let the LLM figure it out. + +### Use Case Examples + +**Multi-project team:** +```python +memory = Memory() +# Each project gets its own branch +memory.remember("Using microservices architecture", scope="/project/alpha/architecture") +memory.remember("GraphQL API for client apps", scope="/project/beta/api") + +# Recall across all projects +memory.recall("API design decisions") + +# Or within a specific project +memory.recall("API design", scope="/project/beta") +``` + +**Per-agent private context with shared knowledge:** +```python +memory = Memory() + +# Researcher has private findings +researcher_memory = memory.scope("/agent/researcher") + +# Writer can read from both its own scope and shared company knowledge +writer_view = memory.slice( + scopes=["/agent/writer", "/company/knowledge"], + read_only=True, +) +``` + +**Customer support (per-customer context):** +```python +memory = Memory() + +# Each customer gets isolated context +memory.remember("Prefers email communication", scope="/customer/acme-corp") +memory.remember("On enterprise plan, 50 seats", scope="/customer/acme-corp") + +# Shared product docs are accessible to all agents +memory.remember("Rate limit is 1000 req/min on enterprise plan", scope="/product/docs") +``` + + +## Memory Slices + +### What Slices Are + +A `MemorySlice` is a view across multiple, possibly disjoint scopes. Unlike a scope (which restricts to one subtree), a slice lets you recall from several branches simultaneously. + +### When to Use Slices vs Scopes + +- **Scope**: Use when an agent or code block should be restricted to a single subtree. Example: an agent that only sees `/agent/researcher`. +- **Slice**: Use when you need to combine context from multiple branches. Example: an agent that reads from its own scope plus shared company knowledge. + +### Read-Only Slices + +The most common pattern: give an agent read access to multiple branches without letting it write to shared areas. + +```python +memory = Memory() + +# Agent can recall from its own scope AND company knowledge, +# but cannot write to company knowledge +agent_view = memory.slice( + scopes=["/agent/researcher", "/company/knowledge"], + read_only=True, +) + +matches = agent_view.recall("company security policies", limit=5) +# Searches both /agent/researcher and /company/knowledge, merges and ranks results + +agent_view.remember("new finding") # Raises PermissionError (read-only) +``` + +### Read-Write Slices + +When read-only is disabled, you can write to any of the included scopes, but you must specify which scope explicitly. + +```python +view = memory.slice(scopes=["/team/alpha", "/team/beta"], read_only=False) + +# Must specify scope when writing +view.remember("Cross-team decision", scope="/team/alpha", categories=["decisions"]) +``` + + +## Composite Scoring + +Recall results are ranked by a weighted combination of three signals: + +``` +composite = semantic_weight * similarity + recency_weight * decay + importance_weight * importance +``` + +Where: +- **similarity** = `1 / (1 + distance)` from the vector index (0 to 1) +- **decay** = `0.5^(age_days / half_life_days)` -- exponential decay (1.0 for today, 0.5 at half-life) +- **importance** = the record's importance score (0 to 1), set at encoding time + +Configure these directly on the `Memory` constructor: + +```python +# Sprint retrospective: favor recent memories, short half-life +memory = Memory( + recency_weight=0.5, + semantic_weight=0.3, + importance_weight=0.2, + recency_half_life_days=7, +) + +# Architecture knowledge base: favor important memories, long half-life +memory = Memory( + recency_weight=0.1, + semantic_weight=0.5, + importance_weight=0.4, + recency_half_life_days=180, +) +``` + +Each `MemoryMatch` includes a `match_reasons` list so you can see why a result ranked where it did (e.g. `["semantic", "recency", "importance"]`). + + +## LLM Analysis Layer + +Memory uses the LLM in three ways: + +1. **On save** -- When you omit scope, categories, or importance, the LLM analyzes the content and suggests scope, categories, importance, and metadata (entities, dates, topics). +2. **On recall** -- For deep/auto recall, the LLM analyzes the query (keywords, time hints, suggested scopes, complexity) to guide retrieval. +3. **Extract memories** -- `extract_memories(content)` breaks raw text (e.g. task output) into discrete memory statements. Agents use this before calling `remember()` on each statement so that atomic facts are stored instead of one large blob. + +All analysis degrades gracefully on LLM failure -- see [Failure Behavior](#failure-behavior). + + +## Memory Consolidation + +When saving new content, the encoding pipeline automatically checks for similar existing records in storage. If the similarity is above `consolidation_threshold` (default 0.85), the LLM decides what to do: + +- **keep** -- The existing record is still accurate and not redundant. +- **update** -- The existing record should be updated with new information (LLM provides the merged content). +- **delete** -- The existing record is outdated, superseded, or contradicted. +- **insert_new** -- Whether the new content should also be inserted as a separate record. + +This prevents duplicates from accumulating. For example, if you save "CrewAI ensures reliable operation" three times, consolidation recognizes the duplicates and keeps only one record. + +### Intra-batch Dedup + +When using `remember_many()`, items within the same batch are compared against each other before hitting storage. If two items have cosine similarity >= `batch_dedup_threshold` (default 0.98), the later one is silently dropped. This catches exact or near-exact duplicates within a single batch without any LLM calls (pure vector math). + +```python +# Only 2 records are stored (the third is a near-duplicate of the first) +memory.remember_many([ + "CrewAI supports complex workflows.", + "Python is a great language.", + "CrewAI supports complex workflows.", # dropped by intra-batch dedup +]) +``` + + +## Non-blocking Saves + +`remember_many()` is **non-blocking** -- it submits the encoding pipeline to a background thread and returns immediately. This means the agent can continue to the next task while memories are being saved. + +```python +# Returns immediately -- save happens in background +memory.remember_many(["Fact A.", "Fact B.", "Fact C."]) + +# recall() automatically waits for pending saves before searching +matches = memory.recall("facts") # sees all 3 records +``` + +### Read Barrier + +Every `recall()` call automatically calls `drain_writes()` before searching, ensuring the query always sees the latest persisted records. This is transparent -- you never need to think about it. + +### Crew Shutdown + +When a crew finishes, `kickoff()` drains all pending memory saves in its `finally` block, so no saves are lost even if the crew completes while background saves are in flight. + +### Standalone Usage + +For scripts or notebooks where there's no crew lifecycle, call `drain_writes()` or `close()` explicitly: + +```python +memory = Memory() +memory.remember_many(["Fact A.", "Fact B."]) + +# Option 1: Wait for pending saves +memory.drain_writes() + +# Option 2: Drain and shut down the background pool +memory.close() +``` + + +## Source and Privacy + +Every memory record can carry a `source` tag for provenance tracking and a `private` flag for access control. + +### Source Tracking + +The `source` parameter identifies where a memory came from: + +```python +# Tag memories with their origin +memory.remember("User prefers dark mode", source="user:alice") +memory.remember("System config updated", source="admin") +memory.remember("Agent found a bug", source="agent:debugger") + +# Recall only memories from a specific source +matches = memory.recall("user preferences", source="user:alice") +``` + +### Private Memories + +Private memories are only visible to recall when the `source` matches: + +```python +# Store a private memory +memory.remember("Alice's API key is sk-...", source="user:alice", private=True) + +# This recall sees the private memory (source matches) +matches = memory.recall("API key", source="user:alice") + +# This recall does NOT see it (different source) +matches = memory.recall("API key", source="user:bob") + +# Admin access: see all private records regardless of source +matches = memory.recall("API key", include_private=True) +``` + +This is particularly useful in multi-user or enterprise deployments where different users' memories should be isolated. + + +## RecallFlow (Deep Recall) + +`recall()` supports two depths: + +- **`depth="shallow"`** -- Direct vector search with composite scoring. Fast (~200ms), no LLM calls. +- **`depth="deep"` (default)** -- Runs a multi-step RecallFlow: query analysis, scope selection, parallel vector search, confidence-based routing, and optional recursive exploration when confidence is low. + +**Smart LLM skip**: Queries shorter than `query_analysis_threshold` (default 200 characters) skip the LLM query analysis entirely, even in deep mode. Short queries like "What database do we use?" are already good search phrases -- the LLM analysis adds little value. This saves ~1-3s per recall for typical short queries. Only longer queries (e.g. full task descriptions) go through LLM distillation into targeted sub-queries. + +```python +# Shallow: pure vector search, no LLM +matches = memory.recall("What did we decide?", limit=10, depth="shallow") + +# Deep (default): intelligent retrieval with LLM analysis for long queries +matches = memory.recall( + "Summarize all architecture decisions from this quarter", + limit=10, + depth="deep", +) +``` + +The confidence thresholds that control the RecallFlow router are configurable: + +```python +memory = Memory( + confidence_threshold_high=0.9, # Only synthesize when very confident + confidence_threshold_low=0.4, # Explore deeper more aggressively + exploration_budget=2, # Allow up to 2 exploration rounds + query_analysis_threshold=200, # Skip LLM for queries shorter than this +) +``` + + +## Embedder Configuration + +Memory needs an embedding model to convert text into vectors for semantic search. By default, `Memory()` uses OpenAI `text-embedding-3-large` embeddings, which produce 3072-dimensional vectors. Set `OPENAI_API_KEY` for the default path, or configure a custom embedder in one of three ways. + + +Existing local memory stores created with 1536-dimensional embeddings, such as `text-embedding-3-small` or `text-embedding-ada-002`, may not be compatible with the `text-embedding-3-large` default. This applies to both the OpenAI and Azure OpenAI providers — Azure's default embedding model also changed from `text-embedding-ada-002` to `text-embedding-3-large`. If local testing fails with an embedding dimension mismatch, reset memory with `crewai reset-memories -m`, delete the local memory storage directory, or explicitly configure the older embedder model until you migrate. + + +### Passing to Memory Directly + +```python +from crewai import Memory + +# As a config dict +memory = Memory(embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-large"}}) + +# As a pre-built callable +from crewai.rag.embeddings.factory import build_embedder +embedder = build_embedder({"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}) +memory = Memory(embedder=embedder) +``` + +### Via Crew Embedder Config + +When using `memory=True`, the crew's `embedder` config is passed through: + +```python +from crewai import Crew + +crew = Crew( + agents=[...], + tasks=[...], + memory=True, + embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-large"}}, +) +``` + +### Provider Examples + + + +```python +memory = Memory(embedder={ + "provider": "openai", + "config": { + "model_name": "text-embedding-3-large", + # "api_key": "sk-...", # or set OPENAI_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "ollama", + "config": { + "model_name": "mxbai-embed-large", + "url": "http://localhost:11434/api/embeddings", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "azure", + "config": { + "deployment_id": "your-embedding-deployment", + "api_key": "your-azure-api-key", + "api_base": "https://your-resource.openai.azure.com", + "api_version": "2024-02-01", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "google-generativeai", + "config": { + "model_name": "gemini-embedding-001", + # "api_key": "...", # or set GOOGLE_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "google-vertex", + "config": { + "model_name": "gemini-embedding-001", + "project_id": "your-gcp-project-id", + "location": "us-central1", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "cohere", + "config": { + "model_name": "embed-english-v3.0", + # "api_key": "...", # or set COHERE_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "voyageai", + "config": { + "model": "voyage-3", + # "api_key": "...", # or set VOYAGE_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "amazon-bedrock", + "config": { + "model_name": "amazon.titan-embed-text-v1", + # Uses default AWS credentials (boto3 session) + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "huggingface", + "config": { + "model_name": "sentence-transformers/all-MiniLM-L6-v2", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "jina", + "config": { + "model_name": "jina-embeddings-v2-base-en", + # "api_key": "...", # or set JINA_API_KEY env var + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "watsonx", + "config": { + "model_id": "ibm/slate-30m-english-rtrvr", + "api_key": "your-watsonx-api-key", + "project_id": "your-project-id", + "url": "https://us-south.ml.cloud.ibm.com", + }, +}) +``` + + + +```python +# Pass any callable that takes a list of strings and returns a list of vectors +def my_embedder(texts: list[str]) -> list[list[float]]: + # Your embedding logic here + return [[0.1, 0.2, ...] for _ in texts] + +memory = Memory(embedder=my_embedder) +``` + + + +### Provider Reference + +| Provider | Key | Typical Model | Notes | +| :--- | :--- | :--- | :--- | +| OpenAI | `openai` | `text-embedding-3-large` | Default. Set `OPENAI_API_KEY`. | +| Ollama | `ollama` | `mxbai-embed-large` | Local, no API key needed. | +| Azure OpenAI | `azure` | `text-embedding-3-large` | Default model. Requires `deployment_id`. | +| Google AI | `google-generativeai` | `gemini-embedding-001` | Set `GOOGLE_API_KEY`. | +| Google Vertex | `google-vertex` | `gemini-embedding-001` | Requires `project_id`. | +| Cohere | `cohere` | `embed-english-v3.0` | Strong multilingual support. | +| VoyageAI | `voyageai` | `voyage-3` | Optimized for retrieval. | +| AWS Bedrock | `amazon-bedrock` | `amazon.titan-embed-text-v1` | Uses boto3 credentials. | +| Hugging Face | `huggingface` | `all-MiniLM-L6-v2` | Local sentence-transformers. | +| Jina | `jina` | `jina-embeddings-v2-base-en` | Set `JINA_API_KEY`. | +| IBM WatsonX | `watsonx` | `ibm/slate-30m-english-rtrvr` | Requires `project_id`. | +| Sentence Transformer | `sentence-transformer` | `all-MiniLM-L6-v2` | Local, no API key. | +| Custom | `custom` | -- | Requires `embedding_callable`. | + + +## LLM Configuration + +Memory uses an LLM for save analysis (scope, categories, importance inference), consolidation decisions, and deep recall query analysis. You can configure which model to use. + +```python +from crewai import Memory, LLM + +# Default: gpt-4o-mini +memory = Memory() + +# Use a different OpenAI model +memory = Memory(llm="gpt-4o") + +# Use Anthropic +memory = Memory(llm="anthropic/claude-3-haiku-20240307") + +# Use Ollama for fully local/private analysis +memory = Memory(llm="ollama/llama3.2") + +# Use Google Gemini +memory = Memory(llm="gemini/gemini-2.0-flash") + +# Pass a pre-configured LLM instance with custom settings +llm = LLM(model="gpt-4o", temperature=0) +memory = Memory(llm=llm) +``` + +The LLM is initialized **lazily** -- it's only created when first needed. This means `Memory()` never fails at construction time, even if API keys aren't set. Errors only surface when the LLM is actually called (e.g. when saving without explicit scope/categories, or during deep recall). + +For fully offline/private operation, use a local model for both the LLM and embedder: + +```python +memory = Memory( + llm="ollama/llama3.2", + embedder={"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}, +) +``` + + +## Storage Backend + +- **Default**: LanceDB, stored under `./.crewai/memory` (or `$CREWAI_STORAGE_DIR/memory` if the env var is set, or the path you pass as `storage="path/to/dir"`). +- **Custom backend**: Implement the `StorageBackend` protocol (see `crewai.memory.storage.backend`) and pass an instance to `Memory(storage=your_backend)`. + + +## Discovery + +Inspect the scope hierarchy, categories, and records: + +```python +memory.tree() # Formatted tree of scopes and record counts +memory.tree("/project", max_depth=2) # Subtree view +memory.info("/project") # ScopeInfo: record_count, categories, oldest/newest +memory.list_scopes("/") # Immediate child scopes +memory.list_categories() # Category names and counts +memory.list_records(scope="/project/alpha", limit=20) # Records in a scope, newest first +``` + + +## Failure Behavior + +If the LLM fails during analysis (network error, rate limit, invalid response), memory degrades gracefully: + +- **Save analysis** -- A warning is logged and the memory is still stored with default scope `/`, empty categories, and importance `0.5`. +- **Extract memories** -- The full content is stored as a single memory so nothing is dropped. +- **Query analysis** -- Recall falls back to simple scope selection and vector search so you still get results. + +No exception is raised for these analysis failures; only storage or embedder failures will raise. + + +## Privacy Note + +Memory content is sent to the configured LLM for analysis (scope/categories/importance on save, query analysis and optional deep recall). For sensitive data, use a local LLM (e.g. Ollama) or ensure your provider meets your compliance requirements. + + +## Memory Events + +All memory operations emit events with `source_type="unified_memory"`. You can listen for timing, errors, and content. + +| Event | Description | Key Properties | +| :---- | :---------- | :------------- | +| **MemoryQueryStartedEvent** | Query begins | `query`, `limit` | +| **MemoryQueryCompletedEvent** | Query succeeds | `query`, `results`, `query_time_ms` | +| **MemoryQueryFailedEvent** | Query fails | `query`, `error` | +| **MemorySaveStartedEvent** | Save begins | `value`, `metadata` | +| **MemorySaveCompletedEvent** | Save succeeds | `value`, `save_time_ms` | +| **MemorySaveFailedEvent** | Save fails | `value`, `error` | +| **MemoryRetrievalStartedEvent** | Agent retrieval starts | `task_id` | +| **MemoryRetrievalCompletedEvent** | Agent retrieval done | `task_id`, `memory_content`, `retrieval_time_ms` | + +Example: monitor query time: + +```python +from crewai.events import BaseEventListener, MemoryQueryCompletedEvent + +class MemoryMonitor(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(MemoryQueryCompletedEvent) + def on_done(source, event): + if getattr(event, "source_type", None) == "unified_memory": + print(f"Query '{event.query}' completed in {event.query_time_ms:.0f}ms") +``` + + +## Troubleshooting + +**Memory not persisting?** +- Ensure the storage path is writable (default `./.crewai/memory`). Pass `storage="./your_path"` to use a different directory, or set the `CREWAI_STORAGE_DIR` environment variable. +- When using a crew, confirm `memory=True` or `memory=Memory(...)` is set. + +**Slow recall?** +- Use `depth="shallow"` for routine agent context. Reserve `depth="deep"` for complex queries. +- Increase `query_analysis_threshold` to skip LLM analysis for more queries. + +**LLM analysis errors in logs?** +- Memory still saves/recalls with safe defaults. Check API keys, rate limits, and model availability if you want full LLM analysis. + +**Background save errors in logs?** +- Memory saves run in a background thread. Errors are emitted as `MemorySaveFailedEvent` but don't crash the agent. Check logs for the root cause (usually LLM or embedder connection issues). + +**Embedding dimension mismatch?** +- Existing local memory stores may have been created with a different embedding model. The default OpenAI memory embedder is now `text-embedding-3-large` (3072 dimensions), while older stores commonly used 1536-dimensional embeddings. For local testing, run `crewai reset-memories -m`, delete the local memory storage directory, or configure the previous embedder model explicitly. + +**Concurrent write conflicts?** +- LanceDB operations are serialized with a shared lock and retried automatically on conflict. This handles multiple `Memory` instances pointing at the same database (e.g. agent memory + crew memory). No action needed. + +**Browse memory from the terminal:** +```bash +crewai memory # Opens the TUI browser +crewai memory --storage-path ./my_memory # Point to a specific directory +``` + +**Reset memory (e.g. for tests):** +```python +crew.reset_memories(command_type="memory") # Resets unified memory +# Or on a Memory instance: +memory.reset() # All scopes +memory.reset(scope="/project/old") # Only that subtree +``` + + +## Configuration Reference + +All configuration is passed as keyword arguments to `Memory(...)`. Every parameter has a sensible default. + +| Parameter | Default | Description | +| :--- | :--- | :--- | +| `llm` | `"gpt-4o-mini"` | LLM for analysis (model name or `BaseLLM` instance). | +| `storage` | `"lancedb"` | Storage backend (`"lancedb"`, a path string, or a `StorageBackend` instance). | +| `embedder` | `None` (OpenAI `text-embedding-3-large`) | Embedder (config dict, callable, or `None` for default OpenAI). | +| `recency_weight` | `0.3` | Weight for recency in composite score. | +| `semantic_weight` | `0.5` | Weight for semantic similarity in composite score. | +| `importance_weight` | `0.2` | Weight for importance in composite score. | +| `recency_half_life_days` | `30` | Days for recency score to halve (exponential decay). | +| `consolidation_threshold` | `0.85` | Similarity above which consolidation is triggered on save. Set to `1.0` to disable. | +| `consolidation_limit` | `5` | Max existing records to compare during consolidation. | +| `default_importance` | `0.5` | Importance assigned when not provided and LLM analysis is skipped. | +| `batch_dedup_threshold` | `0.98` | Cosine similarity for dropping near-duplicates within a `remember_many()` batch. | +| `confidence_threshold_high` | `0.8` | Recall confidence above which results are returned directly. | +| `confidence_threshold_low` | `0.5` | Recall confidence below which deeper exploration is triggered. | +| `complex_query_threshold` | `0.7` | For complex queries, explore deeper below this confidence. | +| `exploration_budget` | `1` | Number of LLM-driven exploration rounds during deep recall. | +| `query_analysis_threshold` | `200` | Queries shorter than this (in characters) skip LLM analysis during deep recall. | diff --git a/docs/v1.15.13/en/concepts/planning.mdx b/docs/v1.15.13/en/concepts/planning.mdx new file mode 100644 index 0000000000..c1992718d5 --- /dev/null +++ b/docs/v1.15.13/en/concepts/planning.mdx @@ -0,0 +1,155 @@ +--- +title: Planning +description: Learn how to add planning to your CrewAI Crew and improve their performance. +icon: ruler-combined +mode: "wide" +--- + +## Overview + +The planning feature in CrewAI allows you to add planning capability to your crew. When enabled, before each Crew iteration, +all Crew information is sent to an AgentPlanner that will plan the tasks step by step, and this plan will be added to each task description. + +### Using the Planning Feature + +Getting started with the planning feature is very easy, the only step required is to add `planning=True` to your Crew: + + +```python Code +from crewai import Crew, Agent, Task, Process + +# Assemble your crew with planning capabilities +my_crew = Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + planning=True, +) +``` + + +From this point on, your crew will have planning enabled, and the tasks will be planned before each iteration. + + +When planning is enabled, crewAI will use `gpt-4o-mini` as the default LLM for planning, which requires a valid OpenAI API key. Since your agents might be using different LLMs, this could cause confusion if you don't have an OpenAI API key configured or if you're experiencing unexpected behavior related to LLM API calls. + + +#### Planning LLM + +Now you can define the LLM that will be used to plan the tasks. + +When running the base case example, you will see something like the output below, which represents the output of the `AgentPlanner` +responsible for creating the step-by-step logic to add to the Agents' tasks. + + +```python Code +from crewai import Crew, Agent, Task, Process + +# Assemble your crew with planning capabilities and custom LLM +my_crew = Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + planning=True, + planning_llm="gpt-4o" +) + +# Run the crew +my_crew.kickoff() +``` + +```markdown Result +[2024-07-15 16:49:11][INFO]: Planning the crew execution +**Step-by-Step Plan for Task Execution** + +**Task Number 1: Conduct a thorough research about AI LLMs** + +**Agent:** AI LLMs Senior Data Researcher + +**Agent Goal:** Uncover cutting-edge developments in AI LLMs + +**Task Expected Output:** A list with 10 bullet points of the most relevant information about AI LLMs + +**Task Tools:** None specified + +**Agent Tools:** None specified + +**Step-by-Step Plan:** + +1. **Define Research Scope:** + + - Determine the specific areas of AI LLMs to focus on, such as advancements in architecture, use cases, ethical considerations, and performance metrics. + +2. **Identify Reliable Sources:** + + - List reputable sources for AI research, including academic journals, industry reports, conferences (e.g., NeurIPS, ACL), AI research labs (e.g., OpenAI, Google AI), and online databases (e.g., IEEE Xplore, arXiv). + +3. **Collect Data:** + + - Search for the latest papers, articles, and reports published in 2024 and early 2025. + - Use keywords like "Large Language Models 2025", "AI LLM advancements", "AI ethics 2025", etc. + +4. **Analyze Findings:** + + - Read and summarize the key points from each source. + - Highlight new techniques, models, and applications introduced in the past year. + +5. **Organize Information:** + + - Categorize the information into relevant topics (e.g., new architectures, ethical implications, real-world applications). + - Ensure each bullet point is concise but informative. + +6. **Create the List:** + + - Compile the 10 most relevant pieces of information into a bullet point list. + - Review the list to ensure clarity and relevance. + +**Expected Output:** + +A list with 10 bullet points of the most relevant information about AI LLMs. + +--- + +**Task Number 2: Review the context you got and expand each topic into a full section for a report** + +**Agent:** AI LLMs Reporting Analyst + +**Agent Goal:** Create detailed reports based on AI LLMs data analysis and research findings + +**Task Expected Output:** A fully fledged report with the main topics, each with a full section of information. Formatted as markdown without '```' + +**Task Tools:** None specified + +**Agent Tools:** None specified + +**Step-by-Step Plan:** + +1. **Review the Bullet Points:** + - Carefully read through the list of 10 bullet points provided by the AI LLMs Senior Data Researcher. + +2. **Outline the Report:** + - Create an outline with each bullet point as a main section heading. + - Plan sub-sections under each main heading to cover different aspects of the topic. + +3. **Research Further Details:** + - For each bullet point, conduct additional research if necessary to gather more detailed information. + - Look for case studies, examples, and statistical data to support each section. + +4. **Write Detailed Sections:** + - Expand each bullet point into a comprehensive section. + - Ensure each section includes an introduction, detailed explanation, examples, and a conclusion. + - Use markdown formatting for headings, subheadings, lists, and emphasis. + +5. **Review and Edit:** + - Proofread the report for clarity, coherence, and correctness. + - Make sure the report flows logically from one section to the next. + - Format the report according to markdown standards. + +6. **Finalize the Report:** + - Ensure the report is complete with all sections expanded and detailed. + - Double-check formatting and make any necessary adjustments. + +**Expected Output:** +A fully fledged report with the main topics, each with a full section of information. Formatted as markdown without '```'. +``` + \ No newline at end of file diff --git a/docs/v1.15.13/en/concepts/processes.mdx b/docs/v1.15.13/en/concepts/processes.mdx new file mode 100644 index 0000000000..a7411a560e --- /dev/null +++ b/docs/v1.15.13/en/concepts/processes.mdx @@ -0,0 +1,66 @@ +--- +title: Processes +description: Detailed guide on workflow management through processes in CrewAI, with updated implementation details. +icon: bars-staggered +mode: "wide" +--- + +## Overview + + + Processes orchestrate the execution of tasks by agents, akin to project management in human teams. + These processes ensure tasks are distributed and executed efficiently, in alignment with a predefined strategy. + + +## Process Implementations + +- **Sequential**: Executes tasks sequentially, ensuring tasks are completed in an orderly progression. +- **Hierarchical**: Organizes tasks in a managerial hierarchy, where tasks are delegated and executed based on a structured chain of command. A manager language model (`manager_llm`) or a custom manager agent (`manager_agent`) must be specified in the crew to enable the hierarchical process, facilitating the creation and management of tasks by the manager. + +## The Role of Processes in Teamwork +Processes enable individual agents to operate as a cohesive unit, streamlining their efforts to achieve common objectives with efficiency and coherence. + +## Assigning Processes to a Crew +To assign a process to a crew, specify the process type upon crew creation to set the execution strategy. For a hierarchical process, ensure to define `manager_llm` or `manager_agent` for the manager agent. + +```python +from crewai import Crew, Process + +# Example: Creating a crew with a sequential process +crew = Crew( + agents=my_agents, + tasks=my_tasks, + process=Process.sequential +) + +# Example: Creating a crew with a hierarchical process +# Ensure to provide a manager_llm or manager_agent +crew = Crew( + agents=my_agents, + tasks=my_tasks, + process=Process.hierarchical, + manager_llm="gpt-4o" + # or + # manager_agent=my_manager_agent +) +``` +**Note:** Ensure `my_agents` and `my_tasks` are defined prior to creating a `Crew` object, and for the hierarchical process, either `manager_llm` or `manager_agent` is also required. + +## Sequential Process + +This method mirrors dynamic team workflows, progressing through tasks in a thoughtful and systematic manner. Task execution follows the predefined order in the task list, with the output of one task serving as context for the next. + +To customize task context, utilize the `context` parameter in the `Task` class to specify outputs that should be used as context for subsequent tasks. + +## Hierarchical Process + +Emulates a corporate hierarchy, CrewAI allows specifying a custom manager agent or automatically creates one, requiring the specification of a manager language model (`manager_llm`). This agent oversees task execution, including planning, delegation, and validation. Tasks are not pre-assigned; the manager allocates tasks to agents based on their capabilities, reviews outputs, and assesses task completion. + +## Process Class: Detailed Overview + +The `Process` class is implemented as an enumeration (`Enum`), ensuring type safety and restricting process values to the defined types (`sequential`, `hierarchical`). + +## Conclusion + +The structured collaboration facilitated by processes within CrewAI is crucial for enabling systematic teamwork among agents. +This documentation has been updated to reflect the latest features and enhancements, ensuring users have access to the most current and comprehensive information. \ No newline at end of file diff --git a/docs/v1.15.13/en/concepts/production-architecture.mdx b/docs/v1.15.13/en/concepts/production-architecture.mdx new file mode 100644 index 0000000000..ecd9078491 --- /dev/null +++ b/docs/v1.15.13/en/concepts/production-architecture.mdx @@ -0,0 +1,162 @@ +--- +title: Production Architecture +description: Best practices for building production-ready AI applications with CrewAI +icon: server +mode: "wide" +--- + +# The Flow-First Mindset + +When building production AI applications with CrewAI, **we recommend starting with a Flow**. + +While it's possible to run individual Crews or Agents, wrapping them in a Flow provides the necessary structure for a robust, scalable application. + +## Why Flows? + +1. **State Management**: Flows provide a built-in way to manage state across different steps of your application. This is crucial for passing data between Crews, maintaining context, and handling user inputs. +2. **Control**: Flows allow you to define precise execution paths, including loops, conditionals, and branching logic. This is essential for handling edge cases and ensuring your application behaves predictably. +3. **Observability**: Flows provide a clear structure that makes it easier to trace execution, debug issues, and monitor performance. We recommend using [CrewAI Tracing](/en/observability/tracing) for detailed insights. Simply run `crewai login` to enable free observability features. + +## The Architecture + +A typical production CrewAI application looks like this: + +```mermaid +graph TD + Start((Start)) --> Flow[Flow Orchestrator] + Flow --> State{State Management} + State --> Step1[Step 1: Data Gathering] + Step1 --> Crew1[Research Crew] + Crew1 --> State + State --> Step2{Condition Check} + Step2 -- "Valid" --> Step3[Step 3: Execution] + Step3 --> Crew2[Action Crew] + Step2 -- "Invalid" --> End((End)) + Crew2 --> End +``` + +### 1. The Flow Class +Your `Flow` class is the entry point. It defines the state schema and the methods that execute your logic. + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class AppState(BaseModel): + user_input: str = "" + research_results: str = "" + final_report: str = "" + +class ProductionFlow(Flow[AppState]): + @start() + def gather_input(self): + # ... logic to get input ... + pass + + @listen(gather_input) + def run_research_crew(self): + # ... trigger a Crew ... + pass +``` + +### 2. State Management +Use Pydantic models to define your state. This ensures type safety and makes it clear what data is available at each step. + +- **Keep it minimal**: Store only what you need to persist between steps. +- **Use structured data**: Avoid unstructured dictionaries when possible. + +### 3. Crews as Units of Work +Delegate complex tasks to Crews. A Crew should be focused on a specific goal (e.g., "Research a topic", "Write a blog post"). + +- **Don't over-engineer Crews**: Keep them focused. +- **Pass state explicitly**: Pass the necessary data from the Flow state to the Crew inputs. + +```python + @listen(gather_input) + def run_research_crew(self): + crew = ResearchCrew() + result = crew.kickoff(inputs={"topic": self.state.user_input}) + self.state.research_results = result.raw +``` + +## Control Primitives + +Leverage CrewAI's control primitives to add robustness and control to your Crews. + +### 1. Task Guardrails +Use [Task Guardrails](/en/concepts/tasks#task-guardrails) to validate task outputs before they are accepted. This ensures that your agents produce high-quality results. + +```python +def validate_content(result: TaskOutput) -> Tuple[bool, Any]: + if len(result.raw) < 100: + return (False, "Content is too short. Please expand.") + return (True, result.raw) + +task = Task( + ..., + guardrail=validate_content +) +``` + +### 2. Structured Outputs +Always use structured outputs (`output_pydantic` or `output_json`) when passing data between tasks or to your application. This prevents parsing errors and ensures type safety. + +```python +class ResearchResult(BaseModel): + summary: str + sources: List[str] + +task = Task( + ..., + output_pydantic=ResearchResult +) +``` + +### 3. LLM Hooks +Use [LLM Hooks](/en/learn/llm-hooks) to inspect or modify messages before they are sent to the LLM, or to sanitize responses. + +```python +@before_llm_call +def log_request(context): + print(f"Agent {context.agent.role} is calling the LLM...") +``` + +## Deployment Patterns + +When deploying your Flow, consider the following: + +### CrewAI Enterprise +The easiest way to deploy your Flow is using CrewAI Enterprise. It handles the infrastructure, authentication, and monitoring for you. + +Check out the [Deployment Guide](https://docs-platform.crewai.com/platform/en/guides/deploy-to-amp) to get started. + +```bash +crewai deploy create +``` + +### Async Execution +For long-running tasks, use `kickoff_async` to avoid blocking your API. + +### Persistence +Use the `@persist` decorator to save the state of your Flow to a database. This allows you to resume execution if the process crashes or if you need to wait for human input. + +```python +@persist +class ProductionFlow(Flow[AppState]): + # ... +``` + +By default, `@persist` resumes a flow when `kickoff(inputs={"id": })` is supplied, extending the same `flow_uuid` history. To **fork** a persisted flow into a new lineage — hydrate state from a previous run but write under a fresh `state.id` — pass `restore_from_state_id`: + +```python +flow.kickoff(restore_from_state_id="") +``` + +The new run gets a fresh `state.id` (auto-generated, or `inputs["id"]` if pinned) so its `@persist` writes don't extend the source's history. Combining with `from_checkpoint` raises a `ValueError`; pick one hydration source. + +## Summary + +- **Start with a Flow.** +- **Define a clear State.** +- **Use Crews for complex tasks.** +- **Deploy with an API and persistence.** diff --git a/docs/v1.15.13/en/concepts/reasoning.mdx b/docs/v1.15.13/en/concepts/reasoning.mdx new file mode 100644 index 0000000000..d37017f57d --- /dev/null +++ b/docs/v1.15.13/en/concepts/reasoning.mdx @@ -0,0 +1,148 @@ +--- +title: Reasoning +description: "Learn how to enable and use agent reasoning to improve task execution." +icon: brain +mode: "wide" +--- + +## Overview + +Agent reasoning is a feature that allows agents to reflect on a task and create a plan before execution. This helps agents approach tasks more methodically and ensures they're ready to perform the assigned work. + +## Usage + +To enable reasoning for an agent, simply set `reasoning=True` when creating the agent: + +```python +from crewai import Agent + +agent = Agent( + role="Data Analyst", + goal="Analyze complex datasets and provide insights", + backstory="You are an experienced data analyst with expertise in finding patterns in complex data.", + reasoning=True, # Enable reasoning + max_reasoning_attempts=3 # Optional: Set a maximum number of reasoning attempts +) +``` + +## How It Works + +When reasoning is enabled, before executing a task, the agent will: + +1. Reflect on the task and create a detailed plan +2. Evaluate whether it's ready to execute the task +3. Refine the plan as necessary until it's ready or max_reasoning_attempts is reached +4. Inject the reasoning plan into the task description before execution + +This process helps the agent break down complex tasks into manageable steps and identify potential challenges before starting. + +## Configuration Options + + + Enable or disable reasoning + + + + Maximum number of attempts to refine the plan before proceeding with execution. If None (default), the agent will continue refining until it's ready. + + +## Example + +Here's a complete example: + +```python +from crewai import Agent, Task, Crew + +# Create an agent with reasoning enabled +analyst = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + backstory="You are an expert data analyst.", + reasoning=True, + max_reasoning_attempts=3 # Optional: Set a limit on reasoning attempts +) + +# Create a task +analysis_task = Task( + description="Analyze the provided sales data and identify key trends.", + expected_output="A report highlighting the top 3 sales trends.", + agent=analyst +) + +# Create a crew and run the task +crew = Crew(agents=[analyst], tasks=[analysis_task]) +result = crew.kickoff() + +print(result) +``` + +## Error Handling + +The reasoning process is designed to be robust, with error handling built in. If an error occurs during reasoning, the agent will proceed with executing the task without the reasoning plan. This ensures that tasks can still be executed even if the reasoning process fails. + +Here's how to handle potential errors in your code: + +```python +from crewai import Agent, Task +import logging + +# Set up logging to capture any reasoning errors +logging.basicConfig(level=logging.INFO) + +# Create an agent with reasoning enabled +agent = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + reasoning=True, + max_reasoning_attempts=3 +) + +# Create a task +task = Task( + description="Analyze the provided sales data and identify key trends.", + expected_output="A report highlighting the top 3 sales trends.", + agent=agent +) + +# Execute the task +# If an error occurs during reasoning, it will be logged and execution will continue +result = agent.execute_task(task) +``` + +## Example Reasoning Output + +Here's an example of what a reasoning plan might look like for a data analysis task: + +``` +Task: Analyze the provided sales data and identify key trends. + +Reasoning Plan: +I'll analyze the sales data to identify the top 3 trends. + +1. Understanding of the task: + I need to analyze sales data to identify key trends that would be valuable for business decision-making. + +2. Key steps I'll take: + - First, I'll examine the data structure to understand what fields are available + - Then I'll perform exploratory data analysis to identify patterns + - Next, I'll analyze sales by time periods to identify temporal trends + - I'll also analyze sales by product categories and customer segments + - Finally, I'll identify the top 3 most significant trends + +3. Approach to challenges: + - If the data has missing values, I'll decide whether to fill or filter them + - If the data has outliers, I'll investigate whether they're valid data points or errors + - If trends aren't immediately obvious, I'll apply statistical methods to uncover patterns + +4. Use of available tools: + - I'll use data analysis tools to explore and visualize the data + - I'll use statistical tools to identify significant patterns + - I'll use knowledge retrieval to access relevant information about sales analysis + +5. Expected outcome: + A concise report highlighting the top 3 sales trends with supporting evidence from the data. + +READY: I am ready to execute the task. +``` + +This reasoning plan helps the agent organize its approach to the task, consider potential challenges, and ensure it delivers the expected output. diff --git a/docs/v1.15.13/en/concepts/skills.mdx b/docs/v1.15.13/en/concepts/skills.mdx new file mode 100644 index 0000000000..66960edb4c --- /dev/null +++ b/docs/v1.15.13/en/concepts/skills.mdx @@ -0,0 +1,419 @@ +--- +title: Skills +description: Filesystem-based skill packages that inject domain expertise and instructions into agent prompts. +icon: bolt +mode: "wide" +--- + +## Overview + +Skills are self-contained directories that provide agents with **domain-specific instructions, guidelines, and reference material**. Each skill is defined by a `SKILL.md` file with YAML frontmatter and a markdown body. + +Agents first receive each configured skill's name and description. When a +description applies to the current request, the agent loads that skill's full +instructions for that execution. This keeps unrelated instructions out of the +context while giving the agent the relevant expertise without code changes. + + +**Skills are NOT tools.** This is the most common point of confusion. + +- **Skills** inject *instructions and context* into the agent's prompt. They tell the agent *how to think* about a problem. +- **Tools** give the agent *callable functions* to take action (search, read files, call APIs). + +You often need **both**: skills for expertise, tools for action. They are configured independently and complement each other. + + +--- + +## Quick Start + +### 1. Create a Skill with the CLI + +The CLI is the supported way to create a skill — it scaffolds the directory layout and a valid `SKILL.md` for you: + +```shell Terminal +crewai create skill code-review +``` + +Inside a crew project (where `pyproject.toml` lives) this creates `./skills/code-review/`; outside a project it creates `./code-review/` in the current directory (you can force that behavior with `--no-project` on `crewai create skill`): + +``` +skills/ +└── code-review/ + ├── SKILL.md # Required — instructions (pre-filled template) + ├── references/ # Optional — reference docs + ├── scripts/ # Optional — executable scripts + └── assets/ # Optional — static files +``` + +### 2. Write Your SKILL.md + +```markdown +--- +name: code-review +description: Guidelines for conducting thorough code reviews with focus on security and performance. +metadata: + author: your-team + version: "1.0" +--- + +## Code Review Guidelines + +When reviewing code, follow this checklist: + +1. **Security**: Check for injection vulnerabilities, auth bypasses, and data exposure +2. **Performance**: Look for N+1 queries, unnecessary allocations, and blocking calls +3. **Readability**: Ensure clear naming, appropriate comments, and consistent style +4. **Testing**: Verify adequate test coverage for new functionality + +### Severity Levels +- **Critical**: Security vulnerabilities, data loss risks → block merge +- **Major**: Performance issues, logic errors → request changes +- **Minor**: Style issues, naming suggestions → approve with comments +``` + +### 3. Attach to an Agent + +```python +from crewai import Agent +from crewai_tools import GithubSearchTool, FileReadTool + +reviewer = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["./skills"], # Discovers review skills + tools=[GithubSearchTool(), FileReadTool()], # Lets agent read code +) +``` + +The agent now has both **expertise** (loaded from the relevant skill when +needed) and **capabilities** (from the tools). + +--- + +## Skills + Tools: Working Together + +Here are common patterns showing how skills and tools complement each other: + +### Pattern 1: Skills Only (Domain Expertise, No Actions Needed) + +Use when the agent needs specific instructions but doesn't need to call external services: + +```python +agent = Agent( + role="Technical Writer", + goal="Write clear API documentation", + backstory="Expert technical writer", + skills=["./skills/api-docs-style"], # Writing guidelines and templates + # No tools needed — agent writes based on provided context +) +``` + +### Pattern 2: Tools Only (Actions, No Special Expertise) + +Use when the agent needs to take action but doesn't need domain-specific instructions: + +```python +from crewai_tools import SerperDevTool, ScrapeWebsiteTool + +agent = Agent( + role="Web Researcher", + goal="Find information about a topic", + backstory="Skilled at finding information online", + tools=[SerperDevTool(), ScrapeWebsiteTool()], # Can search and scrape + # No skills needed — general research doesn't need special guidelines +) +``` + +### Pattern 3: Skills + Tools (Expertise AND Actions) + +The most common real-world pattern. The skill provides *how* to approach the work; tools provide *what* the agent can do: + +```python +from crewai_tools import SerperDevTool, FileReadTool, CodeInterpreterTool + +analyst = Agent( + role="Security Analyst", + goal="Audit infrastructure for vulnerabilities", + backstory="Expert in cloud security and compliance", + skills=["./skills/security-audit"], # Audit methodology and checklists + tools=[ + SerperDevTool(), # Research known vulnerabilities + FileReadTool(), # Read config files + CodeInterpreterTool(), # Run analysis scripts + ], +) +``` + +### Pattern 4: Skills + MCPs + +Skills work alongside MCP servers the same way they work with tools: + +```python +agent = Agent( + role="Data Analyst", + goal="Analyze customer data and generate reports", + backstory="Expert data analyst with strong statistical background", + skills=["./skills/data-analysis"], # Analysis methodology + mcps=["https://data-warehouse.example.com/sse"], # Remote data access +) +``` + +### Pattern 5: Skills + Apps + +Skills can guide how an agent uses platform integrations: + +```python +agent = Agent( + role="Customer Support Agent", + goal="Respond to customer inquiries professionally", + backstory="Experienced support representative", + skills=["./skills/support-playbook"], # Response templates and escalation rules + apps=["gmail", "zendesk"], # Can send emails and update tickets +) +``` + +--- + +## Creating, Publishing, and Installing Skills + +Skills have a full lifecycle managed by the CLI: **create them with `crewai create skill`, publish them with `crewai skill publish`** — hand-rolling directories works for local experiments, but the CLI is the intended workflow and keeps your skill layout and frontmatter valid. + + + `crewai skill create` is deprecated and still works with a warning. Use `crewai create skill` instead. + + +### Create + +```shell Terminal +crewai create skill my-skill +``` + +Scaffolds the directory (into `./skills/` inside a crew project) with a template `SKILL.md`, plus empty `scripts/`, `references/`, and `assets/` directories. Edit `SKILL.md` to define the instructions. + +### Publish + +Run from inside the skill directory (where `SKILL.md` is): + +```shell Terminal +cd skills/my-skill +crewai skill publish +``` + +Publishing reads `name`, `description`, and `metadata.version` from the `SKILL.md` frontmatter and pushes the skill to the CrewAI registry. **Published skills are always scoped to your organization** — like tools, only members of the publishing org can see and install them; there is no public visibility. Useful flags: + +| Flag | Effect | +| :--- | :--- | +| `--org ` | Publish under a specific organization (overrides settings). | +| `--force` | Skip git-state validation (uncommitted changes, etc.). | + +### Install + +Install a published skill by its `@org/name` reference: + +```shell Terminal +crewai skill install @acme/code-review +``` + +Inside a crew project the skill lands in `./skills/{name}/`; outside a project it goes to the shared cache at `~/.crewai/skills/{org}/{name}/`. + +Agents can also reference registry skills directly — they resolve from the local cache (or project `skills/` directory) at runtime: + +```python +agent = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["@acme/code-review"], # registry ref, resolved locally +) +``` + +### Pin a Version + +An unpinned reference resolves to the newest published version, so publishing a +new version changes every agent that references it. Append `@` to pin +one instead: + +```python +agent = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["@acme/code-review@1.2.0"], # pinned; a leading "v" also works +) +``` + +A pinned reference re-downloads unless the copy it finds is that exact version — +a pin asks for a specific version rather than hinting at one. A cached skill is +matched on the version recorded when it was installed, so it needs nothing in +its frontmatter; a project-local copy under `skills/` has no such record, so it +is matched on `metadata.version` in its `SKILL.md` frontmatter. Pinning an +unpublished version fails rather than falling back to the latest. + + +Agents from the **Agent Repository** are pinned automatically: the repository +records a version alongside each skill it assigns, and the runtime applies those +pins when it loads the agent. + + +### List + +```shell Terminal +crewai skill list +``` + +Shows installed skills from both the project `./skills/` directory and the global cache, with their versions and paths. + +--- + +## Crew-Level Skills + +Skills can be set on a crew to apply to **all agents**: + +```python +from crewai import Crew + +crew = Crew( + agents=[researcher, writer, reviewer], + tasks=[research_task, write_task, review_task], + skills=["./skills"], # All agents get these skills +) +``` + +Agent-level skills take priority — if the same skill is discovered at both levels, the agent's version is used. + +--- + +## SKILL.md Format + +```markdown +--- +name: my-skill +description: Short description of what this skill does and when to use it. +license: Apache-2.0 # optional +compatibility: crewai>=0.1.0 # optional +metadata: # optional + author: your-name + version: "1.0" +allowed-tools: web-search file-read # optional, experimental +--- + +Instructions for the agent go here. This markdown body is injected +into the agent's prompt when the skill is activated. +``` + +### Frontmatter Fields + +| Field | Required | Description | +| :-------------- | :------- | :----------------------------------------------------------------------- | +| `name` | Yes | 1–64 chars. Lowercase alphanumeric and hyphens. Must match directory name. | +| `description` | Yes | 1–1024 chars. Describes what the skill does and when to use it. | +| `license` | No | License name or reference to a bundled license file. | +| `compatibility` | No | Max 500 chars. Environment requirements (products, packages, network). | +| `metadata` | No | Arbitrary string key-value mapping. | +| `allowed-tools` | No | Space-delimited list of pre-approved tools. Experimental. | + +--- + +## Directory Structure + +``` +my-skill/ +├── SKILL.md # Required — frontmatter + instructions +├── scripts/ # Optional — executable scripts +├── references/ # Optional — reference documents +└── assets/ # Optional — static files (configs, data) +``` + +The directory name must match the `name` field in `SKILL.md`. The `scripts/`, `references/`, and `assets/` directories are available on the skill's `path` for agents that need to reference files directly. + +--- + +## Pre-loading Skills + +For more control, you can discover and activate skills programmatically. +Passing an activated skill makes its instructions always-on: + +```python +from pathlib import Path +from crewai.skills import discover_skills, activate_skill + +# Discover all skills in a directory +skills = discover_skills(Path("./skills")) + +# Activate them (loads full SKILL.md body) +activated = [activate_skill(s) for s in skills] + +# Pass to an agent +agent = Agent( + role="Researcher", + goal="Find relevant information", + backstory="An expert researcher.", + skills=activated, +) +``` + +--- + +## How Skills Are Loaded + +Skills use **progressive disclosure** — only loading what's needed at each stage: + +| Stage | What's loaded | When | +| :--------- | :------------------------------------ | :---------------------------------------- | +| Discovery | Name, description, frontmatter fields | Agent setup or `discover_skills()` | +| Activation | Full SKILL.md body text | Relevant runtime request or `activate_skill()` | +| Resources | Resource directory catalog | Explicit `load_resources()` call | + +With `skills=["./skills"]`, the directory is discovered at setup but the full +instructions are not placed in every prompt. The agent reviews the metadata on +each execution and loads only a skill that applies. The loaded instructions are +scoped to that execution, so skills selected for earlier calls do not accumulate +on the agent. + +Inline skill strings and `Skill` objects already activated with +`activate_skill()` remain always-on. This provides an explicit opt-in when the +instructions should apply to every request. + +--- + +## Skills vs Knowledge + +Both skills and knowledge modify the agent's prompt, but they serve different purposes: + +| Aspect | Skills | Knowledge | +| :--- | :--- | :--- | +| **What it provides** | Instructions, procedures, guidelines | Facts, data, information | +| **How it's stored** | Markdown files (SKILL.md) | Embedded in vector store (ChromaDB) | +| **How it's retrieved** | Entire body injected into prompt | Semantic search finds relevant chunks | +| **Best for** | Methodology, checklists, style guides | Company docs, product info, reference data | +| **Set via** | `skills=["./skills"]` | `knowledge_sources=[source]` | + +**Rule of thumb:** If the agent needs to follow a *process*, use a skill. If the agent needs to reference *data*, use knowledge. + +--- + +## Common Questions + + + + It depends on your use case. Skills and tools are **independent** — you can use either, both, or neither. + + - **Skills alone**: When the agent needs expertise but no external actions (e.g., writing with style guidelines) + - **Tools alone**: When the agent needs actions but no special methodology (e.g., simple web search) + - **Both**: When the agent needs expertise AND actions (e.g., security audit with specific checklists AND ability to scan code) + + + + **No.** The `allowed-tools` field in SKILL.md is experimental metadata only — it does not provision or inject any tools. You must always set tools separately via `tools=[]`, `mcps=[]`, or `apps=[]`. + + + + The agent-level skill takes priority. Skills are deduplicated by name — the agent's skills are processed first, so if the same skill name appears at both levels, the agent's version is used. + + + + There's a soft warning at 50,000 characters, but no hard limit. Keep skills focused and concise for best results — large prompt injections can dilute the agent's attention. + + diff --git a/docs/v1.15.13/en/concepts/streaming.mdx b/docs/v1.15.13/en/concepts/streaming.mdx new file mode 100644 index 0000000000..9813864b0c --- /dev/null +++ b/docs/v1.15.13/en/concepts/streaming.mdx @@ -0,0 +1,137 @@ +--- +title: Streaming +description: Understand CrewAI's streaming model for Flows, direct LLM calls, tools, and conversational turns. +icon: radio +mode: "wide" +--- + +## Overview + +Streaming lets your application receive execution updates while work is still running. Instead of waiting for the final result, you can render LLM tokens, tool activity, Flow lifecycle events, and conversation messages as they happen. + +CrewAI has two streaming surfaces: + +| Surface | Used by | Output | +|---------|---------|--------| +| Frame streaming | Flows, direct LLM calls, conversational turns | Ordered `StreamFrame` objects | +| Crew chunk streaming | Crews with `stream=True` | `CrewStreamingOutput` chunks | + +For new runtime integrations, UIs, terminal apps, service bridges, and conversational surfaces, use frame streaming. It provides one stable event envelope across the runtime. + +## StreamFrame + +A `StreamFrame` is the common object emitted by streamable runtimes: + +```python +frame.id # unique frame id +frame.seq # execution-local order, when available +frame.type # source event type, such as "llm_stream_chunk" +frame.channel # "llm", "flow", "tools", "messages", "lifecycle", or "custom" +frame.namespace # source/runtime namespace +frame.timestamp # event timestamp +frame.parent_id # parent event id, when available +frame.previous_id # previous event id, when available +frame.data # structured event payload +frame.event # alias for frame.data +frame.content # printable text for token-like frames, otherwise "" +``` + +The important fields for most consumers are: + +| Field | Use it for | +|-------|------------| +| `channel` | Routing frames to the right UI region | +| `type` | Handling a specific event inside a channel | +| `content` | Printing token-like text | +| `event` | Reading structured metadata, such as tool names or message roles | +| `seq` | Preserving execution order | + +## Channels + +Frames are grouped into high-level channels: + +| Channel | Contains | +|---------|----------| +| `llm` | LLM call lifecycle, text chunks, and thinking chunks | +| `flow` | Flow lifecycle, method execution, routing, pause, and resume events | +| `tools` | Tool usage start, finish, and error events | +| `messages` | Conversation transcript events | +| `lifecycle` | Runtime lifecycle events that do not belong to another channel | +| `custom` | Events that do not map to a built-in channel | + +The stream itself remains one ordered timeline. Channel projections let consumers focus on only part of that timeline. + +```mermaid +flowchart LR + A["flow
flow_started"] --> B["llm
llm_call_started"] + B --> C["llm
llm_stream_chunk"] + C --> D["tools
tool_usage_started"] + D --> E["tools
tool_usage_finished"] + E --> F["llm
llm_stream_chunk"] + F --> G["flow
flow_finished"] +``` + +## Stream Sessions + +Frame streaming returns a stream session: + +```python +stream = flow.stream_events(inputs={"topic": "AI agents"}) +``` + +The session is both an iterator and the holder for the final result: + +```python +with stream: + for frame in stream: + print(frame.content, end="", flush=True) + +result = stream.result +``` + +Consume the stream before reading `stream.result`. Reading the result too early raises an error because the runtime may still be producing frames. + +## Channel Projections + +Use channel projections when you only need one kind of frame: + +```python +with flow.stream_events(inputs={"topic": "AI agents"}) as stream: + for frame in stream.llm: + print(frame.content, end="", flush=True) + +result = stream.result +``` + +Available projections: + +| Projection | Frames | +|------------|--------| +| `stream.events` | All frames | +| `stream.llm` | LLM frames | +| `stream.flow` | Flow frames | +| `stream.tools` | Tool frames | +| `stream.messages` | Conversation message frames | +| `stream.interleave([...])` | Selected channels in relative order | + +## Entrypoints + +Use the entrypoint that matches the runtime you are streaming: + +| Runtime | Streaming entrypoint | +|---------|----------------------| +| Flow | `flow.stream_events(...)` | +| Flow with `stream=True` | `flow.kickoff(...)` returns a stream session | +| Async Flow | `flow.astream(...)` or `await flow.kickoff_async(...)` when `stream=True` | +| Direct LLM call | `llm.stream_events(...)` | +| Conversational Flow turn | `flow.stream_turn(...)` | +| Crew | `Crew(..., stream=True).kickoff(...)` returns `CrewStreamingOutput` | + +Direct `llm.call(...)` still returns the final assembled LLM result. Use `llm.stream_events(...)` when you want to iterate over LLM chunks as they arrive. + +## Related Guides + +- [Consuming Streams](/edge/en/learn/consuming-streams) +- [Streaming Runtime Contract](/edge/en/learn/streaming-runtime-contract) +- [Streaming Flow Execution](/edge/en/learn/streaming-flow-execution) +- [Streaming Crew Execution](/edge/en/learn/streaming-crew-execution) diff --git a/docs/v1.15.13/en/concepts/tasks.mdx b/docs/v1.15.13/en/concepts/tasks.mdx new file mode 100644 index 0000000000..6a11465b5a --- /dev/null +++ b/docs/v1.15.13/en/concepts/tasks.mdx @@ -0,0 +1,1036 @@ +--- +title: Tasks +description: Detailed guide on managing and creating tasks within the CrewAI framework. +icon: list-check +mode: "wide" +--- + +## Overview + +In the CrewAI framework, a `Task` is a specific assignment completed by an `Agent`. + +Tasks provide all necessary details for execution, such as a description, the agent responsible, required tools, and more, facilitating a wide range of action complexities. + +Tasks within CrewAI can be collaborative, requiring multiple agents to work together. This is managed through the task properties and orchestrated by the Crew's process, enhancing teamwork and efficiency. + + +CrewAI AMP includes a Visual Task Builder in Crew Studio that simplifies complex task creation and chaining. Design your task flows visually and test them in real-time without writing code. + +![Task Builder Screenshot](/images/enterprise/crew-studio-interface.png) + +The Visual Task Builder enables: + +- Drag-and-drop task creation +- Visual task dependencies and flow +- Real-time testing and validation +- Easy sharing and collaboration + + +### Task Execution Flow + +Tasks can be executed in two ways: + +- **Sequential**: Tasks are executed in the order they are defined +- **Hierarchical**: Tasks are assigned to agents based on their roles and expertise + +The execution flow is defined when creating the crew: + +```python Code +crew = Crew( + agents=[agent1, agent2], + tasks=[task1, task2], + process=Process.sequential # or Process.hierarchical +) +``` + +## 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. | +| **Agent** _(optional)_ | `agent` | `Optional[BaseAgent]` | The agent responsible for executing the task. | +| **Tools** _(optional)_ | `tools` | `List[BaseTool]` | The tools/resources the agent is limited to use for this task. | +| **Context** _(optional)_ | `context` | `Optional[List["Task"]]` | Other tasks whose outputs will be used as context for this task. | +| **Async Execution** _(optional)_ | `async_execution` | `Optional[bool]` | Whether the task should be executed asynchronously. Defaults to False. | +| **Human Input** _(optional)_ | `human_input` | `Optional[bool]` | Whether the task should have a human review the final answer of the agent. Defaults to False. | +| **Markdown** _(optional)_ | `markdown` | `Optional[bool]` | Whether the task should instruct the agent to return the final answer formatted in Markdown. Defaults to False. | +| **Config** _(optional)_ | `config` | `Optional[Dict[str, Any]]` | Task-specific configuration parameters. | +| **Output File** _(optional)_ | `output_file` | `Optional[str]` | File path for storing the task output. | +| **Create Directory** _(optional)_ | `create_directory` | `Optional[bool]` | Whether to create the directory for output_file if it doesn't exist. Defaults to True. | +| **Output JSON** _(optional)_ | `output_json` | `Optional[Type[BaseModel]]` | A Pydantic model to structure the JSON output. | +| **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 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. | + + + The task attribute `max_retries` is deprecated and will be removed in v1.0.0. + Use `guardrail_max_retries` instead to control retry attempts when a guardrail + fails. + + +## Creating Tasks + +There are two common ways to create tasks in CrewAI: using **JSONC project configuration (recommended for new crews)** or defining them **directly in code**. + +### JSONC Configuration (Recommended) + +New projects created with `crewai create crew ` define tasks in `crew.jsonc`. The `agents` array points to files in `agents/`, and the `tasks` array defines the ordered work the crew should run. + +After creating your CrewAI project as outlined in the [Installation](/en/installation) section, edit the generated `crew.jsonc`. + + +Use `{placeholder}` values in task `description`, `expected_output`, and `output_file`. Put defaults in the top-level `inputs` object; `crewai run` prompts for any missing values. + + +Here's an example `crew.jsonc` with two ordered tasks: + +````jsonc crew.jsonc +{ + "name": "Research Crew", + "agents": ["researcher", "reporting_analyst"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research about {topic}. Include current and relevant information.", + "expected_output": "A list of the most relevant information about {topic}.", + "agent": "researcher" + }, + { + "name": "reporting_task", + "description": "Review the research and expand it into a detailed report.", + "expected_output": "A polished markdown report without fenced code blocks.", + "agent": "reporting_analyst", + "context": ["research_task"], + "markdown": true, + "output_file": "report.md" + } + ], + "inputs": { + "topic": "AI Agents" + } +} +```` + +Each task must include `description` and `expected_output`. The `agent` value should match an agent name listed in `agents`. `context` is a list of prior task names; forward references are rejected so sequential context stays explicit. + +Task entries support any public `Task` field. Common fields include `name`, `agent`, `context`, `output_file`, `tools`, `human_input`, `async_execution`, `guardrail`, `guardrails`, `guardrail_max_retries`, `markdown`, `input_files`, `output_json`, `output_pydantic`, `response_model`, and `converter_cls`. Use `"type": "ConditionalTask"` with a `condition` field for conditional tasks. + +### Classic YAML Configuration + +Classic projects created with `crewai create crew --classic` use `config/tasks.yaml` and a `@CrewBase` class in `crew.py`. This remains supported for existing YAML projects or teams that prefer decorator-based Python wiring. + +### Direct Code Definition (Alternative) + +Alternatively, you can define tasks directly in your code without using YAML configuration: + +```python task.py +from crewai import Task + +research_task = Task( + description=""" + Conduct a thorough research about AI Agents. + Make sure you find any interesting and relevant information given + the current year is 2025. + """, + expected_output=""" + A list with 10 bullet points of the most relevant information about AI Agents + """, + agent=researcher +) + +reporting_task = Task( + description=""" + Review the context you got and expand each topic into a full section for a report. + Make sure the report is detailed and contains any and all relevant information. + """, + expected_output=""" + A fully fledge reports with the mains topics, each with a full section of information. + """, + agent=reporting_analyst, + markdown=True, # Enable markdown formatting for the final output + output_file="report.md" +) +``` + + + Directly specify an `agent` for assignment or let the `hierarchical` CrewAI's + process decide based on roles, availability, etc. + + +## Task Output + +Understanding task outputs is crucial for building effective AI workflows. CrewAI provides a structured way to handle task results through the `TaskOutput` class, which supports multiple output formats and can be easily passed between tasks. + +The output of a task in CrewAI framework is encapsulated within the `TaskOutput` class. This class provides a structured way to access results of a task, including various formats such as raw output, JSON, and Pydantic models. + +By default, the `TaskOutput` will only include the `raw` output. A `TaskOutput` will only include the `pydantic` or `json_dict` output if the original `Task` object was configured with `output_pydantic` or `output_json`, respectively. + +### Task Output Attributes + +| Attribute | Parameters | Type | Description | +| :---------------- | :-------------- | :------------------------- | :------------------------------------------------------------------------------------------------- | +| **Description** | `description` | `str` | Description of the task. | +| **Summary** | `summary` | `Optional[str]` | Summary of the task, auto-generated from the first 10 words of the description. | +| **Raw** | `raw` | `str` | The raw output of the task. This is the default format for the output. | +| **Pydantic** | `pydantic` | `Optional[BaseModel]` | A Pydantic model object representing the structured output of the task. | +| **JSON Dict** | `json_dict` | `Optional[Dict[str, Any]]` | A dictionary representing the JSON output of the task. | +| **Agent** | `agent` | `str` | The agent that executed the task. | +| **Output Format** | `output_format` | `OutputFormat` | The format of the task output, with options including RAW, JSON, and Pydantic. The default is RAW. | +| **Messages** | `messages` | `list[LLMMessage]` | The messages from the last task execution. | + +### Task Methods and Properties + +| Method/Property | Description | +| :-------------- | :------------------------------------------------------------------------------------------------ | +| **json** | Returns the JSON string representation of the task output if the output format is JSON. | +| **to_dict** | Converts the JSON and Pydantic outputs to a dictionary. | +| **str** | Returns the string representation of the task output, prioritizing Pydantic, then JSON, then raw. | + +### Accessing Task Outputs + +Once a task has been executed, its output can be accessed through the `output` attribute of the `Task` object. The `TaskOutput` class provides various ways to interact with and present this output. + +#### Example + +```python Code +# Example task +task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +# Execute the crew +crew = Crew( + agents=[research_agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() + +# Accessing the task output +task_output = task.output + +print(f"Task Description: {task_output.description}") +print(f"Task Summary: {task_output.summary}") +print(f"Raw Output: {task_output.raw}") +if task_output.json_dict: + print(f"JSON Output: {json.dumps(task_output.json_dict, indent=2)}") +if task_output.pydantic: + print(f"Pydantic Output: {task_output.pydantic}") +``` + +## Markdown Output Formatting + +The `markdown` parameter enables automatic markdown formatting for task outputs. When set to `True`, the task will instruct the agent to format the final answer using proper Markdown syntax. + +### Using Markdown Formatting + +```python Code +# Example task with markdown formatting enabled +formatted_task = Task( + description="Create a comprehensive report on AI trends", + expected_output="A well-structured report with headers, sections, and bullet points", + agent=reporter_agent, + markdown=True # Enable automatic markdown formatting +) +``` + +When `markdown=True`, the agent will receive additional instructions to format the output using: + +- `#` for headers +- `**text**` for bold text +- `*text*` for italic text +- `-` or `*` for bullet points +- `` `code` `` for inline code +- ` `language ``` for code blocks + +### YAML Configuration with Markdown + +```yaml tasks.yaml +analysis_task: + description: > + Analyze the market data and create a detailed report + expected_output: > + A comprehensive analysis with charts and key findings + agent: analyst + markdown: true # Enable markdown formatting + output_file: analysis.md +``` + +### Benefits of Markdown Output + +- **Consistent Formatting**: Ensures all outputs follow proper markdown conventions +- **Better Readability**: Structured content with headers, lists, and emphasis +- **Documentation Ready**: Output can be directly used in documentation systems +- **Cross-Platform Compatibility**: Markdown is universally supported + + + The markdown formatting instructions are automatically added to the task + prompt when `markdown=True`, so you don't need to specify formatting + requirements in your task description. + + +## Task Dependencies and Context + +Tasks can depend on the output of other tasks using the `context` attribute. For example: + +```python Code +research_task = Task( + description="Research the latest developments in AI", + expected_output="A list of recent AI developments", + agent=researcher +) + +analysis_task = Task( + description="Analyze the research findings and identify key trends", + expected_output="Analysis report of AI trends", + agent=analyst, + context=[research_task] # This task will wait for research_task to complete +) +``` + +## Task Guardrails + +Task guardrails provide a way to validate and transform task outputs before they +are passed to the next task. This feature helps ensure data quality and provides +feedback to agents when their output doesn't meet specific criteria. + +CrewAI supports two types of guardrails: + +1. **Function-based guardrails**: Python functions with custom validation logic, giving you complete control over the validation process and ensuring reliable, deterministic results. + +2. **LLM-based guardrails**: String descriptions that use the agent's LLM to validate outputs based on natural language criteria. These are ideal for complex or subjective validation requirements. + +### Function-Based Guardrails + +To add a function-based guardrail to a task, provide a validation function through the `guardrail` parameter: + +```python Code +from typing import Tuple, Union, Dict, Any +from crewai import TaskOutput + +def validate_blog_content(result: TaskOutput) -> Tuple[bool, Any]: + """Validate blog content meets requirements.""" + try: + # Check word count + word_count = len(result.raw.split()) + if word_count > 200: + return (False, "Blog content exceeds 200 words") + + # Additional validation logic here + return (True, result.raw.strip()) + except Exception as e: + return (False, "Unexpected error during validation") + +blog_task = Task( + description="Write a blog post about AI", + expected_output="A blog post under 200 words", + agent=blog_agent, + guardrail=validate_blog_content # Add the guardrail function +) +``` + +### LLM-Based Guardrails (String Descriptions) + +Instead of writing custom validation functions, you can use string descriptions that leverage LLM-based validation. When you provide a string to the `guardrail` or `guardrails` parameter, CrewAI automatically creates an `LLMGuardrail` that uses the agent's LLM to validate the output based on your description. + +**Requirements**: + +- The task must have an `agent` assigned (the guardrail uses the agent's LLM) +- Provide a clear, descriptive string explaining the validation criteria + +```python Code +from crewai import Task + +# Single LLM-based guardrail +blog_task = Task( + description="Write a blog post about AI", + expected_output="A blog post under 200 words", + agent=blog_agent, + guardrail="The blog post must be under 200 words and contain no technical jargon" +) +``` + +LLM-based guardrails are particularly useful for: + +- **Complex validation logic** that's difficult to express programmatically +- **Subjective criteria** like tone, style, or quality assessments +- **Natural language requirements** that are easier to describe than code + +The LLM guardrail will: + +1. Analyze the task output against your description +2. Return `(True, output)` if the output complies with the criteria +3. Return `(False, feedback)` with specific feedback if validation fails + +**Example with detailed validation criteria**: + +```python Code +research_task = Task( + description="Research the latest developments in quantum computing", + expected_output="A comprehensive research report", + agent=researcher_agent, + guardrail=""" + The research report must: + - Be at least 1000 words long + - Include at least 5 credible sources + - Cover both technical and practical applications + - Be written in a professional, academic tone + - Avoid speculation or unverified claims + """ +) +``` + +### Multiple Guardrails + +You can apply multiple guardrails to a task using the `guardrails` parameter. Multiple guardrails are executed sequentially, with each guardrail receiving the output from the previous one. This allows you to chain validation and transformation steps. + +The `guardrails` parameter accepts: + +- A list of guardrail functions or string descriptions +- A single guardrail function or string (same as `guardrail`) + +**Note**: If `guardrails` is provided, it takes precedence over `guardrail`. The `guardrail` parameter will be ignored when `guardrails` is set. + +```python Code +from typing import Tuple, Any +from crewai import TaskOutput, Task + +def validate_word_count(result: TaskOutput) -> Tuple[bool, Any]: + """Validate word count is within limits.""" + word_count = len(result.raw.split()) + if word_count < 100: + return (False, f"Content too short: {word_count} words. Need at least 100 words.") + if word_count > 500: + return (False, f"Content too long: {word_count} words. Maximum is 500 words.") + return (True, result.raw) + +def validate_no_profanity(result: TaskOutput) -> Tuple[bool, Any]: + """Check for inappropriate language.""" + profanity_words = ["badword1", "badword2"] # Example list + content_lower = result.raw.lower() + for word in profanity_words: + if word in content_lower: + return (False, f"Inappropriate language detected: {word}") + return (True, result.raw) + +def format_output(result: TaskOutput) -> Tuple[bool, Any]: + """Format and clean the output.""" + formatted = result.raw.strip() + # Capitalize first letter + formatted = formatted[0].upper() + formatted[1:] if formatted else formatted + return (True, formatted) + +# Apply multiple guardrails sequentially +blog_task = Task( + description="Write a blog post about AI", + expected_output="A well-formatted blog post between 100-500 words", + agent=blog_agent, + guardrails=[ + validate_word_count, # First: validate length + validate_no_profanity, # Second: check content + format_output # Third: format the result + ], + guardrail_max_retries=3 +) +``` + +In this example, the guardrails execute in order: + +1. `validate_word_count` checks the word count +2. `validate_no_profanity` checks for inappropriate language (using the output from step 1) +3. `format_output` formats the final result (using the output from step 2) + +If any guardrail fails, the error is sent back to the agent, and the task is retried up to `guardrail_max_retries` times. + +**Mixing function-based and LLM-based guardrails**: + +You can combine both function-based and string-based guardrails in the same list: + +```python Code +from typing import Tuple, Any +from crewai import TaskOutput, Task + +def validate_word_count(result: TaskOutput) -> Tuple[bool, Any]: + """Validate word count is within limits.""" + word_count = len(result.raw.split()) + if word_count < 100: + return (False, f"Content too short: {word_count} words. Need at least 100 words.") + if word_count > 500: + return (False, f"Content too long: {word_count} words. Maximum is 500 words.") + return (True, result.raw) + +# Mix function-based and LLM-based guardrails +blog_task = Task( + description="Write a blog post about AI", + expected_output="A well-formatted blog post between 100-500 words", + agent=blog_agent, + guardrails=[ + validate_word_count, # Function-based: precise word count check + "The content must be engaging and suitable for a general audience", # LLM-based: subjective quality check + "The writing style should be clear, concise, and free of technical jargon" # LLM-based: style validation + ], + guardrail_max_retries=3 +) +``` + +This approach combines the precision of programmatic validation with the flexibility of LLM-based assessment for subjective criteria. + +### Guardrail Function Requirements + +1. **Function Signature**: + + - Must accept exactly one parameter (the task output) + - Should return a tuple of `(bool, Any)` + - Type hints are recommended but optional + +2. **Return Values**: + - On success: it returns a tuple of `(bool, Any)`. For example: `(True, validated_result)` + - On Failure: it returns a tuple of `(bool, str)`. For example: `(False, "Error message explain the failure")` + +### Error Handling Best Practices + +1. **Structured Error Responses**: + +```python Code +from crewai import TaskOutput, LLMGuardrail + +def validate_with_context(result: TaskOutput) -> Tuple[bool, Any]: + try: + # Main validation logic + validated_data = perform_validation(result) + return (True, validated_data) + except ValidationError as e: + return (False, f"VALIDATION_ERROR: {str(e)}") + except Exception as e: + return (False, str(e)) +``` + +2. **Error Categories**: + + - Use specific error codes + - Include relevant context + - Provide actionable feedback + +3. **Validation Chain**: + +```python Code +from typing import Any, Dict, List, Tuple, Union +from crewai import TaskOutput + +def complex_validation(result: TaskOutput) -> Tuple[bool, Any]: + """Chain multiple validation steps.""" + # Step 1: Basic validation + if not result: + return (False, "Empty result") + + # Step 2: Content validation + try: + validated = validate_content(result) + if not validated: + return (False, "Invalid content") + + # Step 3: Format validation + formatted = format_output(validated) + return (True, formatted) + except Exception as e: + return (False, str(e)) +``` + +### Handling Guardrail Results + +When a guardrail returns `(False, error)`: + +1. The error is sent back to the agent +2. The agent attempts to fix the issue +3. The process repeats until: + - The guardrail returns `(True, result)` + - Maximum retries are reached (`guardrail_max_retries`) + +Example with retry handling: + +```python Code +from typing import Optional, Tuple, Union +from crewai import TaskOutput, Task + +def validate_json_output(result: TaskOutput) -> Tuple[bool, Any]: + """Validate and parse JSON output.""" + try: + # Try to parse as JSON + data = json.loads(result) + return (True, data) + except json.JSONDecodeError as e: + return (False, "Invalid JSON format") + +task = Task( + description="Generate a JSON report", + expected_output="A valid JSON object", + agent=analyst, + guardrail=validate_json_output, + guardrail_max_retries=3 # Limit retry attempts +) +``` + +## Getting Structured Consistent Outputs from Tasks + + + It's also important to note that the output of the final task of a crew + becomes the final output of the actual crew itself. + + +### Using `output_pydantic` + +The `output_pydantic` property allows you to define a Pydantic model that the task output should conform to. This ensures that the output is not only structured but also validated according to the Pydantic model. + +Here's an example demonstrating how to use output_pydantic: + +```python Code +import json + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + + +class Blog(BaseModel): + title: str + content: str + + +blog_agent = Agent( + role="Blog Content Generator Agent", + goal="Generate a blog title and content", + backstory="""You are an expert content creator, skilled in crafting engaging and informative blog posts.""", + verbose=False, + allow_delegation=False, + llm="gpt-4o", +) + +task1 = Task( + description="""Create a blog title and content on a given topic. Make sure the content is under 200 words.""", + expected_output="A compelling blog title and well-written content.", + agent=blog_agent, + output_pydantic=Blog, +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[blog_agent], + tasks=[task1], + verbose=True, + process=Process.sequential, +) + +result = crew.kickoff() + +# Option 1: Accessing Properties Using Dictionary-Style Indexing +print("Accessing Properties - Option 1") +title = result["title"] +content = result["content"] +print("Title:", title) +print("Content:", content) + +# Option 2: Accessing Properties Directly from the Pydantic Model +print("Accessing Properties - Option 2") +title = result.pydantic.title +content = result.pydantic.content +print("Title:", title) +print("Content:", content) + +# Option 3: Accessing Properties Using the to_dict() Method +print("Accessing Properties - Option 3") +output_dict = result.to_dict() +title = output_dict["title"] +content = output_dict["content"] +print("Title:", title) +print("Content:", content) + +# Option 4: Printing the Entire Blog Object +print("Accessing Properties - Option 5") +print("Blog:", result) + +``` + +In this example: + +- A Pydantic model Blog is defined with title and content fields. +- The task task1 uses the output_pydantic property to specify that its output should conform to the Blog model. +- After executing the crew, you can access the structured output in multiple ways as shown. + +#### Explanation of Accessing the Output + +1. Dictionary-Style Indexing: You can directly access the fields using result["field_name"]. This works because the CrewOutput class implements the **getitem** method. +2. Directly from Pydantic Model: Access the attributes directly from the result.pydantic object. +3. Using to_dict() Method: Convert the output to a dictionary and access the fields. +4. Printing the Entire Object: Simply print the result object to see the structured output. + +### Using `output_json` + +The `output_json` property allows you to define the expected output in JSON format. This ensures that the task's output is a valid JSON structure that can be easily parsed and used in your application. + +Here's an example demonstrating how to use `output_json`: + +```python Code +import json + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + + +# Define the Pydantic model for the blog +class Blog(BaseModel): + title: str + content: str + + +# Define the agent +blog_agent = Agent( + role="Blog Content Generator Agent", + goal="Generate a blog title and content", + backstory="""You are an expert content creator, skilled in crafting engaging and informative blog posts.""", + verbose=False, + allow_delegation=False, + llm="gpt-4o", +) + +# Define the task with output_json set to the Blog model +task1 = Task( + description="""Create a blog title and content on a given topic. Make sure the content is under 200 words.""", + expected_output="A JSON object with 'title' and 'content' fields.", + agent=blog_agent, + output_json=Blog, +) + +# Instantiate the crew with a sequential process +crew = Crew( + agents=[blog_agent], + tasks=[task1], + verbose=True, + process=Process.sequential, +) + +# Kickoff the crew to execute the task +result = crew.kickoff() + +# Option 1: Accessing Properties Using Dictionary-Style Indexing +print("Accessing Properties - Option 1") +title = result["title"] +content = result["content"] +print("Title:", title) +print("Content:", content) + +# Option 2: Printing the Entire Blog Object +print("Accessing Properties - Option 2") +print("Blog:", result) +``` + +In this example: + +- A Pydantic model Blog is defined with title and content fields, which is used to specify the structure of the JSON output. +- The task task1 uses the output_json property to indicate that it expects a JSON output conforming to the Blog model. +- After executing the crew, you can access the structured JSON output in two ways as shown. + +#### Explanation of Accessing the Output + +1. Accessing Properties Using Dictionary-Style Indexing: You can access the fields directly using result["field_name"]. This is possible because the CrewOutput class implements the **getitem** method, allowing you to treat the output like a dictionary. In this option, we're retrieving the title and content from the result. +2. Printing the Entire Blog Object: By printing result, you get the string representation of the CrewOutput object. Since the **str** method is implemented to return the JSON output, this will display the entire output as a formatted string representing the Blog object. + +--- + +By using output_pydantic or output_json, you ensure that your tasks produce outputs in a consistent and structured format, making it easier to process and utilize the data within your application or across multiple tasks. + +## Integrating Tools with Tasks + +Leverage tools from the [CrewAI Toolkit](https://github.com/joaomdmoura/crewai-tools) and [LangChain Tools](https://python.langchain.com/docs/integrations/tools) for enhanced task performance and agent interaction. + +## Creating a Task with Tools + +```python Code +import os +os.environ["OPENAI_API_KEY"] = "Your Key" +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key + +from crewai import Agent, Task, Crew +from crewai_tools import SerperDevTool + +research_agent = Agent( + role='Researcher', + goal='Find and summarize the latest AI news', + backstory="""You're a researcher at a large company. + You're responsible for analyzing data and providing insights + to the business.""", + verbose=True +) + +# to perform a semantic search for a specified query from a text's content across the internet +search_tool = SerperDevTool() + +task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +crew = Crew( + agents=[research_agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() +print(result) +``` + +This demonstrates how tasks with specific tools can override an agent's default set for tailored task execution. + +## Referring to Other Tasks + +In CrewAI, the output of one task is automatically relayed into the next one, but you can specifically define what tasks' output, including multiple, should be used as context for another task. + +This is useful when you have a task that depends on the output of another task that is not performed immediately after it. This is done through the `context` attribute of the task: + +```python Code +# ... + +research_ai_task = Task( + description="Research the latest developments in AI", + expected_output="A list of recent AI developments", + async_execution=True, + agent=research_agent, + tools=[search_tool] +) + +research_ops_task = Task( + description="Research the latest developments in AI Ops", + expected_output="A list of recent AI Ops developments", + async_execution=True, + agent=research_agent, + tools=[search_tool] +) + +write_blog_task = Task( + description="Write a full blog post about the importance of AI and its latest news", + expected_output="Full blog post that is 4 paragraphs long", + agent=writer_agent, + context=[research_ai_task, research_ops_task] +) + +#... +``` + +## Asynchronous Execution + +You can define a task to be executed asynchronously. This means that the crew will not wait for it to be completed to continue with the next task. This is useful for tasks that take a long time to be completed, or that are not crucial for the next tasks to be performed. + +You can then use the `context` attribute to define in a future task that it should wait for the output of the asynchronous task to be completed. + +```python Code +#... + +list_ideas = Task( + description="List of 5 interesting ideas to explore for an article about AI.", + expected_output="Bullet point list of 5 ideas for an article.", + agent=researcher, + async_execution=True # Will be executed asynchronously +) + +list_important_history = Task( + description="Research the history of AI and give me the 5 most important events.", + expected_output="Bullet point list of 5 important events.", + agent=researcher, + async_execution=True # Will be executed asynchronously +) + +write_article = Task( + description="Write an article about AI, its history, and interesting ideas.", + expected_output="A 4 paragraph article about AI.", + agent=writer, + context=[list_ideas, list_important_history] # Will wait for the output of the two tasks to be completed +) + +#... +``` + +## Callback Mechanism + +The callback function is executed after the task is completed, allowing for actions or notifications to be triggered based on the task's outcome. + +```python Code +# ... + +def callback_function(output: TaskOutput): + # Do something after the task is completed + # Example: Send an email to the manager + print(f""" + Task completed! + Task: {output.description} + Output: {output.raw} + """) + +research_task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool], + callback=callback_function +) + +#... +``` + +## Accessing a Specific Task Output + +Once a crew finishes running, you can access the output of a specific task by using the `output` attribute of the task object: + +```python Code +# ... +task1 = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +#... + +crew = Crew( + agents=[research_agent], + tasks=[task1, task2, task3], + verbose=True +) + +result = crew.kickoff() + +# Returns a TaskOutput object with the description and results of the task +print(f""" + Task completed! + Task: {task1.output.description} + Output: {task1.output.raw} +""") +``` + +## Tool Override Mechanism + +Specifying tools in a task allows for dynamic adaptation of agent capabilities, emphasizing CrewAI's flexibility. + +## Error Handling and Validation Mechanisms + +While creating and executing tasks, certain validation mechanisms are in place to ensure the robustness and reliability of task attributes. These include but are not limited to: + +- Ensuring only one output type is set per task to maintain clear output expectations. +- Preventing the manual assignment of the `id` attribute to uphold the integrity of the unique identifier system. + +These validations help in maintaining the consistency and reliability of task executions within the crewAI framework. + +## Creating Directories when Saving Files + +The `create_directory` parameter controls whether CrewAI should automatically create directories when saving task outputs to files. This feature is particularly useful for organizing outputs and ensuring that file paths are correctly structured, especially when working with complex project hierarchies. + +### Default Behavior + +By default, `create_directory=True`, which means CrewAI will automatically create any missing directories in the output file path: + +```python Code +# Default behavior - directories are created automatically +report_task = Task( + description='Generate a comprehensive market analysis report', + expected_output='A detailed market analysis with charts and insights', + agent=analyst_agent, + output_file='reports/2025/market_analysis.md', # Creates 'reports/2025/' if it doesn't exist + markdown=True +) +``` + +### Disabling Directory Creation + +If you want to prevent automatic directory creation and ensure that the directory already exists, set `create_directory=False`: + +```python Code +# Strict mode - directory must already exist +strict_output_task = Task( + description='Save critical data that requires existing infrastructure', + expected_output='Data saved to pre-configured location', + agent=data_agent, + output_file='secure/vault/critical_data.json', + create_directory=False # Will raise RuntimeError if 'secure/vault/' doesn't exist +) +``` + +### YAML Configuration + +You can also configure this behavior in your YAML task definitions: + +```yaml tasks.yaml +analysis_task: + description: > + Generate quarterly financial analysis + expected_output: > + A comprehensive financial report with quarterly insights + agent: financial_analyst + output_file: reports/quarterly/q4_2024_analysis.pdf + create_directory: true # Automatically create 'reports/quarterly/' directory + +audit_task: + description: > + Perform compliance audit and save to existing audit directory + expected_output: > + A compliance audit report + agent: auditor + output_file: audit/compliance_report.md + create_directory: false # Directory must already exist +``` + +### Use Cases + +**Automatic Directory Creation (`create_directory=True`):** + +- Development and prototyping environments +- Dynamic report generation with date-based folders +- Automated workflows where directory structure may vary +- Multi-tenant applications with user-specific folders + +**Manual Directory Management (`create_directory=False`):** + +- Production environments with strict file system controls +- Security-sensitive applications where directories must be pre-configured +- Systems with specific permission requirements +- Compliance environments where directory creation is audited + +### Error Handling + +When `create_directory=False` and the directory doesn't exist, CrewAI will raise a `RuntimeError`: + +```python Code +try: + result = crew.kickoff() +except RuntimeError as e: + # Handle missing directory error + print(f"Directory creation failed: {e}") + # Create directory manually or use fallback location +``` + +Check out the video below to see how to use structured outputs in CrewAI: + + + +## Conclusion + +Tasks are the driving force behind the actions of agents in CrewAI. +By properly defining tasks and their outcomes, you set the stage for your AI agents to work effectively, either independently or as a collaborative unit. +Equipping tasks with appropriate tools, understanding the execution process, and following robust validation practices are crucial for maximizing CrewAI's potential, +ensuring agents are effectively prepared for their assignments and that tasks are executed as intended. diff --git a/docs/v1.15.13/en/concepts/testing.mdx b/docs/v1.15.13/en/concepts/testing.mdx new file mode 100644 index 0000000000..dbac110b43 --- /dev/null +++ b/docs/v1.15.13/en/concepts/testing.mdx @@ -0,0 +1,49 @@ +--- +title: Testing +description: Learn how to test your CrewAI Crew and evaluate their performance. +icon: vial +mode: "wide" +--- + +## Overview + +Testing is a crucial part of the development process, and it is essential to ensure that your crew is performing as expected. With crewAI, you can easily test your crew and evaluate its performance using the built-in testing capabilities. + +### Using the Testing Feature + +We added the CLI command `crewai test` to make it easy to test your crew. This command will run your crew for a specified number of iterations and provide detailed performance metrics. The parameters are `n_iterations` and `model`, which are optional and default to 2 and `gpt-4o-mini` respectively. For now, the only provider available is OpenAI. + +```bash +crewai test +``` + +If you want to run more iterations or use a different model, you can specify the parameters like this: + +```bash +crewai test --n_iterations 5 --model gpt-4o +``` + +or using the short forms: + +```bash +crewai test -n 5 -m gpt-4o +``` + +When you run the `crewai test` command, the crew will be executed for the specified number of iterations, and the performance metrics will be displayed at the end of the run. + +A table of scores at the end will show the performance of the crew in terms of the following metrics: + +
**Tasks Scores (1-10 Higher is better)**
+ +| Tasks/Crew/Agents | Run 1 | Run 2 | Avg. Total | Agents | Additional Info | +|:------------------|:-----:|:-----:|:----------:|:------------------------------:|:---------------------------------| +| Task 1 | 9.0 | 9.5 | **9.2** | Professional Insights | | +| | | | | Researcher | | +| Task 2 | 9.0 | 10.0 | **9.5** | Company Profile Investigator | | +| Task 3 | 9.0 | 9.0 | **9.0** | Automation Insights | | +| | | | | Specialist | | +| Task 4 | 9.0 | 9.0 | **9.0** | Final Report Compiler | Automation Insights Specialist | +| Crew | 9.00 | 9.38 | **9.2** | | | +| Execution Time (s) | 126 | 145 | **135** | | | + +The example above shows the test results for two runs of the crew with two tasks, with the average total score for each task and the crew as a whole. diff --git a/docs/v1.15.13/en/concepts/tools.mdx b/docs/v1.15.13/en/concepts/tools.mdx new file mode 100644 index 0000000000..e78c4aa448 --- /dev/null +++ b/docs/v1.15.13/en/concepts/tools.mdx @@ -0,0 +1,461 @@ +--- +title: Tools +description: Understanding and leveraging tools within the CrewAI framework for agent collaboration and task execution. +icon: screwdriver-wrench +mode: "wide" +--- + +## Overview + +CrewAI tools empower agents with capabilities ranging from web searching and data analysis to collaboration and delegating tasks among coworkers. +This documentation outlines how to create, integrate, and leverage these tools within the CrewAI framework, including a new focus on collaboration tools. + + + Tools give agents **callable functions** to take action. They work alongside [MCPs](/en/mcp/overview) (remote tool servers), [Apps](/en/concepts/agent-capabilities) (platform integrations), [Skills](/en/concepts/skills) (domain expertise), and [Knowledge](/en/concepts/knowledge) (retrieved facts). See the [Agent Capabilities](/en/concepts/agent-capabilities) overview to understand when to use each. + + +## What is a Tool? + +A tool in CrewAI is a skill or function that agents can utilize to perform various actions. +This includes tools from the [CrewAI Toolkit](https://github.com/joaomdmoura/crewai-tools) and [LangChain Tools](https://python.langchain.com/docs/integrations/tools), +enabling everything from simple searches to complex interactions and effective teamwork among agents. + + +CrewAI AMP provides a comprehensive Tools Repository with pre-built integrations for common business systems and APIs. Deploy agents with enterprise tools in minutes instead of days. + +The Enterprise Tools Repository includes: + +- Pre-built connectors for popular enterprise systems +- Custom tool creation interface +- Version control and sharing capabilities +- Security and compliance features + + +## Key Characteristics of Tools + +- **Utility**: Crafted for tasks such as web searching, data analysis, content generation, and agent collaboration. +- **Integration**: Boosts agent capabilities by seamlessly integrating tools into their workflow. +- **Customizability**: Provides the flexibility to develop custom tools or utilize existing ones, catering to the specific needs of agents. +- **Error Handling**: Incorporates robust error handling mechanisms to ensure smooth operation. +- **Caching Mechanism**: Features intelligent caching to optimize performance and reduce redundant operations. +- **Asynchronous Support**: Handles both synchronous and asynchronous tools, enabling non-blocking operations. +- **Typed Outputs**: Uses optional Pydantic models to give agents clear JSON fields while direct Python calls still receive the tool's normal return value. + +## Using CrewAI Tools + +To enhance your agents' capabilities with crewAI tools, begin by installing our extra tools package: + +```bash +pip install 'crewai[tools]' +``` + +Here's an example demonstrating their use: + +```python Code +import os +from crewai import Agent, Task, Crew +# Importing crewAI tools +from crewai_tools import ( + DirectoryReadTool, + FileReadTool, + SerperDevTool, + WebsiteSearchTool +) + +# Set up API keys +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key +os.environ["OPENAI_API_KEY"] = "Your Key" + +# Instantiate tools +docs_tool = DirectoryReadTool(directory='./blog-posts') +file_tool = FileReadTool() +search_tool = SerperDevTool() +web_rag_tool = WebsiteSearchTool() + +# Create agents +researcher = Agent( + role='Market Research Analyst', + goal='Provide up-to-date market analysis of the AI industry', + backstory='An expert analyst with a keen eye for market trends.', + tools=[search_tool, web_rag_tool], + verbose=True +) + +writer = Agent( + role='Content Writer', + goal='Craft engaging blog posts about the AI industry', + backstory='A skilled writer with a passion for technology.', + tools=[docs_tool, file_tool], + verbose=True +) + +# Define tasks +research = Task( + description='Research the latest trends in the AI industry and provide a summary.', + expected_output='A summary of the top 3 trending developments in the AI industry with a unique perspective on their significance.', + agent=researcher +) + +write = Task( + description='Write an engaging blog post about the AI industry, based on the research analyst's summary. Draw inspiration from the latest blog posts in the directory.', + expected_output='A 4-paragraph blog post formatted in markdown with engaging, informative, and accessible content, avoiding complex jargon.', + agent=writer, + output_file='blog-posts/new_post.md' # The final blog post will be saved here +) + +# Assemble a crew with planning enabled +crew = Crew( + agents=[researcher, writer], + tasks=[research, write], + verbose=True, + planning=True, # Enable planning feature +) + +# Execute tasks +crew.kickoff() +``` + +## Available CrewAI Tools + +- **Error Handling**: All tools are built with error handling capabilities, allowing agents to gracefully manage exceptions and continue their tasks. +- **Caching Mechanism**: All tools support caching, enabling agents to efficiently reuse previously obtained results, reducing the load on external resources and speeding up the execution time. You can also define finer control over the caching mechanism using the `cache_function` attribute on the tool. + +Here is a list of the available tools and their descriptions: + +| Tool | Description | +| :------------------------------- | :--------------------------------------------------------------------------------------------- | +| **ApifyActorsTool** | A tool that integrates Apify Actors with your workflows for web scraping and automation tasks. | +| **BrowserbaseLoadTool** | A tool for interacting with and extracting data from web browsers. | +| **CodeDocsSearchTool** | A RAG tool optimized for searching through code documentation and related technical documents. | +| **CodeInterpreterTool** | A tool for interpreting python code. | +| **ComposioTool** | Enables use of Composio tools. | +| **CSVSearchTool** | A RAG tool designed for searching within CSV files, tailored to handle structured data. | +| **DALL-E Tool** | A tool for generating images using the DALL-E API. | +| **DirectorySearchTool** | A RAG tool for searching within directories, useful for navigating through file systems. | +| **DOCXSearchTool** | A RAG tool aimed at searching within DOCX documents, ideal for processing Word files. | +| **DirectoryReadTool** | Facilitates reading and processing of directory structures and their contents. | +| **ExaSearchTool** | Search the web with Exa, the fastest and most accurate web search API. Supports token-efficient highlights and full page content. | +| **FileReadTool** | Enables reading and extracting data from files, supporting various file formats. | +| **FirecrawlSearchTool** | A tool to search webpages using Firecrawl and return the results. | +| **FirecrawlCrawlWebsiteTool** | A tool for crawling webpages using Firecrawl. | +| **FirecrawlScrapeWebsiteTool** | A tool for scraping webpages URL using Firecrawl and returning its contents. | +| **GithubSearchTool** | A RAG tool for searching within GitHub repositories, useful for code and documentation search. | +| **SerperDevTool** | A specialized tool for development purposes, with specific functionalities under development. | +| **TXTSearchTool** | A RAG tool focused on searching within text (.txt) files, suitable for unstructured data. | +| **JSONSearchTool** | A RAG tool designed for searching within JSON files, catering to structured data handling. | +| **LlamaIndexTool** | Enables the use of LlamaIndex tools. | +| **MDXSearchTool** | A RAG tool tailored for searching within Markdown (MDX) files, useful for documentation. | +| **PDFSearchTool** | A RAG tool aimed at searching within PDF documents, ideal for processing scanned documents. | +| **PGSearchTool** | A RAG tool optimized for searching within PostgreSQL databases, suitable for database queries. | +| **Vision Tool** | A tool for generating images using the DALL-E API. | +| **RagTool** | A general-purpose RAG tool capable of handling various data sources and types. | +| **ScrapeElementFromWebsiteTool** | Enables scraping specific elements from websites, useful for targeted data extraction. | +| **ScrapeWebsiteTool** | Facilitates scraping entire websites, ideal for comprehensive data collection. | +| **WebsiteSearchTool** | A RAG tool for searching website content, optimized for web data extraction. | +| **XMLSearchTool** | A RAG tool designed for searching within XML files, suitable for structured data formats. | +| **YoutubeChannelSearchTool** | A RAG tool for searching within YouTube channels, useful for video content analysis. | +| **YoutubeVideoSearchTool** | A RAG tool aimed at searching within YouTube videos, ideal for video data extraction. | + +## Creating your own Tools + + + Developers can craft `custom tools` tailored for their agent's needs or + utilize pre-built options. + + +There are two main ways for one to create a CrewAI tool: + +### Subclassing `BaseTool` + +```python Code +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class MyToolInput(BaseModel): + """Input schema for MyCustomTool.""" + argument: str = Field(..., description="Description of the argument.") + +class MyCustomTool(BaseTool): + name: str = "Name of my tool" + description: str = "What this tool does. It's vital for effective utilization." + args_schema: Type[BaseModel] = MyToolInput + + def _run(self, argument: str) -> str: + # Your tool's logic here + return "Tool's result" +``` + +### Typed Tool Outputs + +When a tool returns structured data, define a Pydantic output model. This gives the agent field names it can trust, such as `sku`, `quantity`, or `needs_reorder`. + +Direct Python calls still receive the value your tool returns. When an agent uses the tool, CrewAI sends the agent a JSON string based on the output model. + +```python Code +from crewai.tools import BaseTool +from pydantic import BaseModel + +class InventoryResult(BaseModel): + sku: str + quantity: int + needs_reorder: bool + +class InventoryTool(BaseTool): + name: str = "Inventory Check" + description: str = "Checks current stock for a product SKU." + + def _run(self, sku: str) -> InventoryResult: + quantity = {"SKU-123": 14, "SKU-456": 0}.get(sku, 0) + return InventoryResult(sku=sku, quantity=quantity, needs_reorder=quantity < 5) + +tool = InventoryTool() + +# Direct calls receive the raw Pydantic object. +result = tool.run(sku="SKU-123") +print(result.quantity) +``` + +To send Markdown or another short text format to the agent, override `format_output_for_agent`. Direct calls to `tool.run(...)` still return the normal Python value. + +```python Code +class InventoryTool(BaseTool): + name: str = "Inventory Check" + description: str = "Checks current stock for a product SKU." + + def _run(self, sku: str) -> InventoryResult: + quantity = {"SKU-123": 14, "SKU-456": 0}.get(sku, 0) + return InventoryResult(sku=sku, quantity=quantity, needs_reorder=quantity < 5) + + def format_output_for_agent(self, raw_result: object) -> str: + result = InventoryResult.model_validate(raw_result) + status = "reorder needed" if result.needs_reorder else "stock is healthy" + return f"{result.sku}: {result.quantity} units. {status}." +``` + +If you do not override `format_output_for_agent`, typed outputs are sent to the agent as JSON. Plain string results work as before. + +## Asynchronous Tool Support + +CrewAI supports asynchronous tools, allowing you to implement tools that perform non-blocking operations like network requests, file I/O, or other async operations without blocking the main execution thread. + +### Creating Async Tools + +You can create async tools in two ways: + +#### 1. Using the `tool` Decorator with Async Functions + +```python Code +from crewai.tools import tool + +@tool("fetch_data_async") +async def fetch_data_async(query: str) -> str: + """Asynchronously fetch data based on the query.""" + # Simulate async operation + await asyncio.sleep(1) + return f"Data retrieved for {query}" +``` + +#### 2. Implementing Async Methods in Custom Tool Classes + +```python Code +from crewai.tools import BaseTool + +class AsyncCustomTool(BaseTool): + name: str = "async_custom_tool" + description: str = "An asynchronous custom tool" + + async def _run(self, query: str = "") -> str: + """Asynchronously run the tool""" + # Your async implementation here + await asyncio.sleep(1) + return f"Processed {query} asynchronously" +``` + +### Using Async Tools + +Async tools work seamlessly in both standard Crew workflows and Flow-based workflows: + +```python Code +# In standard Crew +agent = Agent(role="researcher", tools=[async_custom_tool]) + +# In Flow +class MyFlow(Flow): + @start() + async def begin(self): + crew = Crew(agents=[agent]) + result = await crew.kickoff_async() + return result +``` + +The CrewAI framework automatically handles the execution of both synchronous and asynchronous tools, so you don't need to worry about how to call them differently. + +### Utilizing the `tool` Decorator + +```python Code +from crewai.tools import tool +@tool("Name of my tool") +def my_tool(question: str) -> str: + """Clear description for what this tool is useful for, your agent will need this information to use it.""" + # Function logic here + return "Result from your custom tool" +``` + +### Custom Caching Mechanism + + + Tools can optionally implement a `cache_function` to fine-tune caching + behavior. This function determines when to cache results based on specific + conditions, offering granular control over caching logic. + + +```python Code +from crewai.tools import tool + +@tool +def multiplication_tool(first_number: int, second_number: int) -> str: + """Useful for when you need to multiply two numbers together.""" + return first_number * second_number + +def cache_func(args, result): + # In this case, we only cache the result if it's a multiple of 2 + cache = result % 2 == 0 + return cache + +multiplication_tool.cache_function = cache_func + +writer1 = Agent( + role="Writer", + goal="You write lessons of math for kids.", + backstory="You're an expert in writing and you love to teach kids but you know nothing of math.", + tools=[multiplication_tool], + allow_delegation=False, + ) + #... +``` + +## Reporting Tool Failures + +A tool can finish without raising and still fail to do what it was asked. Slack +answers `HTTP 200` with `{"ok": false, "error": "channel_not_found"}`; an MCP +server sets `isError`; a platform action returns an error payload. The tool call +"worked", so the error text reaches the agent as an ordinary result — the agent +narrates the problem in its final answer and the run is recorded as a success. + +Return a `ToolFailure` instead of an error string and the framework can tell the +difference: + +```python Code +from typing import Any + +from crewai.tools import BaseTool +from crewai.tools.tool_failure import ToolFailure + + +class SendSlackMessage(BaseTool): + name: str = "send_slack_message" + description: str = "Post a message to a Slack channel." + + def _run(self, channel: str, text: str) -> Any: + payload = slack.post(channel=channel, text=text) + if not payload["ok"]: + return ToolFailure( + message=f"Slack rejected the message: {payload['error']}", + code=payload["error"], + retryable=payload["error"] == "rate_limited", + ) + return payload +``` + +The agent still reads plain prose — `ToolFailure.as_agent_message()` renders the +message — so model behavior is unchanged. What changes is that the failure is now +visible to everything downstream. + +Detection is strictly declarative. CrewAI never guesses whether a string "looks +like" an error, so a tool that legitimately returns text about an error is never +misread as having failed. Failures are recorded when a tool returns a +`ToolFailure`, when a tool raises, when an MCP server sets `isError`, when a +tool's `max_usage_count` is spent, or when the agent calls a tool that does not exist. + +### Choosing a Failure Policy + +`tool_failure_policy` controls what happens next: + +| Policy | Behavior | +| :-- | :-- | +| `ignore` | Nothing is recorded, emitted, or acted on. | +| `warn` *(default)* | Records the failure, emits `ToolFailureDetectedEvent`, and continues. | +| `raise` | Records and emits, then aborts with `ToolExecutionFailedError`. | + +```python Code +from crewai import Agent, Crew, Task +from crewai.tools.tool_failure import ToolFailurePolicy + +agent = Agent( + role="Slack Messenger", + goal="Post the report to Slack", + backstory="...", + tools=[SendSlackMessage()], + tool_failure_policy=ToolFailurePolicy.WARN, +) + +# Tighten a single high-stakes task without changing the agent. +task = Task( + description="Post the final report to #engineering", + expected_output="Confirmation the message was posted", + agent=agent, + tool_failure_policy=ToolFailurePolicy.RAISE, +) + +# Or set a baseline once for every agent in the crew. +crew = Crew( + agents=[agent], + tasks=[task], + tool_failure_policy=ToolFailurePolicy.WARN, +) +``` + +The most specific setting wins: **tool → task → agent → crew → `warn`**. Every +level defaults to `None`, meaning "inherit from the next one out", so the +effective default with nothing configured anywhere is `warn`. + +### Inspecting Failures + +Recorded failures are structured, so nothing downstream has to parse a string: + +```python Code +result = crew.kickoff() + +if result.has_tool_failures: + for record in result.tool_failures: + print(record.tool_name) # "send_slack_message" + print(record.failure.code) # "channel_not_found" + print(record.failure.reason) # ToolFailureReason.TOOL_REPORTED + print(record.summary()) +``` + +`tool_failures` is available on `TaskOutput`, `CrewOutput`, and +`LiteAgentOutput`. A crew can finish successfully with a non-empty list — check +it before treating `raw` as complete. + +To react as failures happen, subscribe to the event: + +```python Code +from crewai.events import ToolFailureDetectedEvent +from crewai.events.event_bus import crewai_event_bus + + +@crewai_event_bus.on(ToolFailureDetectedEvent) +def on_tool_failure(source, event): + print(f"{event.tool_name} failed: {event.failure.message} ({event.policy})") +``` + +The event is emitted before the `raise` policy aborts, so subscribers always +observe the failure. `ToolUsageFinishedEvent` also carries a `failure` field, letting +a trace UI mark the call as failed without correlating two events. + +## Conclusion + +Tools are pivotal in extending the capabilities of CrewAI agents, enabling them to undertake a broad spectrum of tasks and collaborate effectively. +When building solutions with CrewAI, leverage both custom and existing tools to empower your agents and enhance the AI ecosystem. Consider utilizing error handling, +caching mechanisms, and the flexibility of tool arguments to optimize your agents' performance and capabilities. diff --git a/docs/v1.15.13/en/concepts/training.mdx b/docs/v1.15.13/en/concepts/training.mdx new file mode 100644 index 0000000000..468e1acefc --- /dev/null +++ b/docs/v1.15.13/en/concepts/training.mdx @@ -0,0 +1,197 @@ +--- +title: Training +description: Learn how to train your CrewAI agents by giving them feedback early on and get consistent results. +icon: dumbbell +mode: "wide" +--- + +## Overview + +The training feature in CrewAI allows you to train your AI agents using the command-line interface (CLI). +By running the command `crewai train -n `, you can specify the number of iterations for the training process. + +During training, CrewAI utilizes techniques to optimize the performance of your agents along with human feedback. +This helps the agents improve their understanding, decision-making, and problem-solving abilities. + +### Training Your Crew Using the CLI + +To use the training feature, follow these steps: + +1. Open your terminal or command prompt. +2. Navigate to the directory where your CrewAI project is located. +3. Run the following command: + +```shell +crewai train -n -f +``` + + Replace `` with the desired number of training iterations and `` with the appropriate filename ending with `.pkl`. + + + + If you omit `-f`, the output defaults to `trained_agents_data.pkl` in the current working directory. You can pass an absolute path to control where the file is written. + + +### Training your Crew programmatically + +To train your crew programmatically, use the following steps: + +1. Define the number of iterations for training. +2. Specify the input parameters for the training process. +3. Execute the training command within a try-except block to handle potential errors. + +```python Code +n_iterations = 2 +inputs = {"topic": "CrewAI Training"} +filename = "your_model.pkl" + +try: + YourCrewName_Crew().crew().train( + n_iterations=n_iterations, + inputs=inputs, + filename=filename + ) + +except Exception as e: + raise Exception(f"An error occurred while training the crew: {e}") +``` + +## How trained data is used by agents + +CrewAI uses the training artifacts in two ways: during training to incorporate your human feedback, and after training to guide agents with consolidated suggestions. + +### Training data flow + +```mermaid +flowchart TD + A["Start training
CLI: crewai train -n -f
or Python: crew.train(...)"] --> B["Setup training mode
- task.human_input = true
- disable delegation
- init training_data.pkl + trained file"] + + subgraph "Iterations" + direction LR + C["Iteration i
initial_output"] --> D["User human_feedback"] + D --> E["improved_output"] + E --> F["Append to training_data.pkl
by agent_id and iteration"] + end + + B --> C + F --> G{"More iterations?"} + G -- "Yes" --> C + G -- "No" --> H["Evaluate per agent
aggregate iterations"] + + H --> I["Consolidate
suggestions[] + quality + final_summary"] + I --> J["Save by agent role to trained file
(default: trained_agents_data.pkl)"] + + J --> K["Normal (non-training) runs"] + K --> L["Auto-load suggestions
from trained_agents_data.pkl"] + L --> M["Append to prompt
for consistent improvements"] +``` + +### During training runs + +- On each iteration, the system records for every agent: + - `initial_output`: the agent’s first answer + - `human_feedback`: your inline feedback when prompted + - `improved_output`: the agent’s follow-up answer after feedback +- This data is stored in a working file named `training_data.pkl` keyed by the agent’s internal ID and iteration. +- While training is active, the agent automatically appends your prior human feedback to its prompt to enforce those instructions on subsequent attempts within the training session. + Training is interactive: tasks set `human_input = true`, so running in a non-interactive environment will block on user input. + +### After training completes + +- When `train(...)` finishes, CrewAI evaluates the collected training data per agent and produces a consolidated result containing: + - `suggestions`: clear, actionable instructions distilled from your feedback and the difference between initial/improved outputs + - `quality`: a 0–10 score capturing improvement + - `final_summary`: a step-by-step set of action items for future tasks +- These consolidated results are saved to the filename you pass to `train(...)` (default via CLI is `trained_agents_data.pkl`). Entries are keyed by the agent’s `role` so they can be applied across sessions. +- During normal (non-training) execution, each agent automatically loads its consolidated `suggestions` and appends them to the task prompt as mandatory instructions. This gives you consistent improvements without changing your agent definitions. + +### File summary + +- `training_data.pkl` (ephemeral, per-session): + - Structure: `agent_id -> { iteration_number: { initial_output, human_feedback, improved_output } }` + - Purpose: capture raw data and human feedback during training + - Location: saved in the current working directory (CWD) +- `trained_agents_data.pkl` (or your custom filename): + - Structure: `agent_role -> { suggestions: string[], quality: number, final_summary: string }` + - Purpose: persist consolidated guidance for future runs + - Location: written to the CWD by default; use `-f` to set a custom (including absolute) path + +## Small Language Model Considerations + + + When using smaller language models (≤7B parameters) for training data evaluation, be aware that they may face challenges with generating structured outputs and following complex instructions. + + +### Limitations of Small Models in Training Evaluation + + + + Smaller models often struggle with producing valid JSON responses needed for structured training evaluations, leading to parsing errors and incomplete data. + + + Models under 7B parameters may provide less nuanced evaluations with limited reasoning depth compared to larger models. + + + Complex training evaluation criteria may not be fully followed or considered by smaller models. + + + Evaluations across multiple training iterations may lack consistency with smaller models. + + + +### Recommendations for Training + + + + For optimal training quality and reliable evaluations, we strongly recommend using models with at least 7B parameters or larger: + + ```python + from crewai import Agent, Crew, Task, LLM + + # Recommended minimum for training evaluation + llm = LLM(model="mistral/open-mistral-7b") + + # Better options for reliable training evaluation + llm = LLM(model="anthropic/claude-3-sonnet-20240229-v1:0") + llm = LLM(model="gpt-4o") + + # Use this LLM with your agents + agent = Agent( + role="Training Evaluator", + goal="Provide accurate training feedback", + llm=llm + ) + ``` + + + More powerful models provide higher quality feedback with better reasoning, leading to more effective training iterations. + + + + If you must use smaller models for training evaluation, be aware of these constraints: + + ```python + # Using a smaller model (expect some limitations) + llm = LLM(model="huggingface/microsoft/Phi-3-mini-4k-instruct") + ``` + + + While CrewAI includes optimizations for small models, expect less reliable and less nuanced evaluation results that may require more human intervention during training. + + + + +### Key Points to Note + +- **Positive Integer Requirement:** Ensure that the number of iterations (`n_iterations`) is a positive integer. The code will raise a `ValueError` if this condition is not met. +- **Filename Requirement:** Ensure that the filename ends with `.pkl`. The code will raise a `ValueError` if this condition is not met. +- **Error Handling:** The code handles subprocess errors and unexpected exceptions, providing error messages to the user. +- Trained guidance is applied at prompt time; it does not modify your Python/YAML agent configuration. +- Agents automatically load trained suggestions from a file named `trained_agents_data.pkl` located in the current working directory. If you trained to a different filename, pass that path with `Crew(trained_agents_file="my_custom_trained.pkl")`, set `CREWAI_TRAINED_AGENTS_FILE`, or use `crewai run -f my_custom_trained.pkl`. +- You can change the output filename when calling `crewai train` with `-f/--filename`. Absolute paths are supported if you want to save outside the CWD. + +It is important to note that the training process may take some time, depending on the complexity of your agents and will also require your feedback on each iteration. + +Once the training is complete, your agents will be equipped with enhanced capabilities and knowledge, ready to tackle complex tasks and provide more consistent and valuable insights. + +Remember to regularly update and retrain your agents to ensure they stay up-to-date with the latest information and advancements in the field. diff --git a/docs/v1.15.13/en/examples/cookbooks.mdx b/docs/v1.15.13/en/examples/cookbooks.mdx new file mode 100644 index 0000000000..1bd7f016db --- /dev/null +++ b/docs/v1.15.13/en/examples/cookbooks.mdx @@ -0,0 +1,49 @@ +--- +title: CrewAI Cookbooks +description: Feature-focused quickstarts and notebooks for learning patterns fast. +icon: book +mode: "wide" +--- + +## Quickstarts & Demos + + + + Coordinate multiple agents on shared tasks. Includes notebook with end-to-end collaboration pattern. + + + + Teach agents to reason about multi-step plans before execution using the planning toolkit. + + + + Explore self-reflection loops, critique prompts, and structured thinking patterns. + + + + + + Apply task-level guardrails with retries, validation functions, and safe fallbacks. + + + + Connect CrewAI to Gemini with search grounding for factual, citation-rich outputs. + + + + Generate video recaps using Gemini multimodal LLM and CrewAI orchestration. + + + + + + View all notebooks and feature demos showcasing specific CrewAI capabilities. + + + Missing a pattern? Drop a request in the community forum and we’ll expand the library. + + + + +Use Cookbooks to learn a pattern quickly, then jump to Full Examples for production‑grade implementations. + diff --git a/docs/v1.15.13/en/examples/example.mdx b/docs/v1.15.13/en/examples/example.mdx new file mode 100644 index 0000000000..37672cbfa3 --- /dev/null +++ b/docs/v1.15.13/en/examples/example.mdx @@ -0,0 +1,86 @@ +--- +title: CrewAI Examples +description: Explore curated examples organized by Crews, Flows, Integrations, and Notebooks. +icon: rocket-launch +mode: "wide" +--- + +## Crews + + + + Multi‑agent marketing campaign planning. + + + Personalized surprise travel planning. + + + CV‑to‑job matching with vector search. + + + Automated job description creation. + + + Multi‑agent team that designs and builds Python games. + + + Candidate sourcing and evaluation. + + + See the full list of crew examples. + + + +## Flows + + + + Multi‑crew content generation with routing. + + + Automated email monitoring and replies. + + + Lead qualification with human‑in‑the‑loop. + + + Notes processing with integrations. + + + Iterative self‑improvement workflows. + + + Parallel chapter generation. + + + See the full list of flow examples. + + + +## Integrations + + + + Integration with LangGraph framework. + + + Using CrewAI with Azure OpenAI. + + + NVIDIA ecosystem integrations. + + + See all integration examples. + + + +## Notebooks + + + + Simple QA Crew + Flow. + + + Interactive examples for learning and experimentation. + + diff --git a/docs/v1.15.13/en/guides/advanced/customizing-prompts.mdx b/docs/v1.15.13/en/guides/advanced/customizing-prompts.mdx new file mode 100644 index 0000000000..00132b5b16 --- /dev/null +++ b/docs/v1.15.13/en/guides/advanced/customizing-prompts.mdx @@ -0,0 +1,331 @@ +--- +title: Customizing Prompts +description: Dive deeper into low-level prompt customization for CrewAI, enabling super custom and complex use cases for different models and languages. +icon: message-pen +mode: "wide" +--- + +## Why Customize Prompts? + +Although CrewAI's default prompts work well for many scenarios, low-level customization opens the door to significantly more flexible and powerful agent behavior. Here's why you might want to take advantage of this deeper control: + +1. **Optimize for specific LLMs** – Different models (such as GPT-4, Claude, or Llama) thrive with prompt formats tailored to their unique architectures. +2. **Change the language** – Build agents that operate exclusively in languages beyond English, handling nuances with precision. +3. **Specialize for complex domains** – Adapt prompts for highly specialized industries like healthcare, finance, or legal. +4. **Adjust tone and style** – Make agents more formal, casual, creative, or analytical. +5. **Support super custom use cases** – Utilize advanced prompt structures and formatting to meet intricate, project-specific requirements. + +This guide explores how to tap into CrewAI's prompts at a lower level, giving you fine-grained control over how agents think and interact. + +## Understanding CrewAI's Prompt System + +Under the hood, CrewAI employs a modular prompt system that you can customize extensively: + +- **Agent templates** – Govern each agent's approach to their assigned role. +- **Prompt slices** – Control specialized behaviors such as tasks, tool usage, and output structure. +- **Error handling** – Direct how agents respond to failures, exceptions, or timeouts. +- **Tool-specific prompts** – Define detailed instructions for how tools are invoked or utilized. + +Check out the [original prompt templates in CrewAI's repository](https://github.com/crewAIInc/crewAI/blob/main/src/crewai/translations/en.json) to see how these elements are organized. From there, you can override or adapt them as needed to unlock advanced behaviors. + +## Understanding Default System Instructions + + +**Production Transparency Issue**: CrewAI automatically injects default instructions into your prompts that you might not be aware of. This section explains what's happening under the hood and how to gain full control. + + +When you define an agent with `role`, `goal`, and `backstory`, CrewAI automatically adds additional system instructions that control formatting and behavior. Understanding these default injections is crucial for production systems where you need full prompt transparency. + +### What CrewAI Automatically Injects + +Based on your agent configuration, CrewAI adds different default instructions: + +#### For Agents Without Tools +```text +"I MUST use these formats, my job depends on it!" +``` + +#### For Agents With Tools +```text +"IMPORTANT: Use the following format in your response: + +Thought: you should always think about what to do +Action: the action to take, only one name of [tool_names] +Action Input: the input to the action, just a simple JSON object... +``` + +#### For Structured Outputs (JSON/Pydantic) +```text +"Ensure your final answer contains only the content in the following format: {output_format} +Ensure the final output does not include any code block markers like ```json or ```python." +``` + +### Viewing the Complete System Prompt + +To see exactly what prompt is being sent to your LLM, you can inspect the generated prompt: + +```python +from crewai import Agent, Crew, Task +from crewai.utilities.prompts import Prompts + +# Create your agent +agent = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + backstory="You are an expert data analyst with 10 years of experience.", + verbose=True +) + +# Create a sample task +task = Task( + description="Analyze the sales data and identify trends", + expected_output="A detailed analysis with key insights and trends", + agent=agent +) + +# Create the prompt generator +prompt_generator = Prompts( + agent=agent, + has_tools=len(agent.tools) > 0, + use_system_prompt=agent.use_system_prompt +) + +# Generate and inspect the actual prompt +generated_prompt = prompt_generator.task_execution() + +# Print the complete system prompt that will be sent to the LLM +if "system" in generated_prompt: + print("=== SYSTEM PROMPT ===") + print(generated_prompt["system"]) + print("\n=== USER PROMPT ===") + print(generated_prompt["user"]) +else: + print("=== COMPLETE PROMPT ===") + print(generated_prompt["prompt"]) + +# You can also see how the task description gets formatted +print("\n=== TASK CONTEXT ===") +print(f"Task Description: {task.description}") +print(f"Expected Output: {task.expected_output}") +``` + +### Overriding Default Instructions + +You have several options to gain full control over the prompts: + +#### Option 1: Custom Templates (Recommended) +```python +from crewai import Agent + +# Define your own system template without default instructions +custom_system_template = """You are {role}. {backstory} +Your goal is: {goal} + +Respond naturally and conversationally. Focus on providing helpful, accurate information.""" + +custom_prompt_template = """Task: {input} + +Please complete this task thoughtfully.""" + +agent = Agent( + role="Research Assistant", + goal="Help users find accurate information", + backstory="You are a helpful research assistant.", + system_template=custom_system_template, + prompt_template=custom_prompt_template, + use_system_prompt=True # Use separate system/user messages +) +``` + +#### Option 2: Custom Prompt File +Create a `custom_prompts.json` file to override specific prompt slices: + +```json +{ + "slices": { + "no_tools": "\nProvide your best answer in a natural, conversational way.", + "tools": "\nYou have access to these tools: {tools}\n\nUse them when helpful, but respond naturally.", + "formatted_task_instructions": "Format your response as: {output_format}" + } +} +``` + +Then use it in your crew: + +```python +crew = Crew( + agents=[agent], + tasks=[task], + prompt_file="custom_prompts.json", + verbose=True +) +``` + + +`agent.i18n` is maintained only for backward compatibility and is deprecated. For runtime prompt customization, pass `prompt_file` to `Crew`. For programmatic access to prompt slices, use the i18n utility directly: + + +```python +from crewai.utilities.i18n import get_i18n + +i18n = get_i18n("custom_prompts.json") +format_slice = i18n.slice("format") +tool_prompt = i18n.tools("ask_question") +``` + +#### Option 3: Disable System Prompts for o1 Models +```python +agent = Agent( + role="Analyst", + goal="Analyze data", + backstory="Expert analyst", + use_system_prompt=False # Disables system prompt separation +) +``` + +### Debugging with Observability Tools + +For production transparency, integrate with observability platforms to monitor all prompts and LLM interactions. This allows you to see exactly what prompts (including default instructions) are being sent to your LLMs. + +See our [Observability documentation](/en/observability/overview) for detailed integration guides with various platforms including Langfuse, MLflow, Weights & Biases, and custom logging solutions. + +### Best Practices for Production + +1. **Always inspect generated prompts** before deploying to production +2. **Use custom templates** when you need full control over prompt content +3. **Integrate observability tools** for ongoing prompt monitoring (see [Observability docs](/en/observability/overview)) +4. **Test with different LLMs** as default instructions may work differently across models +5. **Document your prompt customizations** for team transparency + + +The default instructions exist to ensure consistent agent behavior, but they can interfere with domain-specific requirements. Use the customization options above to maintain full control over your agent's behavior in production systems. + + +## Best Practices for Managing Prompt Files + +When engaging in low-level prompt customization, follow these guidelines to keep things organized and maintainable: + +1. **Keep files separate** – Store your customized prompts in dedicated JSON files outside your main codebase. +2. **Version control** – Track changes within your repository, ensuring clear documentation of prompt adjustments over time. +3. **Organize by model or language** – Use naming schemes like `prompts_llama.json` or `prompts_es.json` to quickly identify specialized configurations. +4. **Document changes** – Provide comments or maintain a README detailing the purpose and scope of your customizations. +5. **Minimize alterations** – Only override the specific slices you genuinely need to adjust, keeping default functionality intact for everything else. + +## The Simplest Way to Customize Prompts + +One straightforward approach is to create a JSON file for the prompts you want to override and then point your Crew at that file: + +1. Craft a JSON file with your updated prompt slices. +2. Reference that file via the `prompt_file` parameter in your Crew. + +CrewAI then merges your customizations with the defaults, so you don't have to redefine every prompt. Here's how: + +For code that needs to read prompt slices directly, use `crewai.utilities.i18n.get_i18n()` with the same prompt file instead of reading `agent.i18n`. + +### Example: Basic Prompt Customization + +Create a `custom_prompts.json` file with the prompts you want to modify. Ensure you list all top-level prompts it should contain, not just your changes: + +```json +{ + "slices": { + "format": "When responding, follow this structure:\n\nTHOUGHTS: Your step-by-step thinking\nACTION: Any tool you're using\nRESULT: Your final answer or conclusion" + } +} +``` + +Then integrate it like so: + +```python +from crewai import Agent, Crew, Task, Process + +# Create agents and tasks as normal +researcher = Agent( + role="Research Specialist", + goal="Find information on quantum computing", + backstory="You are a quantum physics expert", + verbose=True +) + +research_task = Task( + description="Research quantum computing applications", + expected_output="A summary of practical applications", + agent=researcher +) + +# Create a crew with your custom prompt file +crew = Crew( + agents=[researcher], + tasks=[research_task], + prompt_file="path/to/custom_prompts.json", + verbose=True +) + +# Run the crew +result = crew.kickoff() +``` + +With these few edits, you gain low-level control over how your agents communicate and solve tasks. + +## Optimizing for Specific Models + +Different models thrive on differently structured prompts. Making deeper adjustments can significantly boost performance by aligning your prompts with a model's nuances. + +### Example: Llama 3.3 Prompting Template + +For instance, when dealing with Meta's Llama 3.3, deeper-level customization may reflect the recommended structure described at: +https://www.llama.com/docs/model-cards-and-prompt-formats/llama3_1/#prompt-template + +Here's an example to highlight how you might fine-tune an Agent to leverage Llama 3.3 in code: + +```python +from crewai import Agent, Crew, Task, Process +from crewai_tools import DirectoryReadTool, FileReadTool + +# Define templates for system, user (prompt), and assistant (response) messages +system_template = """<|begin_of_text|><|start_header_id|>system<|end_header_id|>{{ .System }}<|eot_id|>""" +prompt_template = """<|start_header_id|>user<|end_header_id|>{{ .Prompt }}<|eot_id|>""" +response_template = """<|start_header_id|>assistant<|end_header_id|>{{ .Response }}<|eot_id|>""" + +# Create an Agent using Llama-specific layouts +principal_engineer = Agent( + role="Principal Engineer", + goal="Oversee AI architecture and make high-level decisions", + backstory="You are the lead engineer responsible for critical AI systems", + verbose=True, + llm="groq/llama-3.3-70b-versatile", # Using the Llama 3 model + system_template=system_template, + prompt_template=prompt_template, + response_template=response_template, + tools=[DirectoryReadTool(), FileReadTool()] +) + +# Define a sample task +engineering_task = Task( + description="Review AI implementation files for potential improvements", + expected_output="A summary of key findings and recommendations", + agent=principal_engineer +) + +# Create a Crew for the task +llama_crew = Crew( + agents=[principal_engineer], + tasks=[engineering_task], + process=Process.sequential, + verbose=True +) + +# Execute the crew +result = llama_crew.kickoff() +print(result.raw) +``` + +Through this deeper configuration, you can exercise comprehensive, low-level control over your Llama-based workflows without needing a separate JSON file. + +## Conclusion + +Low-level prompt customization in CrewAI opens the door to super custom, complex use cases. By establishing well-organized prompt files (or direct inline templates), you can accommodate various models, languages, and specialized domains. This level of flexibility ensures you can craft precisely the AI behavior you need, all while knowing CrewAI still provides reliable defaults when you don't override them. + + +You now have the foundation for advanced prompt customizations in CrewAI. Whether you're adapting for model-specific structures or domain-specific constraints, this low-level approach lets you shape agent interactions in highly specialized ways. + diff --git a/docs/v1.15.13/en/guides/advanced/fingerprinting.mdx b/docs/v1.15.13/en/guides/advanced/fingerprinting.mdx new file mode 100644 index 0000000000..b6bd7ec02c --- /dev/null +++ b/docs/v1.15.13/en/guides/advanced/fingerprinting.mdx @@ -0,0 +1,134 @@ +--- +title: Fingerprinting +description: Learn how to use CrewAI's fingerprinting system to uniquely identify and track components throughout their lifecycle. +icon: fingerprint +mode: "wide" +--- + +## Overview + +Fingerprints in CrewAI provide a way to uniquely identify and track components throughout their lifecycle. Each `Agent`, `Crew`, and `Task` automatically receives a unique fingerprint when created, which cannot be manually overridden. + +These fingerprints can be used for: +- Auditing and tracking component usage +- Ensuring component identity integrity +- Attaching metadata to components +- Creating a traceable chain of operations + +## How Fingerprints Work + +A fingerprint is an instance of the `Fingerprint` class from the `crewai.security` module. Each fingerprint contains: + +- A UUID string: A unique identifier for the component that is automatically generated and cannot be manually set +- A creation timestamp: When the fingerprint was generated, automatically set and cannot be manually modified +- Metadata: A dictionary of additional information that can be customized + +Fingerprints are automatically generated and assigned when a component is created. Each component exposes its fingerprint through a read-only property. + +## Basic Usage + +### Accessing Fingerprints + +```python +from crewai import Agent, Crew, Task + +# Create components - fingerprints are automatically generated +agent = Agent( + role="Data Scientist", + goal="Analyze data", + backstory="Expert in data analysis" +) + +crew = Crew( + agents=[agent], + tasks=[] +) + +task = Task( + description="Analyze customer data", + expected_output="Insights from data analysis", + agent=agent +) + +# Access the fingerprints +agent_fingerprint = agent.fingerprint +crew_fingerprint = crew.fingerprint +task_fingerprint = task.fingerprint + +# Print the UUID strings +print(f"Agent fingerprint: {agent_fingerprint.uuid_str}") +print(f"Crew fingerprint: {crew_fingerprint.uuid_str}") +print(f"Task fingerprint: {task_fingerprint.uuid_str}") +``` + +### Working with Fingerprint Metadata + +You can add metadata to fingerprints for additional context: + +```python +# Add metadata to the agent's fingerprint +agent.security_config.fingerprint.metadata = { + "version": "1.0", + "department": "Data Science", + "project": "Customer Analysis" +} + +# Access the metadata +print(f"Agent metadata: {agent.fingerprint.metadata}") +``` + +## Fingerprint Persistence + +Fingerprints are designed to persist and remain unchanged throughout a component's lifecycle. If you modify a component, the fingerprint remains the same: + +```python +original_fingerprint = agent.fingerprint.uuid_str + +# Modify the agent +agent.goal = "New goal for analysis" + +# The fingerprint remains unchanged +assert agent.fingerprint.uuid_str == original_fingerprint +``` + +## Deterministic Fingerprints + +While you cannot directly set the UUID and creation timestamp, you can create deterministic fingerprints using the `generate` method with a seed: + +```python +from crewai.security import Fingerprint + +# Create a deterministic fingerprint using a seed string +deterministic_fingerprint = Fingerprint.generate(seed="my-agent-id") + +# The same seed always produces the same fingerprint +same_fingerprint = Fingerprint.generate(seed="my-agent-id") +assert deterministic_fingerprint.uuid_str == same_fingerprint.uuid_str + +# You can also set metadata +custom_fingerprint = Fingerprint.generate( + seed="my-agent-id", + metadata={"version": "1.0"} +) +``` + +## Advanced Usage + +### Fingerprint Structure + +Each fingerprint has the following structure: + +```python +from crewai.security import Fingerprint + +fingerprint = agent.fingerprint + +# UUID string - the unique identifier (auto-generated) +uuid_str = fingerprint.uuid_str # e.g., "123e4567-e89b-12d3-a456-426614174000" + +# Creation timestamp (auto-generated) +created_at = fingerprint.created_at # A datetime object + +# Metadata - for additional information (can be customized) +metadata = fingerprint.metadata # A dictionary, defaults to {} +``` \ No newline at end of file diff --git a/docs/v1.15.13/en/guides/agents/crafting-effective-agents.mdx b/docs/v1.15.13/en/guides/agents/crafting-effective-agents.mdx new file mode 100644 index 0000000000..c0141ddac3 --- /dev/null +++ b/docs/v1.15.13/en/guides/agents/crafting-effective-agents.mdx @@ -0,0 +1,453 @@ +--- +title: Crafting Effective Agents +description: Learn best practices for designing powerful, specialized AI agents that collaborate effectively to solve complex problems. +icon: robot +mode: "wide" +--- + +## The Art and Science of Agent Design + +At the heart of CrewAI lies the agent - a specialized AI entity designed to perform specific roles within a collaborative framework. While creating basic agents is simple, crafting truly effective agents that produce exceptional results requires understanding key design principles and best practices. + +This guide will help you master the art of agent design, enabling you to create specialized AI personas that collaborate effectively, think critically, and produce high-quality outputs tailored to your specific needs. + +### Why Agent Design Matters + +The way you define your agents significantly impacts: + +1. **Output quality**: Well-designed agents produce more relevant, high-quality results +2. **Collaboration effectiveness**: Agents with complementary skills work together more efficiently +3. **Task performance**: Agents with clear roles and goals execute tasks more effectively +4. **System scalability**: Thoughtfully designed agents can be reused across multiple crews and contexts + +Let's explore best practices for creating agents that excel in these dimensions. + +## The 80/20 Rule: Focus on Tasks Over Agents + +When building effective AI systems, remember this crucial principle: **80% of your effort should go into designing tasks, and only 20% into defining agents**. + +Why? Because even the most perfectly defined agent will fail with poorly designed tasks, but well-designed tasks can elevate even a simple agent. This means: + +- Spend most of your time writing clear task instructions +- Define detailed inputs and expected outputs +- Add examples and context to guide execution +- Dedicate the remaining time to agent role, goal, and backstory + +This doesn't mean agent design isn't important - it absolutely is. But task design is where most execution failures occur, so prioritize accordingly. + +## Core Principles of Effective Agent Design + +### 1. The Role-Goal-Backstory Framework + +The most powerful agents in CrewAI are built on a strong foundation of three key elements: + +#### Role: The Agent's Specialized Function + +The role defines what the agent does and their area of expertise. When crafting roles: + +- **Be specific and specialized**: Instead of "Writer," use "Technical Documentation Specialist" or "Creative Storyteller" +- **Align with real-world professions**: Base roles on recognizable professional archetypes +- **Include domain expertise**: Specify the agent's field of knowledge (e.g., "Financial Analyst specializing in market trends") + +**Examples of effective roles:** +```yaml +role: "Senior UX Researcher specializing in user interview analysis" +role: "Full-Stack Software Architect with expertise in distributed systems" +role: "Corporate Communications Director specializing in crisis management" +``` + +#### Goal: The Agent's Purpose and Motivation + +The goal directs the agent's efforts and shapes their decision-making process. Effective goals should: + +- **Be clear and outcome-focused**: Define what the agent is trying to achieve +- **Emphasize quality standards**: Include expectations about the quality of work +- **Incorporate success criteria**: Help the agent understand what "good" looks like + +**Examples of effective goals:** +```yaml +goal: "Uncover actionable user insights by analyzing interview data and identifying recurring patterns, unmet needs, and improvement opportunities" +goal: "Design robust, scalable system architectures that balance performance, maintainability, and cost-effectiveness" +goal: "Craft clear, empathetic crisis communications that address stakeholder concerns while protecting organizational reputation" +``` + +#### Backstory: The Agent's Experience and Perspective + +The backstory gives depth to the agent, influencing how they approach problems and interact with others. Good backstories: + +- **Establish expertise and experience**: Explain how the agent gained their skills +- **Define working style and values**: Describe how the agent approaches their work +- **Create a cohesive persona**: Ensure all elements of the backstory align with the role and goal + +**Examples of effective backstories:** +```yaml +backstory: "You have spent 15 years conducting and analyzing user research for top tech companies. You have a talent for reading between the lines and identifying patterns that others miss. You believe that good UX is invisible and that the best insights come from listening to what users don't say as much as what they do say." + +backstory: "With 20+ years of experience building distributed systems at scale, you've developed a pragmatic approach to software architecture. You've seen both successful and failed systems and have learned valuable lessons from each. You balance theoretical best practices with practical constraints and always consider the maintenance and operational aspects of your designs." + +backstory: "As a seasoned communications professional who has guided multiple organizations through high-profile crises, you understand the importance of transparency, speed, and empathy in crisis response. You have a methodical approach to crafting messages that address concerns while maintaining organizational credibility." +``` + +### 2. Specialists Over Generalists + +Agents perform significantly better when given specialized roles rather than general ones. A highly focused agent delivers more precise, relevant outputs: + +**Generic (Less Effective):** +```yaml +role: "Writer" +``` + +**Specialized (More Effective):** +```yaml +role: "Technical Blog Writer specializing in explaining complex AI concepts to non-technical audiences" +``` + +**Specialist Benefits:** +- Clearer understanding of expected output +- More consistent performance +- Better alignment with specific tasks +- Improved ability to make domain-specific judgments + +### 3. Balancing Specialization and Versatility + +Effective agents strike the right balance between specialization (doing one thing extremely well) and versatility (being adaptable to various situations): + +- **Specialize in role, versatile in application**: Create agents with specialized skills that can be applied across multiple contexts +- **Avoid overly narrow definitions**: Ensure agents can handle variations within their domain of expertise +- **Consider the collaborative context**: Design agents whose specializations complement the other agents they'll work with + +### 4. Setting Appropriate Expertise Levels + +The expertise level you assign to your agent shapes how they approach tasks: + +- **Novice agents**: Good for straightforward tasks, brainstorming, or initial drafts +- **Intermediate agents**: Suitable for most standard tasks with reliable execution +- **Expert agents**: Best for complex, specialized tasks requiring depth and nuance +- **World-class agents**: Reserved for critical tasks where exceptional quality is needed + +Choose the appropriate expertise level based on task complexity and quality requirements. For most collaborative crews, a mix of expertise levels often works best, with higher expertise assigned to core specialized functions. + +## Practical Examples: Before and After + +Let's look at some examples of agent definitions before and after applying these best practices: + +### Example 1: Content Creation Agent + +**Before:** +```yaml +role: "Writer" +goal: "Write good content" +backstory: "You are a writer who creates content for websites." +``` + +**After:** +```yaml +role: "B2B Technology Content Strategist" +goal: "Create compelling, technically accurate content that explains complex topics in accessible language while driving reader engagement and supporting business objectives" +backstory: "You have spent a decade creating content for leading technology companies, specializing in translating technical concepts for business audiences. You excel at research, interviewing subject matter experts, and structuring information for maximum clarity and impact. You believe that the best B2B content educates first and sells second, building trust through genuine expertise rather than marketing hype." +``` + +### Example 2: Research Agent + +**Before:** +```yaml +role: "Researcher" +goal: "Find information" +backstory: "You are good at finding information online." +``` + +**After:** +```yaml +role: "Academic Research Specialist in Emerging Technologies" +goal: "Discover and synthesize cutting-edge research, identifying key trends, methodologies, and findings while evaluating the quality and reliability of sources" +backstory: "With a background in both computer science and library science, you've mastered the art of digital research. You've worked with research teams at prestigious universities and know how to navigate academic databases, evaluate research quality, and synthesize findings across disciplines. You're methodical in your approach, always cross-referencing information and tracing claims to primary sources before drawing conclusions." +``` + +## Crafting Effective Tasks for Your Agents + +While agent design is important, task design is critical for successful execution. Here are best practices for designing tasks that set your agents up for success: + +### The Anatomy of an Effective Task + +A well-designed task has two key components that serve different purposes: + +#### Task Description: The Process +The description should focus on what to do and how to do it, including: +- Detailed instructions for execution +- Context and background information +- Scope and constraints +- Process steps to follow + +#### Expected Output: The Deliverable +The expected output should define what the final result should look like: +- Format specifications (markdown, JSON, etc.) +- Structure requirements +- Quality criteria +- Examples of good outputs (when possible) + +### Task Design Best Practices + +#### 1. Single Purpose, Single Output +Tasks perform best when focused on one clear objective: + +**Bad Example (Too Broad):** +```yaml +task_description: "Research market trends, analyze the data, and create a visualization." +``` + +**Good Example (Focused):** +```yaml +# Task 1 +research_task: + description: "Research the top 5 market trends in the AI industry for 2024." + expected_output: "A markdown list of the 5 trends with supporting evidence." + +# Task 2 +analysis_task: + description: "Analyze the identified trends to determine potential business impacts." + expected_output: "A structured analysis with impact ratings (High/Medium/Low)." + +# Task 3 +visualization_task: + description: "Create a visual representation of the analyzed trends." + expected_output: "A description of a chart showing trends and their impact ratings." +``` + +#### 2. Be Explicit About Inputs and Outputs +Always clearly specify what inputs the task will use and what the output should look like: + +**Example:** +```yaml +analysis_task: + description: > + Analyze the customer feedback data from the CSV file. + Focus on identifying recurring themes related to product usability. + Consider sentiment and frequency when determining importance. + expected_output: > + A markdown report with the following sections: + 1. Executive summary (3-5 bullet points) + 2. Top 3 usability issues with supporting data + 3. Recommendations for improvement +``` + +#### 3. Include Purpose and Context +Explain why the task matters and how it fits into the larger workflow: + +**Example:** +```yaml +competitor_analysis_task: + description: > + Analyze our three main competitors' pricing strategies. + This analysis will inform our upcoming pricing model revision. + Focus on identifying patterns in how they price premium features + and how they structure their tiered offerings. +``` + +#### 4. Use Structured Output Tools +For machine-readable outputs, specify the format clearly: + +**Example:** +```yaml +data_extraction_task: + description: "Extract key metrics from the quarterly report." + expected_output: "JSON object with the following keys: revenue, growth_rate, customer_acquisition_cost, and retention_rate." +``` + +## Common Mistakes to Avoid + +Based on lessons learned from real-world implementations, here are the most common pitfalls in agent and task design: + +### 1. Unclear Task Instructions + +**Problem:** Tasks lack sufficient detail, making it difficult for agents to execute effectively. + +**Example of Poor Design:** +```yaml +research_task: + description: "Research AI trends." + expected_output: "A report on AI trends." +``` + +**Improved Version:** +```yaml +research_task: + description: > + Research the top emerging AI trends for 2024 with a focus on: + 1. Enterprise adoption patterns + 2. Technical breakthroughs in the past 6 months + 3. Regulatory developments affecting implementation + + For each trend, identify key companies, technologies, and potential business impacts. + expected_output: > + A comprehensive markdown report with: + - Executive summary (5 bullet points) + - 5-7 major trends with supporting evidence + - For each trend: definition, examples, and business implications + - References to authoritative sources +``` + +### 2. "God Tasks" That Try to Do Too Much + +**Problem:** Tasks that combine multiple complex operations into one instruction set. + +**Example of Poor Design:** +```yaml +comprehensive_task: + description: "Research market trends, analyze competitor strategies, create a marketing plan, and design a launch timeline." +``` + +**Improved Version:** +Break this into sequential, focused tasks: +```yaml +# Task 1: Research +market_research_task: + description: "Research current market trends in the SaaS project management space." + expected_output: "A markdown summary of key market trends." + +# Task 2: Competitive Analysis +competitor_analysis_task: + description: "Analyze strategies of the top 3 competitors based on the market research." + expected_output: "A comparison table of competitor strategies." + context: [market_research_task] + +# Continue with additional focused tasks... +``` + +### 3. Misaligned Description and Expected Output + +**Problem:** The task description asks for one thing while the expected output specifies something different. + +**Example of Poor Design:** +```yaml +analysis_task: + description: "Analyze customer feedback to find areas of improvement." + expected_output: "A marketing plan for the next quarter." +``` + +**Improved Version:** +```yaml +analysis_task: + description: "Analyze customer feedback to identify the top 3 areas for product improvement." + expected_output: "A report listing the 3 priority improvement areas with supporting customer quotes and data points." +``` + +### 4. Not Understanding the Process Yourself + +**Problem:** Asking agents to execute tasks that you yourself don't fully understand. + +**Solution:** +1. Try to perform the task manually first +2. Document your process, decision points, and information sources +3. Use this documentation as the basis for your task description + +### 5. Premature Use of Hierarchical Structures + +**Problem:** Creating unnecessarily complex agent hierarchies where sequential processes would work better. + +**Solution:** Start with sequential processes and only move to hierarchical models when the workflow complexity truly requires it. + +### 6. Vague or Generic Agent Definitions + +**Problem:** Generic agent definitions lead to generic outputs. + +**Example of Poor Design:** +```yaml +agent: + role: "Business Analyst" + goal: "Analyze business data" + backstory: "You are good at business analysis." +``` + +**Improved Version:** +```yaml +agent: + role: "SaaS Metrics Specialist focusing on growth-stage startups" + goal: "Identify actionable insights from business data that can directly impact customer retention and revenue growth" + backstory: "With 10+ years analyzing SaaS business models, you've developed a keen eye for the metrics that truly matter for sustainable growth. You've helped numerous companies identify the leverage points that turned around their business trajectory. You believe in connecting data to specific, actionable recommendations rather than general observations." +``` + +## Advanced Agent Design Strategies + +### Designing for Collaboration + +When creating agents that will work together in a crew, consider: + +- **Complementary skills**: Design agents with distinct but complementary abilities +- **Handoff points**: Define clear interfaces for how work passes between agents +- **Constructive tension**: Sometimes, creating agents with slightly different perspectives can lead to better outcomes through productive dialogue + +For example, a content creation crew might include: + +```yaml +# Research Agent +role: "Research Specialist for technical topics" +goal: "Gather comprehensive, accurate information from authoritative sources" +backstory: "You are a meticulous researcher with a background in library science..." + +# Writer Agent +role: "Technical Content Writer" +goal: "Transform research into engaging, clear content that educates and informs" +backstory: "You are an experienced writer who excels at explaining complex concepts..." + +# Editor Agent +role: "Content Quality Editor" +goal: "Ensure content is accurate, well-structured, and polished while maintaining consistency" +backstory: "With years of experience in publishing, you have a keen eye for detail..." +``` + +### Creating Specialized Tool Users + +Some agents can be designed specifically to leverage certain tools effectively: + +```yaml +role: "Data Analysis Specialist" +goal: "Derive meaningful insights from complex datasets through statistical analysis" +backstory: "With a background in data science, you excel at working with structured and unstructured data..." +tools: [PythonREPLTool, DataVisualizationTool, CSVAnalysisTool] +``` + +### Tailoring Agents to LLM Capabilities + +Different LLMs have different strengths. Design your agents with these capabilities in mind: + +```yaml +# For complex reasoning tasks +analyst: + role: "Data Insights Analyst" + goal: "..." + backstory: "..." + llm: openai/gpt-4o + +# For creative content +writer: + role: "Creative Content Writer" + goal: "..." + backstory: "..." + llm: anthropic/claude-3-opus +``` + +## Testing and Iterating on Agent Design + +Agent design is often an iterative process. Here's a practical approach: + +1. **Start with a prototype**: Create an initial agent definition +2. **Test with sample tasks**: Evaluate performance on representative tasks +3. **Analyze outputs**: Identify strengths and weaknesses +4. **Refine the definition**: Adjust role, goal, and backstory based on observations +5. **Test in collaboration**: Evaluate how the agent performs in a crew setting + +## Conclusion + +Crafting effective agents is both an art and a science. By carefully defining roles, goals, and backstories that align with your specific needs, and combining them with well-designed tasks, you can create specialized AI collaborators that produce exceptional results. + +Remember that agent and task design is an iterative process. Start with these best practices, observe your agents in action, and refine your approach based on what you learn. And always keep in mind the 80/20 rule - focus most of your effort on creating clear, focused tasks to get the best results from your agents. + + +Congratulations! You now understand the principles and practices of effective agent design. Apply these techniques to create powerful, specialized agents that work together seamlessly to accomplish complex tasks. + + +## Next Steps + +- Experiment with different agent configurations for your specific use case +- Learn about [building your first crew](/en/guides/crews/first-crew) to see how agents work together +- Explore [CrewAI Flows](/en/guides/flows/first-flow) for more advanced orchestration diff --git a/docs/v1.15.13/en/guides/coding-tools/agents-md.mdx b/docs/v1.15.13/en/guides/coding-tools/agents-md.mdx new file mode 100644 index 0000000000..3736a7b6a0 --- /dev/null +++ b/docs/v1.15.13/en/guides/coding-tools/agents-md.mdx @@ -0,0 +1,65 @@ +--- +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 create tool my_tool +``` + + + `crewai tool create` is deprecated and still works with a warning. Use `crewai create tool` instead. + + +## 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. diff --git a/docs/v1.15.13/en/guides/coding-tools/build-with-ai.mdx b/docs/v1.15.13/en/guides/coding-tools/build-with-ai.mdx new file mode 100644 index 0000000000..6c03b23237 --- /dev/null +++ b/docs/v1.15.13/en/guides/coding-tools/build-with-ai.mdx @@ -0,0 +1,214 @@ +--- +title: "Build with AI" +description: "Everything AI coding agents need to build, deploy, and scale with CrewAI — skills, machine-readable docs, deployment, and enterprise features." +icon: robot +mode: "wide" +--- + +# Build with AI + +CrewAI is AI-native. This page brings together everything an AI coding agent needs to build with CrewAI — whether you're Claude Code, Codex, Cursor, Gemini CLI, or any other assistant helping a developer ship crews and flows. + +### Supported Coding Agents + + + + + + + + + + + This page is designed to be consumed by both humans and AI assistants. If you're a coding agent, start with **Skills** to get CrewAI context, then use **llms.txt** for full docs access. + + +--- + +## 1. Skills — Teach Your Agent CrewAI + +**Skills** are instruction packs that give coding agents deep CrewAI knowledge — how to scaffold Flows, configure Crews, use tools, and follow framework conventions. + + + + Anthropic + CrewAI skills are available in the **Claude Code plugin marketplace** — the same distribution channel used by top AI-native companies: + ```shell + /plugin marketplace add crewAIInc/skills + /plugin install crewai-skills@crewai-plugins + /reload-plugins + ``` + + Four skills activate automatically when you ask relevant CrewAI questions: + + | Skill | When it runs | + |-------|--------------| + | `getting-started` | Scaffolding new projects, choosing between `LLM.call()` / `Agent` / `Crew` / `Flow`, wiring `crew.jsonc` / `main.py` | + | `design-agent` | Configuring agents — role, goal, backstory, tools, LLMs, memory, guardrails | + | `design-task` | Writing task descriptions, dependencies, structured output (`output_pydantic`, `output_json`), human review | + | `ask-docs` | Querying the live [CrewAI docs MCP server](https://docs.crewai.com/mcp) for up-to-date API details | + + + Works with Claude Code, Codex, Cursor, Gemini CLI, or any coding agent: + ```shell + npx skills add crewaiinc/skills + ``` + Pulls from the [skills.sh registry](https://skills.sh/crewaiinc/skills). + + + + + + Use either method above — the Claude Code plugin marketplace or `npx skills add`. Both install the official [crewAIInc/skills](https://github.com/crewAIInc/skills) pack. + + + The skill pack teaches your agent: + - **Flows** — stateful apps, steps, and crew kickoffs + - **Crews & Agents** — JSON-first patterns (`crew.jsonc`, `agents/*.jsonc`), roles, tasks, delegation + - **Tools & Integrations** — search, APIs, MCP servers, and common CrewAI tools + - **Project layout** — CLI scaffolds and repo conventions + - **Up-to-date patterns** — tracks current CrewAI docs and best practices + + + Your agent can now scaffold and build CrewAI projects without you re-explaining the framework each session. + + + + + + How skills work in CrewAI agents — injection, activation, and patterns. + + + Overview of the crewAIInc/skills pack and what it includes. + + + Set up AGENTS.md for Claude Code, Codex, Cursor, and Gemini CLI. + + + Official listing — skills, install stats, and audits. + + + +--- + +## 2. llms.txt — Machine-Readable Docs + +CrewAI publishes an `llms.txt` file that gives AI assistants direct access to the full documentation in a machine-readable format. + +``` +https://docs.crewai.com/llms.txt +``` + + + + [`llms.txt`](https://llmstxt.org/) is an emerging standard for making documentation consumable by large language models. Instead of scraping HTML, your agent can fetch a single structured text file with all the content it needs. + + CrewAI's `llms.txt` is **already live** — your agent can use it right now. + + + Point your coding agent at the URL when it needs CrewAI reference docs: + + ``` + Fetch https://docs.crewai.com/llms.txt for CrewAI documentation. + ``` + + Many coding agents (Claude Code, Cursor, etc.) can fetch URLs directly. The file contains structured documentation covering all CrewAI concepts, APIs, and guides. + + + - **No scraping required** — clean, structured content in one request + - **Always up-to-date** — served directly from docs.crewai.com + - **Optimized for LLMs** — formatted for context windows, not browsers + - **Complements skills** — skills teach patterns, llms.txt provides reference + + + +--- + +## 3. Deploy to Enterprise + +Go from a local crew to production on **CrewAI AMP** (Agent Management Platform) in minutes. + + + + Scaffold and test your crew or flow: + ```bash + crewai create crew my_crew + cd my_crew + crewai run + ``` + + + Ensure your project structure is ready: + ```bash + crewai deploy --prepare + ``` + See the [preparation guide](https://docs-platform.crewai.com/platform/en/guides/prepare-for-deployment) for details on project structure and requirements. + + + Push to the CrewAI AMP platform: + ```bash + crewai deploy + ``` + You can also deploy via [GitHub integration](https://docs-platform.crewai.com/platform/en/guides/deploy-to-amp) or [Crew Studio](https://docs-platform.crewai.com/platform/en/guides/enable-crew-studio). + + + Your deployed crew gets a REST API endpoint. Integrate it into any application: + ```bash + curl -X POST https://app.crewai.com/api/v1/crews//kickoff \ + -H "Authorization: Bearer $CREWAI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"inputs": {"topic": "AI agents"}}' + ``` + + + + + + Full deployment guide — CLI, GitHub, and Crew Studio methods. + + + Platform overview — what AMP provides for production crews. + + + +--- + +## 4. Enterprise Features + +CrewAI AMP is built for production teams. Here's what you get beyond deployment. + + + + Detailed execution traces, logs, and performance metrics for every crew run. Monitor agent decisions, tool calls, and task completion in real time. + + + No-code/low-code interface to create, customize, and deploy crews visually — then export to code or deploy directly. + + + Stream real-time events from crew executions to your systems. Integrate with Slack, Zapier, or any webhook consumer. + + + SSO, RBAC, and organization-level controls. Manage who can create, deploy, and access crews across your team. + + + Publish and share custom tools across your organization. Install community tools from the registry. + + + Run CrewAI AMP on your own infrastructure. Full platform capabilities with data residency and compliance controls. + + + + + + AMP is for teams that need to move AI agent workflows from prototypes to production — with observability, access controls, and scalable infrastructure. Whether you're a startup or enterprise, AMP handles the operational complexity so you can focus on building agents. + + + - **Cloud (app.crewai.com)** — managed by CrewAI, fastest path to production + - **Factory (self-hosted)** — run on your own infrastructure for full data control + - **Hybrid** — mix cloud and self-hosted based on sensitivity requirements + + + + + Sign up and deploy your first crew to production. + diff --git a/docs/v1.15.13/en/guides/concepts/evaluating-use-cases.mdx b/docs/v1.15.13/en/guides/concepts/evaluating-use-cases.mdx new file mode 100644 index 0000000000..186afa2c64 --- /dev/null +++ b/docs/v1.15.13/en/guides/concepts/evaluating-use-cases.mdx @@ -0,0 +1,504 @@ +--- +title: Evaluating Use Cases for CrewAI +description: Learn how to assess your AI application needs and choose the right approach between Crews and Flows based on complexity and precision requirements. +icon: scale-balanced +mode: "wide" +--- + +## Understanding the Decision Framework + +When building AI applications with CrewAI, one of the most important decisions you'll make is choosing the right approach for your specific use case. Should you use a Crew? A Flow? A combination of both? This guide will help you evaluate your requirements and make informed architectural decisions. + +At the heart of this decision is understanding the relationship between **complexity** and **precision** in your application: + + + Complexity vs. Precision Matrix + + +This matrix helps visualize how different approaches align with varying requirements for complexity and precision. Let's explore what each quadrant means and how it guides your architectural choices. + +## The Complexity-Precision Matrix Explained + +### What is Complexity? + +In the context of CrewAI applications, **complexity** refers to: + +- The number of distinct steps or operations required +- The diversity of tasks that need to be performed +- The interdependencies between different components +- The need for conditional logic and branching +- The sophistication of the overall workflow + +### What is Precision? + +**Precision** in this context refers to: + +- The accuracy required in the final output +- The need for structured, predictable results +- The importance of reproducibility +- The level of control needed over each step +- The tolerance for variation in outputs + +### The Four Quadrants + +#### 1. Low Complexity, Low Precision + +**Characteristics:** +- Simple, straightforward tasks +- Tolerance for some variation in outputs +- Limited number of steps +- Creative or exploratory applications + +**Recommended Approach:** Simple Crews with minimal agents + +**Example Use Cases:** +- Basic content generation +- Idea brainstorming +- Simple summarization tasks +- Creative writing assistance + +#### 2. Low Complexity, High Precision + +**Characteristics:** +- Simple workflows that require exact, structured outputs +- Need for reproducible results +- Limited steps but high accuracy requirements +- Often involves data processing or transformation + +**Recommended Approach:** Flows with direct LLM calls or simple Crews with structured outputs + +**Example Use Cases:** +- Data extraction and transformation +- Form filling and validation +- Structured content generation (JSON, XML) +- Simple classification tasks + +#### 3. High Complexity, Low Precision + +**Characteristics:** +- Multi-stage processes with many steps +- Creative or exploratory outputs +- Complex interactions between components +- Tolerance for variation in final results + +**Recommended Approach:** Complex Crews with multiple specialized agents + +**Example Use Cases:** +- Research and analysis +- Content creation pipelines +- Exploratory data analysis +- Creative problem-solving + +#### 4. High Complexity, High Precision + +**Characteristics:** +- Complex workflows requiring structured outputs +- Multiple interdependent steps with strict accuracy requirements +- Need for both sophisticated processing and precise results +- Often mission-critical applications + +**Recommended Approach:** Flows orchestrating multiple Crews with validation steps + +**Example Use Cases:** +- Enterprise decision support systems +- Complex data processing pipelines +- Multi-stage document processing +- Regulated industry applications + +## Choosing Between Crews and Flows + +### When to Choose Crews + +Crews are ideal when: + +1. **You need collaborative intelligence** - Multiple agents with different specializations need to work together +2. **The problem requires emergent thinking** - The solution benefits from different perspectives and approaches +3. **The task is primarily creative or analytical** - The work involves research, content creation, or analysis +4. **You value adaptability over strict structure** - The workflow can benefit from agent autonomy +5. **The output format can be somewhat flexible** - Some variation in output structure is acceptable + +```python +# Example: Research Crew for market analysis +from crewai import Agent, Crew, Process, Task + +# Create specialized agents +researcher = Agent( + role="Market Research Specialist", + goal="Find comprehensive market data on emerging technologies", + backstory="You are an expert at discovering market trends and gathering data." +) + +analyst = Agent( + role="Market Analyst", + goal="Analyze market data and identify key opportunities", + backstory="You excel at interpreting market data and spotting valuable insights." +) + +# Define their tasks +research_task = Task( + description="Research the current market landscape for AI-powered healthcare solutions", + expected_output="Comprehensive market data including key players, market size, and growth trends", + agent=researcher +) + +analysis_task = Task( + description="Analyze the market data and identify the top 3 investment opportunities", + expected_output="Analysis report with 3 recommended investment opportunities and rationale", + agent=analyst, + context=[research_task] +) + +# Create the crew +market_analysis_crew = Crew( + agents=[researcher, analyst], + tasks=[research_task, analysis_task], + process=Process.sequential, + verbose=True +) + +# Run the crew +result = market_analysis_crew.kickoff() +``` + +### When to Choose Flows + +Flows are ideal when: + +1. **You need precise control over execution** - The workflow requires exact sequencing and state management +2. **The application has complex state requirements** - You need to maintain and transform state across multiple steps +3. **You need structured, predictable outputs** - The application requires consistent, formatted results +4. **The workflow involves conditional logic** - Different paths need to be taken based on intermediate results +5. **You need to combine AI with procedural code** - The solution requires both AI capabilities and traditional programming + +```python +# Example: Customer Support Flow with structured processing +from crewai.flow.flow import Flow, listen, or_, router, start +from pydantic import BaseModel +from typing import List, Dict + +# Define structured state +class SupportTicketState(BaseModel): + ticket_id: str = "" + customer_name: str = "" + issue_description: str = "" + category: str = "" + priority: str = "medium" + resolution: str = "" + satisfaction_score: int = 0 + +class CustomerSupportFlow(Flow[SupportTicketState]): + @start() + def receive_ticket(self): + # In a real app, this might come from an API + self.state.ticket_id = "TKT-12345" + self.state.customer_name = "Alex Johnson" + self.state.issue_description = "Unable to access premium features after payment" + return "Ticket received" + + @listen(receive_ticket) + def categorize_ticket(self, _): + # Use a direct LLM call for categorization + from crewai import LLM + llm = LLM(model="openai/gpt-4o-mini") + + prompt = f""" + Categorize the following customer support issue into one of these categories: + - Billing + - Account Access + - Technical Issue + - Feature Request + - Other + + Issue: {self.state.issue_description} + + Return only the category name. + """ + + self.state.category = llm.call(prompt).strip() + return self.state.category + + @router(categorize_ticket) + def route_by_category(self, category): + # Route to different handlers based on category + return category.lower().replace(" ", "_") + + @listen("billing") + def handle_billing_issue(self): + # Handle billing-specific logic + self.state.priority = "high" + # More billing-specific processing... + return "Billing issue handled" + + @listen("account_access") + def handle_access_issue(self): + # Handle access-specific logic + self.state.priority = "high" + # More access-specific processing... + return "Access issue handled" + + # Additional category handlers... + + @listen(or_("billing", "account_access", "technical_issue", "feature_request", "other")) + def resolve_ticket(self, resolution_info): + # Final resolution step + self.state.resolution = f"Issue resolved: {resolution_info}" + return self.state.resolution + +# Run the flow +support_flow = CustomerSupportFlow() +result = support_flow.kickoff() +``` + +### When to Combine Crews and Flows + +The most sophisticated applications often benefit from combining Crews and Flows: + +1. **Complex multi-stage processes** - Use Flows to orchestrate the overall process and Crews for complex subtasks +2. **Applications requiring both creativity and structure** - Use Crews for creative tasks and Flows for structured processing +3. **Enterprise-grade AI applications** - Use Flows to manage state and process flow while leveraging Crews for specialized work + +```python +# Example: Content Production Pipeline combining Crews and Flows +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel +from typing import List, Dict + +class ContentState(BaseModel): + topic: str = "" + target_audience: str = "" + content_type: str = "" + outline: Dict = {} + draft_content: str = "" + final_content: str = "" + seo_score: int = 0 + +class ContentProductionFlow(Flow[ContentState]): + @start() + def initialize_project(self): + # Set initial parameters + self.state.topic = "Sustainable Investing" + self.state.target_audience = "Millennial Investors" + self.state.content_type = "Blog Post" + return "Project initialized" + + @listen(initialize_project) + def create_outline(self, _): + # Use a research crew to create an outline + researcher = Agent( + role="Content Researcher", + goal=f"Research {self.state.topic} for {self.state.target_audience}", + backstory="You are an expert researcher with deep knowledge of content creation." + ) + + outliner = Agent( + role="Content Strategist", + goal=f"Create an engaging outline for a {self.state.content_type}", + backstory="You excel at structuring content for maximum engagement." + ) + + research_task = Task( + description=f"Research {self.state.topic} focusing on what would interest {self.state.target_audience}", + expected_output="Comprehensive research notes with key points and statistics", + agent=researcher + ) + + outline_task = Task( + description=f"Create an outline for a {self.state.content_type} about {self.state.topic}", + expected_output="Detailed content outline with sections and key points", + agent=outliner, + context=[research_task] + ) + + outline_crew = Crew( + agents=[researcher, outliner], + tasks=[research_task, outline_task], + process=Process.sequential, + verbose=True + ) + + # Run the crew and store the result + result = outline_crew.kickoff() + + # Parse the outline (in a real app, you might use a more robust parsing approach) + import json + try: + self.state.outline = json.loads(result.raw) + except: + # Fallback if not valid JSON + self.state.outline = {"sections": result.raw} + + return "Outline created" + + @listen(create_outline) + def write_content(self, _): + # Use a writing crew to create the content + writer = Agent( + role="Content Writer", + goal=f"Write engaging content for {self.state.target_audience}", + backstory="You are a skilled writer who creates compelling content." + ) + + editor = Agent( + role="Content Editor", + goal="Ensure content is polished, accurate, and engaging", + backstory="You have a keen eye for detail and a talent for improving content." + ) + + writing_task = Task( + description=f"Write a {self.state.content_type} about {self.state.topic} following this outline: {self.state.outline}", + expected_output="Complete draft content in markdown format", + agent=writer + ) + + editing_task = Task( + description="Edit and improve the draft content for clarity, engagement, and accuracy", + expected_output="Polished final content in markdown format", + agent=editor, + context=[writing_task] + ) + + writing_crew = Crew( + agents=[writer, editor], + tasks=[writing_task, editing_task], + process=Process.sequential, + verbose=True + ) + + # Run the crew and store the result + result = writing_crew.kickoff() + self.state.final_content = result.raw + + return "Content created" + + @listen(write_content) + def optimize_for_seo(self, _): + # Use a direct LLM call for SEO optimization + from crewai import LLM + llm = LLM(model="openai/gpt-4o-mini") + + prompt = f""" + Analyze this content for SEO effectiveness for the keyword "{self.state.topic}". + Rate it on a scale of 1-100 and provide 3 specific recommendations for improvement. + + Content: {self.state.final_content[:1000]}... (truncated for brevity) + + Format your response as JSON with the following structure: + {{ + "score": 85, + "recommendations": [ + "Recommendation 1", + "Recommendation 2", + "Recommendation 3" + ] + }} + """ + + seo_analysis = llm.call(prompt) + + # Parse the SEO analysis + import json + try: + analysis = json.loads(seo_analysis) + self.state.seo_score = analysis.get("score", 0) + return analysis + except: + self.state.seo_score = 50 + return {"score": 50, "recommendations": ["Unable to parse SEO analysis"]} + +# Run the flow +content_flow = ContentProductionFlow() +result = content_flow.kickoff() +``` + +## Practical Evaluation Framework + +To determine the right approach for your specific use case, follow this step-by-step evaluation framework: + +### Step 1: Assess Complexity + +Rate your application's complexity on a scale of 1-10 by considering: + +1. **Number of steps**: How many distinct operations are required? + - 1-3 steps: Low complexity (1-3) + - 4-7 steps: Medium complexity (4-7) + - 8+ steps: High complexity (8-10) + +2. **Interdependencies**: How interconnected are the different parts? + - Few dependencies: Low complexity (1-3) + - Some dependencies: Medium complexity (4-7) + - Many complex dependencies: High complexity (8-10) + +3. **Conditional logic**: How much branching and decision-making is needed? + - Linear process: Low complexity (1-3) + - Some branching: Medium complexity (4-7) + - Complex decision trees: High complexity (8-10) + +4. **Domain knowledge**: How specialized is the knowledge required? + - General knowledge: Low complexity (1-3) + - Some specialized knowledge: Medium complexity (4-7) + - Deep expertise in multiple domains: High complexity (8-10) + +Calculate your average score to determine overall complexity. + +### Step 2: Assess Precision Requirements + +Rate your precision requirements on a scale of 1-10 by considering: + +1. **Output structure**: How structured must the output be? + - Free-form text: Low precision (1-3) + - Semi-structured: Medium precision (4-7) + - Strictly formatted (JSON, XML): High precision (8-10) + +2. **Accuracy needs**: How important is factual accuracy? + - Creative content: Low precision (1-3) + - Informational content: Medium precision (4-7) + - Critical information: High precision (8-10) + +3. **Reproducibility**: How consistent must results be across runs? + - Variation acceptable: Low precision (1-3) + - Some consistency needed: Medium precision (4-7) + - Exact reproducibility required: High precision (8-10) + +4. **Error tolerance**: What is the impact of errors? + - Low impact: Low precision (1-3) + - Moderate impact: Medium precision (4-7) + - High impact: High precision (8-10) + +Calculate your average score to determine overall precision requirements. + +### Step 3: Map to the Matrix + +Plot your complexity and precision scores on the matrix: + +- **Low Complexity (1-4), Low Precision (1-4)**: Simple Crews +- **Low Complexity (1-4), High Precision (5-10)**: Flows with direct LLM calls +- **High Complexity (5-10), Low Precision (1-4)**: Complex Crews +- **High Complexity (5-10), High Precision (5-10)**: Flows orchestrating Crews + +### Step 4: Consider Additional Factors + +Beyond complexity and precision, consider: + +1. **Development time**: Crews are often faster to prototype +2. **Maintenance needs**: Flows provide better long-term maintainability +3. **Team expertise**: Consider your team's familiarity with different approaches +4. **Scalability requirements**: Flows typically scale better for complex applications +5. **Integration needs**: Consider how the solution will integrate with existing systems + +## Conclusion + +Choosing between Crews and Flows—or combining them—is a critical architectural decision that impacts the effectiveness, maintainability, and scalability of your CrewAI application. By evaluating your use case along the dimensions of complexity and precision, you can make informed decisions that align with your specific requirements. + +Remember that the best approach often evolves as your application matures. Start with the simplest solution that meets your needs, and be prepared to refine your architecture as you gain experience and your requirements become clearer. + + +You now have a framework for evaluating CrewAI use cases and choosing the right approach based on complexity and precision requirements. This will help you build more effective, maintainable, and scalable AI applications. + + +## Next Steps + +- Learn more about [crafting effective agents](/en/guides/agents/crafting-effective-agents) +- Explore [building your first crew](/en/guides/crews/first-crew) +- Dive into [mastering flow state management](/en/guides/flows/mastering-flow-state) +- Check out the [core concepts](/en/concepts/agents) for deeper understanding diff --git a/docs/v1.15.13/en/guides/crews/first-crew.mdx b/docs/v1.15.13/en/guides/crews/first-crew.mdx new file mode 100644 index 0000000000..9665a293aa --- /dev/null +++ b/docs/v1.15.13/en/guides/crews/first-crew.mdx @@ -0,0 +1,162 @@ +--- +title: Build Your First Crew +description: Step-by-step tutorial to create a collaborative AI team with JSON-first crew configuration. +icon: users-gear +mode: "wide" +--- + +## Build a Research Crew + +In this guide, you will create a two-agent research crew that gathers information about a topic and writes a markdown report. New crew projects are JSON-first: agents are defined in `agents/*.jsonc`, tasks and crew settings are defined in `crew.jsonc`, and `crewai run` loads the JSON definition directly. + +### Prerequisites + +Before starting, make sure you have: + +1. Installed CrewAI following the [installation guide](/en/installation) +2. Set up your LLM API key following the [LLM setup guide](/en/concepts/llms#setting-up-your-llm) +3. A [Serper.dev](https://serper.dev/) API key if you want the researcher to use web search + +## Step 1: Create a New Crew + +```bash +crewai create crew research_crew +cd research_crew +``` + +The CLI creates a JSON-first project: + +```text +research_crew/ +├── .gitignore +├── .env +├── agents/ +│ └── researcher.jsonc +├── crew.jsonc +├── knowledge/ +├── pyproject.toml +├── README.md +├── skills/ +└── tools/ +``` + + +Need the older `crew.py`, `config/agents.yaml`, and `config/tasks.yaml` layout? Create it with `crewai create crew research_crew --classic`. + + +## Step 2: Define Your Agents + +Replace the generated `agents/researcher.jsonc` file and add `agents/analyst.jsonc`. The file names are the names you reference from `crew.jsonc`. + +```jsonc agents/researcher.jsonc +{ + "role": "Senior Research Specialist for {topic}", + "goal": "Find comprehensive and accurate information about {topic}, with a focus on recent developments and key insights.", + "backstory": "You are an experienced research specialist who organizes complex information into clear, useful notes.", + // Replace with your model, for example "openai/gpt-4o". + "llm": "provider/model-id", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +```jsonc agents/analyst.jsonc +{ + "role": "Report Analyst for {topic}", + "goal": "Turn research findings into a clear, well-structured report.", + "backstory": "You are a careful analyst with strong technical writing skills and a talent for extracting useful insights.", + // Replace with your model, for example "openai/gpt-4o". + "llm": "provider/model-id", + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +Replace `provider/model-id` with the model you use, for example `openai/gpt-4o`, `anthropic/claude-sonnet-4-6`, or `gemini/gemini-2.0-flash-001`. + +## Step 3: Define Tasks and Crew Settings + +Replace `crew.jsonc` with: + +```jsonc crew.jsonc +{ + "name": "Research Crew", + "agents": ["researcher", "analyst"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research on {topic}. Focus on key concepts, recent developments, major challenges, notable applications, and future outlook.", + "expected_output": "A comprehensive research document with organized sections, specific facts, and useful examples about {topic}.", + "agent": "researcher" + }, + { + "name": "analysis_task", + "description": "Analyze the research findings and create a polished report on {topic}. Include an executive summary, key insights, trend analysis, and recommendations.", + "expected_output": "A professional markdown report with clear headings, a concise summary, main findings, and recommendations.", + "agent": "analyst", + "context": ["research_task"], + "output_file": "output/report.md", + "markdown": true + } + ], + "process": "sequential", + "verbose": true, + "memory": true, + "inputs": { + "topic": "Artificial Intelligence in Healthcare" + } +} +``` + +`context` points to prior task names, so the analyst receives the research task output. The `inputs` object provides default values for `{topic}`. If you remove a default, `crewai run` prompts for it. + +## Step 4: Set Environment Variables + +Open `.env` and add the keys your model and tools need: + +```sh +SERPER_API_KEY=your_serper_api_key +# Add your model provider API key here too. +``` + +See the [LLM setup guide](/en/concepts/llms#setting-up-your-llm) for provider-specific keys. + +## Step 5: Install and Run + +```bash +crewai install +crewai run +``` + +`crewai run` detects `crew.jsonc`, loads the agents from `agents/`, prompts for missing placeholders, and runs the crew. When the run finishes, open `output/report.md`. + +## How It Works + +1. `crew.jsonc` defines the crew, task order, process, memory, and runtime inputs. +2. `agents/researcher.jsonc` and `agents/analyst.jsonc` define the agents. +3. The researcher runs first. +4. The analyst runs second with `context: ["research_task"]`. +5. The final task writes `output/report.md`. + +## Extending Your Crew + +You can add: + +- More agents by creating new `agents/.jsonc` files and listing them in `crew.jsonc` +- More tasks by appending objects to the `tasks` array +- Built-in tools by adding tool class names such as `"FileReadTool"` or `"SerperDevTool"` +- Custom tools with `"custom:"`, which loads `tools/.py` +- Hierarchical execution with `"process": "hierarchical"` and a `manager_llm` or `manager_agent` + + +Only run JSON crew projects from sources you trust. `custom:` tools and `{"python": "module.attribute"}` references execute local Python code when the crew loads. + + + +You now have a working JSON-first crew that researches a topic and writes a report. + diff --git a/docs/v1.15.13/en/guides/flows/conversational-flows.mdx b/docs/v1.15.13/en/guides/flows/conversational-flows.mdx new file mode 100644 index 0000000000..b8fd7f43d5 --- /dev/null +++ b/docs/v1.15.13/en/guides/flows/conversational-flows.mdx @@ -0,0 +1,540 @@ +--- +title: Conversational Flows +description: Build multi-turn chat apps with handle_turn per turn, message history, intent routing, tracing, and WebSocket bridges. +icon: comments +mode: "wide" +--- + +## Overview + +Conversational apps treat each user line as a **new flow run** with the **same session id**. CrewAI adds helpers for message history, optional intent routing, deferred tracing, UI bridges, and a local `flow.chat()` REPL for conversational flows. + +| Concept | Implementation | +|---------|----------------| +| Session id | `handle_turn(..., session_id=...)` → `kickoff(inputs={"id": ...})` → `state.id` | +| User line | `handle_turn(message)` appends to `state.messages` before the graph runs | +| Turn complete | `FlowFinished` for **this run** only; chat continues on the next `handle_turn` | +| Full-session trace | `ConversationConfig(defer_trace_finalization=True)` + `finalize_session_traces()` | + +## Turn APIs + +Use **`flow.handle_turn(message, session_id=...)`** for every user message from REST, WebSocket, tests, and custom UIs. Use **`flow.chat()`** when you want a local terminal chat loop for a conversational `Flow`. + +`Flow.kickoff()` does **not** accept `user_message=` or `session_id=` keyword arguments. For conversational flows, `handle_turn()` stores the pending message and calls `kickoff(inputs={"id": session_id})` internally after resetting per-turn execution state. + +| API | Use for | +|-----|---------| +| `handle_turn(message, session_id=...)` | Ergonomic one-turn wrapper for conversational `Flow` | +| `stream_turn(message, session_id=...)` | Stream one conversational turn as ordered runtime frames | +| `chat()` | Local terminal REPL for conversational `Flow` | +| `kickoff(inputs={...})` | Advanced flow execution without conversational turn handling | +| `ask()` | Blocking prompt **inside** one step (wizard, clarification) | +| `@human_feedback` | Approve/reject **a step output** — not the next chat line | +| `ChatSession.handle_turn(...)` | Transport layer over `handle_turn` (SSE / WebSocket) | + +## Quick start + +```python +from uuid import uuid4 + +from crewai import Flow +from crewai.flow import listen +from crewai.experimental.conversational import ( + ConversationConfig, + ConversationState, +) + + +@ConversationConfig(defer_trace_finalization=True) +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context): + message = (self.state.current_user_message or "").lower() + if "order" in message: + return "order" + if "bye" in message or "goodbye" in message: + return "goodbye" + return "help" + + @listen("order") + def handle_order(self): + reply = "Your order is on the way." + self.append_assistant_message(reply) + return reply + + @listen("help") + def handle_help(self): + reply = "How can I help?" + self.append_assistant_message(reply) + return reply + + @listen("goodbye") + def handle_goodbye(self): + reply = "Goodbye!" + self.append_assistant_message(reply) + return reply + + +session_id = str(uuid4()) +flow = SupportFlow() + +try: + flow.handle_turn("Where is my order?", session_id=session_id) + flow.handle_turn("What about returns?", session_id=session_id) +finally: + flow.finalize_session_traces() # one trace link for the whole chat +``` + +## Streaming a turn + +Use `stream_turn()` when a UI or runtime needs structured events for one chat turn. It returns a stream session with ordered frames for Flow routing, LLM chunks, tool activity, and conversation messages. + +```python +stream = flow.stream_turn("Where is my order?", session_id=session_id) + +with stream: + for frame in stream.events: + if frame.channel == "llm" and frame.type == "llm_stream_chunk": + print(frame.data.get("chunk", ""), end="", flush=True) + +result = stream.result +``` + +For the full frame contract, channel list, and async API, see [Streaming Runtime Contract](/edge/en/learn/streaming-runtime-contract). + +## Turn lifecycle + +Each `handle_turn` runs this pipeline: + +1. **Turn setup** — stores the pending user message, resolves the session id, resets per-turn execution tracking, and calls `kickoff(inputs={"id": session_id})`. +2. **State restore** — if `inputs["id"]` exists and `@persist` is configured, loads the latest snapshot. +3. **`FlowStarted`** — emitted on the first deferred session turn only. +4. **Pending turn hydration** — appends the user message to `state.messages`, sets `current_user_message` / `last_user_message`, and optionally classifies when `intents` / `default_intents` + `intent_llm` are set. +5. **Graph execution** — `conversation_start` → `route_conversation` → the selected `@listen` handler. +6. **End of run** — per-turn `flow_finished` and trace finalization are **skipped** when deferral is enabled; nested `Agent.kickoff()` / crews do not close the parent batch either. + +Handlers should call **`append_assistant_message(reply)`** so the next turn’s `conversation_messages` includes assistant text. The user line is already stored by `handle_turn` — do not append it again in handlers. + +## `ConversationConfig` (class-level defaults) + +Decorate your conversational `Flow` subclass with `ConversationConfig`. + +| Field | Default | Purpose | +|-------|---------|---------| +| `system_prompt` | Framework default | System message used by the built-in `converse_turn`. | +| `llm` | `None` | Conversation LLM used by `converse_turn` and as router fallback. | +| `router` | `None` | `RouterConfig` for LLM-driven routing. | +| `intent_llm` | `None` | LLM for `intents=` / `default_intents` pre-classification. | +| `default_intents` | `None` | Outcome labels for pre-classification. | +| `defer_trace_finalization` | `True` | Keep one trace batch open across `handle_turn()` calls. | + +Override pre-classification per turn with `handle_turn(..., intents=..., intent_llm=...)`. + +## Lower-level `ChatState` helpers + +`ChatState`, `ConversationalConfig`, and `crewai.flow.conversation` helpers are still importable for advanced orchestration, tests, or custom wrappers. They do not add `user_message=` or `session_id=` keyword arguments to `Flow.kickoff()`. + +```python +from crewai.flow import ChatState + + +class MyChatState(ChatState): + # Inherited: id, messages, last_user_message, last_intent, session_ready + research_turn_count: int = 0 + custom_flag: bool = False +``` + +| Field | Role | +|-------|------| +| `id` | Session UUID (same as `inputs["id"]`) | +| `messages` | `list` of `{role, content}` for LLM history | +| `last_user_message` | Latest user line for this turn | +| `last_intent` | Route label after classification (if used) | +| `session_ready` | One-time bootstrap flag (permissions, caches, etc.) | + +`ConversationalInputs` is a `TypedDict` for conventional `kickoff(inputs={...})` keys: `id`, `user_message`, `last_intent`. + +## `Flow` conversational API + +### `handle_turn` parameters + +| Parameter | Purpose | +|-----------|---------| +| `message` | This turn’s text | +| `session_id` | Conversation UUID → `inputs["id"]` / `state.id` | +| `intents` | Outcome labels for pre-kickoff `classify_intent` | +| `intent_llm` | LLM for classification (required with `intents`) | +| `**kickoff_kwargs` | Forwarded to `kickoff()` for options like `input_files`, `from_checkpoint`, and `restore_from_state_id` | + +### `kickoff` parameters + +`Flow.kickoff()` accepts `inputs`, `input_files`, `from_checkpoint`, and `restore_from_state_id`. Pass `inputs={"id": session_id}` when you need raw flow execution, but use `handle_turn()` when the call represents a chat message. + +### Instance attributes + +| Attribute | Purpose | +|-----------|---------| +| `conversational` | Set to `True` to enable the conversational graph and `handle_turn()` | +| `defer_trace_finalization` | Instance flag; set automatically from config on `handle_turn()` | +| `suppress_flow_events` | Hides console flow panels; **tracing still records** method/flow events | +| `stream` | Enable streaming; use with `ChatSession.handle_turn(..., stream=True)` | + +### Methods and properties + +| Name | Description | +|------|-------------| +| `append_assistant_message(content)` | Append a user-visible assistant reply to `state.messages` | +| `append_message(role, content, **extra)` | Lower-level append to `state.messages` | +| `conversation_messages` | Read-only history for LLM calls | +| `classify_intent(text, outcomes, *, llm, context=None)` | Map text to one outcome (same collapse logic as `@human_feedback`) | +| `receive_user_message(text, *, outcomes=None, llm=None)` | Append user message; optionally set `last_intent` | +| `finalize_session_traces()` | Emit deferred `flow_finished` and finalize the session trace batch | +| `_should_defer_trace_finalization()` | Whether this flow defers per-turn trace finalization | +| `input_history` | Audit trail of `ask()` prompts and responses | + +### Module helpers (`crewai.flow.conversation`) + +Importable for tests or custom orchestration: + +| Function | Description | +|----------|-------------| +| `normalize_kickoff_inputs(inputs, user_message=..., session_id=...)` | Merge conversational kwargs into `inputs` | +| `get_conversation_messages(flow)` | Read messages from state or internal buffer | +| `append_message(flow, role, content, **extra)` | Same as instance method | +| `prepare_conversational_turn(flow, user_message=..., intents=..., intent_llm=..., config=...)` | Lower-level turn hydration for custom wrappers | +| `receive_user_message(flow, text, ...)` | Same as instance method | +| `set_state_field(flow, name, value)` | Set a field on dict or Pydantic state | +| `get_conversational_config(flow)` | Read class `conversational_config` | +| `input_history_to_messages(entries)` | Convert `input_history` to LLM message format | + +## Intent routing patterns + +### A. Pre-classify via `ConversationConfig` (simplest) + +Set `default_intents` and `intent_llm`. Each `handle_turn()` runs classification before routing; read `self.state.last_intent` in `route_turn()`. + +### B. Classify inside `route_turn` (richer prompts) + +Set `default_intents=None` so `handle_turn()` only appends the user message. In `route_turn()`, call `classify_intent` with a custom prompt or descriptions: + +```python +def route_turn(self, context): + intent = self.classify_intent( + self._routing_prompt(self.state.current_user_message), + ("GREETING", "ORDER", "RESEARCH", "GOODBYE"), + llm="gpt-4o-mini", + ) + self.state.last_intent = intent + return intent +``` + +Use **`@listen("RESEARCH")`** (or similar) for steps that run `Agent.kickoff()` with tools — not bare `LLM.call()` — when you need web research or multi-step tool use. + +## When the flow finishes but the user keeps chatting + +`FlowFinished` means **this graph run** completed. The conversation continues with another `handle_turn()` and the same `session_id`. `@persist` restores `messages`, flags, and context. + +**Persist pattern:** prefer `@persist` on a **single terminal step** (for example `finalize`) rather than on the whole `Flow` class. Class-level persist saves after every method; `load_state` uses the latest row, which may be a mid-run snapshot (for example right after `bootstrap`) and miss handler updates from the same turn. + +Do **not** use `@human_feedback` for follow-up chat lines unless a human must approve a specific step output before it is shown. + +## Conversational `Flow` (experimental) + + + **This is an experimental feature.** The conversational `Flow` surface + (`conversational = True`, `handle_turn`, `ConversationConfig`, + `RouterConfig`, `ConversationState`, the built-in graph + helpers) lives + under `crewai.experimental` and may change shape before it graduates. + Pin your CrewAI version if you depend on specific behavior, and watch the + changelog for breaking updates. Open issues / feedback welcome. + + +Opt into the conversational chat graph by setting `conversational = True` on a `Flow` subclass. The base `Flow` then ships a built-in `@start` / `@router` / `converse_turn` / `end_conversation` graph, manages `state.messages`, can drive a router LLM, and keeps the trace batch open across turns. You write the **custom routes**; the framework owns the rest. + +Use this when you want a multi-turn chat with a router and per-route handlers without wiring the lifecycle yourself. Use `Flow[ChatState]` (the lower-level pattern above) when you need full control. + +### Quick example + +```python +from crewai import Flow +from crewai.flow import listen +from crewai.experimental.conversational import ( + ConversationConfig, + ConversationState, +) + + +@ConversationConfig(defer_trace_finalization=True) +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context: dict) -> str | None: + message = (self.state.current_user_message or "").lower() + if "search" in message or "news" in message: + return "INTERNET_SEARCH" + if "docs" in message or "crewai" in message: + return "CREWAI_DOCS" + return "converse" + + @listen("INTERNET_SEARCH") + def handle_internet_search(self) -> str: + """Fresh web research, current news, real-time lookups.""" + reply = "I would run the web research route here." + self.append_assistant_message(reply) + return reply + + @listen("CREWAI_DOCS") + def handle_crewai_docs(self) -> str: + """Look up the CrewAI documentation for framework/API questions.""" + reply = "I would look up the CrewAI docs here." + self.append_assistant_message(reply) + return reply + + +flow = SupportFlow() +try: + flow.handle_turn("What can you do?") # routes to converse + flow.handle_turn("Search the web for AI news.") # routes to INTERNET_SEARCH + flow.handle_turn("Check the CrewAI docs.") # routes to CREWAI_DOCS +finally: + flow.finalize_session_traces() +``` + +For a local terminal chat, use `chat()`: + +```python +def kickoff() -> None: + SupportFlow().chat() +``` + +`chat()` wraps `handle_turn()` in a REPL, exits on `exit` / `quit`, skips blank lines by default, and calls `finalize_session_traces()` when the session ends. + +### `ConversationConfig` + +Class decorator that attaches per-class chat defaults. + +| Field | Default | Purpose | +|-------|---------|---------| +| `system_prompt` | `slices.conversational_system_prompt` from i18n | System message used by the built-in `converse_turn`. Pass `""` to opt out entirely. | +| `llm` | `None` | Conversation LLM (used by `converse_turn` and as router fallback). | +| `router` | `None` | `RouterConfig` for LLM-driven routing. Without it, the flow always falls through to `converse`. | +| `answer_from_history_prompt` | Framework default | System message for the optional `answer_from_history` route. | +| `answer_from_history_llm` | `None` | Enables the `answer_from_history` short-circuit when set. | +| `intent_llm` | `None` | LLM for legacy `intents=`/`default_intents` pre-classification. | +| `default_intents` | `None` | Outcome labels for legacy pre-classification. | +| `visible_agent_outputs` | `None` | `"all"`, or a list of agent names whose `append_agent_result()` calls should be promoted to public assistant messages. | +| `defer_trace_finalization` | `True` | Keep one trace batch open across `handle_turn()` calls. | + +### `RouterConfig` and the auto-built route catalog + +```python +from typing import Literal + +from pydantic import BaseModel + +from crewai import LLM +from crewai.experimental.conversational import RouterConfig + + +class MyRoute(BaseModel): + intent: Literal["INTERNET_SEARCH", "CREWAI_DOCS", "converse"] + + +ROUTER_LLM = LLM(model="gpt-4o-mini") + +router_config = RouterConfig( + prompt="Optional domain framing (policy, voice, persona).", + response_format=MyRoute, # optional; auto-generated otherwise + llm=ROUTER_LLM, # falls back to ConversationConfig.llm + routes=["INTERNET_SEARCH", "CREWAI_DOCS"], # optional; inferred from listeners + route_descriptions={ + "INTERNET_SEARCH": "Override the docstring for this one route.", + }, + default_intent="converse", # used when LLM call fails or no LLM available + fallback_intent="converse", # used when LLM returns an invalid route + intent_field="intent", +) +``` + +The router prompt that gets sent to the LLM is built automatically. For each route the framework picks a description with this precedence: + +1. `RouterConfig.route_descriptions[label]` — explicit override. +2. `Flow.builtin_route_descriptions[label]` — framework-canned text for `converse`, `end`, `answer_from_history` (phrased for the router LLM). +3. First non-empty line of the `@listen(label)` handler's docstring. +4. Empty (the route is listed without a description). + +So in practice, **adding a new route is `@listen("X")` + a one-line docstring**: + +```python +from crewai.flow import listen + + +@listen("INTERNET_SEARCH") +def handle_internet_search(self) -> str: + """Fresh web research, current news, real-time lookups.""" + ... +``` + +### Naming handlers + +The string in `@listen("…")` is a **router route label** (an event name), not the Python method name. Route labels and method completion events share one trigger namespace, so naming a handler the same as its route causes the handler to re-trigger itself in a loop. + +Use a different method name — the docs examples use a `handle_*` prefix: + +```python +@listen("create_video") +def handle_create_video(self) -> str: + """User wants a new video.""" + ... +``` + +Do **not** mirror the route label on the method: + +```python +@listen("create_video") +def create_video(self) -> str: # rejected at flow instantiation + ... +``` + +…and the router LLM sees: + +``` +Routes: +- CREWAI_DOCS: Look up the CrewAI documentation for framework/API questions. +- INTERNET_SEARCH: Fresh web research, current news, real-time lookups. +- converse: Ordinary chat, follow-ups, summaries, clarifications… +- end: User signals the conversation is finished (goodbye, exit, done). +``` + +`RouterConfig.prompt` is for **domain framing** (assistant persona, business rules, voice). The route catalog is auto-built — don't list routes in `prompt`; they'll drift the moment you add a handler. + +### Built-in routes + +| Route | Handler | Purpose | +|-------|---------|---------| +| `converse` | `converse_turn` | Default chat handler. Calls `ConversationConfig.llm` with the system prompt + canonical message history. | +| `end` | `end_conversation` | Sets `state.ended = True` and emits a terminator reply. | +| `answer_from_history` | `answer_from_history_turn` | Optional. Routes here when `ConversationConfig.answer_from_history_llm` is set and the message can be answered from existing history. | + +You can override any of these by defining a same-named handler in your subclass. + +### `handle_turn()` semantics + +`flow.handle_turn(message)` runs one turn: + +1. Resets per-execution tracking (`_completed_methods`, `_method_outputs`) so the graph re-runs — without this, repeated `kickoff` calls on the same flow instance would short-circuit on turn 2+ because `Flow.kickoff_async` treats `inputs={"id": ...}` as a checkpoint restore. +2. Appends the user message to `state.messages`, sets `current_user_message` / `last_user_message`. `last_intent` is **preserved from the prior turn** so the router LLM can use it as a signal. +3. Runs `conversation_start` → `route_conversation` → the chosen `@listen` handler. +4. The router stores its decision in `state.last_intent` (visible to the next turn's router context). +5. If your handler returned a string and didn't already call `append_assistant_message`, `handle_turn` appends it for you. + +Call `handle_turn()` for chat messages. Calling `kickoff(inputs={"id": ...})` directly runs the flow graph without applying the conversational turn wrapper. + +### `chat()` for local REPLs + +`flow.chat()` is the batteries-included terminal wrapper around `handle_turn()`: + +```python +flow = SupportFlow() +flow.chat() +``` + +It handles the common local loop: + +1. Prompts for a user message. +2. Stops on `exit` / `quit`, `EOFError`, or `KeyboardInterrupt`. +3. Calls `handle_turn(message, session_id=...)`. +4. Prints the assistant result. +5. Finalizes deferred session traces in a `finally` block. + +Customize the terminal behavior with injectable I/O: + +```python +flow.chat( + session_id="demo-session", + prompt="You: ", + assistant_prefix="Assistant: ", + exit_commands=("exit", "quit", "bye"), +) +``` + +For web apps, background workers, tests, and custom transports, keep using `handle_turn()` directly. + +### Custom router behavior + +To run side effects (event bus setup, telemetry) on every routing decision, override `route_turn`: + +```python +from typing import Any + +from crewai import Flow +from crewai.experimental.conversational import ConversationState + + +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context: dict[str, Any]) -> str | None: + self.event_bus = MyBus(self) + return super().route_turn(context) +``` + +To bypass the LLM router entirely and pick a route programmatically, return a string from `route_turn`; returning `None` falls back to `_route_with_config(...)`. + +### `append_assistant_message` and `append_agent_result` + +Inside a `@listen(label)` handler, choose: + +- `self.append_assistant_message(text)` — adds a user-visible assistant turn to `state.messages`. The next turn's `converse_turn` sees it. +- `self.append_agent_result(agent_name, result, visibility="private")` — records a structured event in `state.events` and a thread in `state.agent_threads[agent_name]`. Public visibility also calls `append_assistant_message` for you. Use private results for scratch work that shouldn't pollute the canonical history. + +`ConversationConfig.visible_agent_outputs` can promote specific agents' private results to public globally (`"all"`, or a list of agent names). + +## Tracing across turns + +With `defer_trace_finalization=True` (default in `ConversationConfig`): + +- **One trace batch** for the whole chat session. +- **`flow_started`** on the first turn only; **`flow_finished`** once in `finalize_session_traces()`. +- **Per-turn** `kickoff` does not print “Trace batch finalized”. +- **Nested work** (`Agent.kickoff()`, crews, Exa tools) appends to the **parent** batch; inner `AgentExecutor` flows do not close the session batch early. + +```python +flow.chat(session_id=session_id) +``` + +`flow.chat()` calls `finalize_session_traces()` for you. When you own the loop +with `handle_turn()`, call `finalize_session_traces()` when +the session ends. + +`suppress_flow_events=True` only hides Rich console panels; trace and method events still emit for observability. + +### Conversational `Flow` trace lifecycle + +The experimental [conversational `Flow`](#conversational-flow-experimental) uses the same tracing lifecycle: `defer_trace_finalization` defaults to `True`, so each `handle_turn()` keeps the session trace open. Always finalize at the end of the session — wrap your REPL/loop in `try/finally` and call `flow.finalize_session_traces()` on exit. Without it, the trace batch stays open and the final conversation may never export. + +## Streaming + +Set `stream = True` on the `Flow` class. `kickoff(...)` will then emit `assistant_delta` (and related) events through the standard event bus. + +## Imports + +```python +from crewai.flow import ( + ChatState, + ConversationalConfig, + ConversationalInputs, + Flow, + listen, + persist, + router, + start, +) +``` + +## See also + +- [Mastering Flow State Management](/en/guides/flows/mastering-flow-state) — persistence, Pydantic state, `@persist` +- [Build Your First Flow](/en/guides/flows/first-flow) — flow basics +- Demo: `lib/crewai/runner_conversational_flow_simple.py` — minimal REPL with `RESEARCH` + Exa agent diff --git a/docs/v1.15.13/en/guides/flows/first-flow.mdx b/docs/v1.15.13/en/guides/flows/first-flow.mdx new file mode 100644 index 0000000000..d26a1eb2d5 --- /dev/null +++ b/docs/v1.15.13/en/guides/flows/first-flow.mdx @@ -0,0 +1,552 @@ +--- +title: Build Your First Flow +description: Learn how to create structured, event-driven workflows with precise control over execution. +icon: diagram-project +mode: "wide" +--- + +## Taking Control of AI Workflows with Flows + +CrewAI Flows represent the next level in AI orchestration - combining the collaborative power of AI agent crews with the precision and flexibility of procedural programming. While crews excel at agent collaboration, flows give you fine-grained control over exactly how and when different components of your AI system interact. + +In this guide, we'll walk through creating a powerful CrewAI Flow that generates a comprehensive learning guide on any topic. This tutorial will demonstrate how Flows provide structured, event-driven control over your AI workflows by combining regular code, direct LLM calls, and crew-based processing. + +### What Makes Flows Powerful + +Flows enable you to: + +1. **Combine different AI interaction patterns** - Use crews for complex collaborative tasks, direct LLM calls for simpler operations, and regular code for procedural logic +2. **Build event-driven systems** - Define how components respond to specific events and data changes +3. **Maintain state across components** - Share and transform data between different parts of your application +4. **Integrate with external systems** - Seamlessly connect your AI workflow with databases, APIs, and user interfaces +5. **Create complex execution paths** - Design conditional branches, parallel processing, and dynamic workflows + +### What You'll Build and Learn + +By the end of this guide, you'll have: + +1. **Created a sophisticated content generation system** that combines user input, AI planning, and multi-agent content creation +2. **Orchestrated the flow of information** between different components of your system +3. **Implemented event-driven architecture** where each step responds to the completion of previous steps +4. **Built a foundation for more complex AI applications** that you can expand and customize + +This guide creator flow demonstrates fundamental patterns that can be applied to create much more advanced applications, such as: + +- Interactive AI assistants that combine multiple specialized subsystems +- Complex data processing pipelines with AI-enhanced transformations +- Autonomous agents that integrate with external services and APIs +- Multi-stage decision-making systems with human-in-the-loop processes + +Let's dive in and build your first flow! + +## Prerequisites + +Before starting, make sure you have: + +1. Installed CrewAI following the [installation guide](/en/installation) +2. Set up your LLM API key in your environment, following the [LLM setup + guide](/en/concepts/llms#setting-up-your-llm) +3. Basic understanding of Python + +## Step 1: Create a New CrewAI Flow Project + +First, let's create a new CrewAI Flow project using the CLI. This command sets up a scaffolded project with all the necessary directories and template files for your flow. + +```bash +crewai create flow guide_creator_flow +cd guide_creator_flow +``` + +This will generate a project with the basic structure needed for your flow. + + + CrewAI Framework Overview + + +## Step 2: Understanding the Project Structure + +The generated project has the following structure. The starter embedded crew uses the classic Python/YAML layout, and in Step 4 we will replace the content crew with a JSONC crew. + +``` +guide_creator_flow/ +├── .gitignore +├── pyproject.toml +├── README.md +├── .env +└── src/ + └── guide_creator_flow/ + ├── __init__.py + ├── main.py + ├── crews/ + │ └── poem_crew/ + │ ├── config/ + │ │ ├── agents.yaml + │ │ └── tasks.yaml + │ └── poem_crew.py + └── tools/ + └── custom_tool.py +``` + +This structure provides a clear separation between different components of your flow: +- The main flow logic in the `src/guide_creator_flow/main.py` file +- Specialized crews in the `src/guide_creator_flow/crews` directory +- Custom tools in the `src/guide_creator_flow/tools` directory + +We'll modify this structure to create our guide creator flow, which will orchestrate the process of generating comprehensive learning guides. + +## Step 3: Add a Content Writer Crew + +Our flow will need a specialized crew to handle the content creation process. Let's use the CrewAI CLI to add a content writer crew: + +```bash +crewai flow add-crew content-crew +``` + +This command automatically creates the necessary directories and template files for your crew. The content writer crew will be responsible for writing and reviewing sections of our guide, working within the overall flow orchestrated by our main application. + +## Step 4: Configure the Content Writer Crew + +Now, let's configure the content writer crew with JSONC. We'll set up two specialized agents - a writer and a reviewer - that collaborate to create high-quality content for our guide. + +1. Create `src/guide_creator_flow/crews/content_crew/agents/content_writer.jsonc`: + +```jsonc +{ + "role": "Educational Content Writer", + "goal": "Create engaging, informative content that thoroughly explains the assigned topic and provides valuable insights to the reader.", + "backstory": "You are a talented educational writer who explains complex concepts in accessible language and organizes information clearly.", + "llm": "provider/model-id", + "settings": { + "verbose": true + } +} +``` + +2. Create `src/guide_creator_flow/crews/content_crew/agents/content_reviewer.jsonc`: + +```jsonc +{ + "role": "Educational Content Reviewer and Editor", + "goal": "Ensure content is accurate, comprehensive, well-structured, and consistent with previously written sections.", + "backstory": "You are a meticulous editor with an eye for detail, clarity, and coherence.", + "llm": "provider/model-id", + "settings": { + "verbose": true + } +} +``` + +Replace `provider/model-id` with the model you use, for example `openai/gpt-4o`, `gemini/gemini-2.0-flash-001`, or `anthropic/claude-sonnet-4-6`. + +3. Create `src/guide_creator_flow/crews/content_crew/crew.jsonc`: + +```jsonc +{ + "name": "Content Crew", + "agents": ["content_writer", "content_reviewer"], + "tasks": [ + { + "name": "write_section_task", + "description": "Write a comprehensive section on the topic: \"{section_title}\".\n\nSection description: {section_description}\nTarget audience: {audience_level} level learners\n\nYour content should begin with a brief introduction, explain key concepts clearly with examples, include practical applications where appropriate, end with a summary, and be approximately 500-800 words.\n\nPreviously written sections:\n{previous_sections}", + "expected_output": "A well-structured, comprehensive section in Markdown format that thoroughly explains the topic and is appropriate for the target audience.", + "agent": "content_writer", + "markdown": true + }, + { + "name": "review_section_task", + "description": "Review and improve this section on \"{section_title}\":\n\n{draft_content}\n\nTarget audience: {audience_level} level learners\nPreviously written sections:\n{previous_sections}\n\nFix errors, improve clarity, verify consistency, enhance structure, and add missing key information.", + "expected_output": "An improved, polished version of the section that maintains the original structure but enhances clarity, accuracy, and consistency.", + "agent": "content_reviewer", + "context": ["write_section_task"], + "markdown": true + } + ], + "process": "sequential", + "verbose": true +} +``` + +The `context` field lets the reviewer use the writer's output. + +4. Replace `src/guide_creator_flow/crews/content_crew/content_crew.py` with a small loader: + +```python +from pathlib import Path + +from crewai.project import load_crew + + +def kickoff_content_crew(inputs: dict): + crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc")) + return crew.kickoff(inputs={**default_inputs, **inputs}) +``` + +This loader turns `crew.jsonc` into a `Crew` at runtime. While this crew can function independently, in our flow it will be orchestrated as part of a larger system. + +## Step 5: Create the Flow + +Now comes the exciting part - creating the flow that will orchestrate the entire guide creation process. This is where we'll combine regular Python code, direct LLM calls, and our content creation crew into a cohesive system. + +Our flow will: +1. Get user input for a topic and audience level +2. Make a direct LLM call to create a structured guide outline +3. Process each section sequentially using the content writer crew +4. Combine everything into a final comprehensive document + +Let's create our flow in the `main.py` file: + +```python +#!/usr/bin/env python +import json +import os +from typing import List, Dict +from pydantic import BaseModel, Field +from crewai import LLM +from crewai.flow.flow import Flow, listen, start +from guide_creator_flow.crews.content_crew.content_crew import kickoff_content_crew + +# Define our models for structured data +class Section(BaseModel): + title: str = Field(description="Title of the section") + description: str = Field(description="Brief description of what the section should cover") + +class GuideOutline(BaseModel): + title: str = Field(description="Title of the guide") + introduction: str = Field(description="Introduction to the topic") + target_audience: str = Field(description="Description of the target audience") + sections: List[Section] = Field(description="List of sections in the guide") + conclusion: str = Field(description="Conclusion or summary of the guide") + +# Define our flow state +class GuideCreatorState(BaseModel): + topic: str = "" + audience_level: str = "" + guide_outline: GuideOutline = None + sections_content: Dict[str, str] = {} + +class GuideCreatorFlow(Flow[GuideCreatorState]): + """Flow for creating a comprehensive guide on any topic""" + + @start() + def get_user_input(self): + """Get input from the user about the guide topic and audience""" + print("\n=== Create Your Comprehensive Guide ===\n") + + # Get user input + self.state.topic = input("What topic would you like to create a guide for? ") + + # Get audience level with validation + while True: + audience = input("Who is your target audience? (beginner/intermediate/advanced) ").lower() + if audience in ["beginner", "intermediate", "advanced"]: + self.state.audience_level = audience + break + print("Please enter 'beginner', 'intermediate', or 'advanced'") + + print(f"\nCreating a guide on {self.state.topic} for {self.state.audience_level} audience...\n") + return self.state + + @listen(get_user_input) + def create_guide_outline(self, state): + """Create a structured outline for the guide using a direct LLM call""" + print("Creating guide outline...") + + # Initialize the LLM + llm = LLM(model="openai/gpt-4o-mini", response_format=GuideOutline) + + # Create the messages for the outline + messages = [ + {"role": "system", "content": "You are a helpful assistant designed to output JSON."}, + {"role": "user", "content": f""" + Create a detailed outline for a comprehensive guide on "{state.topic}" for {state.audience_level} level learners. + + The outline should include: + 1. A compelling title for the guide + 2. An introduction to the topic + 3. 4-6 main sections that cover the most important aspects of the topic + 4. A conclusion or summary + + For each section, provide a clear title and a brief description of what it should cover. + """} + ] + + # Make the LLM call with JSON response format + response = llm.call(messages=messages) + + # Parse the JSON response + outline_dict = json.loads(response) + self.state.guide_outline = GuideOutline(**outline_dict) + + # Ensure output directory exists before saving + os.makedirs("output", exist_ok=True) + + # Save the outline to a file + with open("output/guide_outline.json", "w") as f: + json.dump(outline_dict, f, indent=2) + + print(f"Guide outline created with {len(self.state.guide_outline.sections)} sections") + return self.state.guide_outline + + @listen(create_guide_outline) + def write_and_compile_guide(self, outline): + """Write all sections and compile the guide""" + print("Writing guide sections and compiling...") + completed_sections = [] + + # Process sections one by one to maintain context flow + for section in outline.sections: + print(f"Processing section: {section.title}") + + # Build context from previous sections + previous_sections_text = "" + if completed_sections: + previous_sections_text = "# Previously Written Sections\n\n" + for title in completed_sections: + previous_sections_text += f"## {title}\n\n" + previous_sections_text += self.state.sections_content.get(title, "") + "\n\n" + else: + previous_sections_text = "No previous sections written yet." + + # Run the content crew for this section + result = kickoff_content_crew(inputs={ + "section_title": section.title, + "section_description": section.description, + "audience_level": self.state.audience_level, + "previous_sections": previous_sections_text, + "draft_content": "" + }) + + # Store the content + self.state.sections_content[section.title] = result.raw + completed_sections.append(section.title) + print(f"Section completed: {section.title}") + + # Compile the final guide + guide_content = f"# {outline.title}\n\n" + guide_content += f"## Introduction\n\n{outline.introduction}\n\n" + + # Add each section in order + for section in outline.sections: + section_content = self.state.sections_content.get(section.title, "") + guide_content += f"\n\n{section_content}\n\n" + + # Add conclusion + guide_content += f"## Conclusion\n\n{outline.conclusion}\n\n" + + # Save the guide + with open("output/complete_guide.md", "w") as f: + f.write(guide_content) + + print("\nComplete guide compiled and saved to output/complete_guide.md") + return "Guide creation completed successfully" + +def kickoff(): + """Run the guide creator flow""" + GuideCreatorFlow().kickoff() + print("\n=== Flow Complete ===") + print("Your comprehensive guide is ready in the output directory.") + print("Open output/complete_guide.md to view it.") + +def plot(): + """Generate a visualization of the flow""" + flow = GuideCreatorFlow() + flow.plot("guide_creator_flow") + print("Flow visualization saved to guide_creator_flow.html") + +if __name__ == "__main__": + kickoff() +``` + +Let's analyze what's happening in this flow: + +1. We define Pydantic models for structured data, ensuring type safety and clear data representation +2. We create a state class to maintain data across different steps of the flow +3. We implement three main flow steps: + - Getting user input with the `@start()` decorator + - Creating a guide outline with a direct LLM call + - Processing sections with our content crew +4. We use the `@listen()` decorator to establish event-driven relationships between steps + +This is the power of flows - combining different types of processing (user interaction, direct LLM calls, crew-based tasks) into a coherent, event-driven system. + +## Step 6: Set Up Your Environment Variables + +Create a `.env` file in your project root with your API keys. See the [LLM setup +guide](/en/concepts/llms#setting-up-your-llm) for details on configuring a provider. + +```sh .env +OPENAI_API_KEY=your_openai_api_key +# or +GEMINI_API_KEY=your_gemini_api_key +# or +ANTHROPIC_API_KEY=your_anthropic_api_key +``` + +## Step 7: Install Dependencies + +Install the required dependencies: + +```bash +crewai install +``` + +## Step 8: Run Your Flow + +Now it's time to see your flow in action! Run it using the CrewAI CLI: + +```bash +crewai run +``` + +When you run this command, you'll see your flow spring to life: +1. It will prompt you for a topic and audience level +2. It will create a structured outline for your guide +3. It will process each section, with the content writer and reviewer collaborating on each +4. Finally, it will compile everything into a comprehensive guide + +This demonstrates the power of flows to orchestrate complex processes involving multiple components, both AI and non-AI. + +## Step 9: Visualize Your Flow + +One of the powerful features of flows is the ability to visualize their structure: + +```bash +crewai flow plot +``` + +This will create an HTML file that shows the structure of your flow, including the relationships between different steps and the data that flows between them. This visualization can be invaluable for understanding and debugging complex flows. + +## Step 10: Review the Output + +Once the flow completes, you'll find two files in the `output` directory: + +1. `guide_outline.json`: Contains the structured outline of the guide +2. `complete_guide.md`: The comprehensive guide with all sections + +Take a moment to review these files and appreciate what you've built - a system that combines user input, direct AI interactions, and collaborative agent work to produce a complex, high-quality output. + +## The Art of the Possible: Beyond Your First Flow + +What you've learned in this guide provides a foundation for creating much more sophisticated AI systems. Here are some ways you could extend this basic flow: + +### Enhancing User Interaction + +You could create more interactive flows with: +- Web interfaces for input and output +- Real-time progress updates +- Interactive feedback and refinement loops +- Multi-stage user interactions + +### Adding More Processing Steps + +You could expand your flow with additional steps for: +- Research before outline creation +- Image generation for illustrations +- Code snippet generation for technical guides +- Final quality assurance and fact-checking + +### Creating More Complex Flows + +You could implement more sophisticated flow patterns: +- Conditional branching based on user preferences or content type +- Parallel processing of independent sections +- Iterative refinement loops with feedback +- Integration with external APIs and services + +### Applying to Different Domains + +The same patterns can be applied to create flows for: +- **Interactive storytelling**: Create personalized stories based on user input +- **Business intelligence**: Process data, generate insights, and create reports +- **Product development**: Facilitate ideation, design, and planning +- **Educational systems**: Create personalized learning experiences + +## Key Features Demonstrated + +This guide creator flow demonstrates several powerful features of CrewAI: + +1. **User interaction**: The flow collects input directly from the user +2. **Direct LLM calls**: Uses the LLM class for efficient, single-purpose AI interactions +3. **Structured data with Pydantic**: Uses Pydantic models to ensure type safety +4. **Sequential processing with context**: Writes sections in order, providing previous sections for context +5. **Multi-agent crews**: Leverages specialized agents (writer and reviewer) for content creation +6. **State management**: Maintains state across different steps of the process +7. **Event-driven architecture**: Uses the `@listen` decorator to respond to events + +## Understanding the Flow Structure + +Let's break down the key components of flows to help you understand how to build your own: + +### 1. Direct LLM Calls + +Flows allow you to make direct calls to language models when you need simple, structured responses: + +```python +llm = LLM( + model="model-id-here", # gpt-4o, gemini-2.0-flash, anthropic/claude... + response_format=GuideOutline +) +response = llm.call(messages=messages) +``` + +This is more efficient than using a crew when you need a specific, structured output. + +### 2. Event-Driven Architecture + +Flows use decorators to establish relationships between components: + +```python +@start() +def get_user_input(self): + # First step in the flow + # ... + +@listen(get_user_input) +def create_guide_outline(self, state): + # This runs when get_user_input completes + # ... +``` + +This creates a clear, declarative structure for your application. + +### 3. State Management + +Flows maintain state across steps, making it easy to share data: + +```python +class GuideCreatorState(BaseModel): + topic: str = "" + audience_level: str = "" + guide_outline: GuideOutline = None + sections_content: Dict[str, str] = {} +``` + +This provides a type-safe way to track and transform data throughout your flow. + +### 4. Crew Integration + +Flows can seamlessly integrate with crews for complex collaborative tasks: + +```python +result = kickoff_content_crew(inputs={ + "section_title": section.title, + # ... +}) +``` + +This allows you to use the right tool for each part of your application - direct LLM calls for simple tasks and crews for complex collaboration. + +## Next Steps + +Now that you've built your first flow, you can: + +1. Experiment with more complex flow structures and patterns +2. Try using `@router()` to create conditional branches in your flows +3. Explore the `and_` and `or_` functions for more complex parallel execution +4. Connect your flow to external APIs, databases, or user interfaces +5. Combine multiple specialized crews in a single flow +6. Build multi-turn chat apps with [Conversational Flows](/en/guides/flows/conversational-flows) (`kickoff` per message, `ChatSession`, deferred tracing) + + +Congratulations! You've successfully built your first CrewAI Flow that combines regular code, direct LLM calls, and crew-based processing to create a comprehensive guide. These foundational skills enable you to create increasingly sophisticated AI applications that can tackle complex, multi-stage problems through a combination of procedural control and collaborative intelligence. + diff --git a/docs/v1.15.13/en/guides/flows/inputs-id-deprecation.mdx b/docs/v1.15.13/en/guides/flows/inputs-id-deprecation.mdx new file mode 100644 index 0000000000..2798c21a50 --- /dev/null +++ b/docs/v1.15.13/en/guides/flows/inputs-id-deprecation.mdx @@ -0,0 +1,143 @@ +--- +title: "Migrating from inputs.id to restore_from_state_id" +description: "Move @persist flows off the deprecated inputs.id hydration onto the supported restore_from_state_id field" +icon: "arrow-right-arrow-left" +--- + + + Passing `id` inside `inputs` to hydrate a `@persist` flow is **deprecated** and + scheduled for removal in a future release. The replacement, `restore_from_state_id`, + is available in CrewAI **v1.14.5 and later** — the steps below apply once you + upgrade. + + +## Overview + +The documented way to hydrate a `@persist` flow from a previous execution is to pass +that execution's UUID as `inputs.id`. CrewAI now exposes a dedicated field, +`restore_from_state_id`, that performs the same hydration without overloading the +`inputs` payload — and without coupling the hydration key to the new execution's +identity. + +## Migration + +If you currently kickoff a `@persist` flow with `inputs={"id": ...}`: + +```python +# Deprecated +flow = CounterFlow() +flow.kickoff(inputs={"id": "abcd1234-5678-90ef-ghij-klmnopqrstuv"}) +``` + +Switch to `restore_from_state_id`: + +```python +# Supported +flow = CounterFlow() +flow.kickoff(restore_from_state_id="abcd1234-5678-90ef-ghij-klmnopqrstuv") +``` + +The two modes have different lineage semantics: + +- `inputs={"id": }` (deprecated) — **resume**: writes land under the supplied + id, extending the same `flow_uuid` history. +- `restore_from_state_id=` — **fork**: hydrates state from the snapshot, then + writes under a fresh `state.id`. The source flow's history is preserved. + +For most production scenarios — re-running a flow seeded from a previous state — fork +is what you want. See [Mastering Flow State](/en/guides/flows/mastering-flow-state) +for the full mental model. + +If you kickoff your flow over the CrewAI AMP REST API, see [AMP](#amp) below for the +equivalent payload migration. + +## Why we are deprecating `inputs.id` for `@persist` + +`inputs.id` is currently the documented way to resume a `@persist` flow from a +previous execution. The problem is that the same UUID does two jobs at once: + +1. **It selects which snapshot `@persist` hydrates from** — load the state saved + under that UUID. +2. **It becomes the new execution's Flow Execution ID** (`state.id` in the SDK; + surfaced as `flow_id` in some contexts) — every `@persist` write from this + kickoff also lands under that same UUID. + +This dual role is the root cause of the issues this guide describes. Because the +supplied UUID is also the new execution's id, two kickoffs that pass the same +`inputs.id` are not two distinct executions — they share an id, share a persistence +record, and (on AMP) share a row in the executions list. There is no way to say +"hydrate from this snapshot, but record this run separately" without splitting the +two responsibilities. + +`restore_from_state_id` is that split. It tells `@persist` which snapshot to hydrate +from, while leaving the new execution free to receive a fresh `state.id`. The +hydration source and the recorded run are no longer the same UUID — which is what +most production scenarios actually want. + +## Removal timeline + +`inputs.id` for `@persist` hydration is scheduled for removal in a future release of +CrewAI. There is no immediate hard cut-off — existing flows continue to work — but +once you upgrade to v1.14.5 or later, new code should use `restore_from_state_id`, and +existing flows should migrate at the next convenient opportunity. + +## AMP + +If you deploy your flow to CrewAI AMP, the migration extends to the kickoff payload +sent to your deployed crew, and the visible symptoms of reusing `inputs.id` show up +on the deployment dashboard. The two subsections below cover both. + +### Migrating the kickoff payload + +If you currently kickoff a deployed flow by embedding `id` in `inputs`: + +```bash +# Deprecated +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + -d '{"inputs": {"id": "abcd1234-5678-90ef-ghij-klmnopqrstuv", "topic": "AI Agent Frameworks"}}' \ + https://your-crew-url.crewai.com/kickoff +``` + +Move the UUID to the top-level `restoreFromStateId` field: + +```bash +# Supported +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + -d '{ + "inputs": {"topic": "AI Agent Frameworks"}, + "restoreFromStateId": "abcd1234-5678-90ef-ghij-klmnopqrstuv" + }' \ + https://your-crew-url.crewai.com/kickoff +``` + +`restoreFromStateId` sits next to `inputs` in the kickoff payload, not inside it. The +`inputs` object now only carries values your flow actually consumes. + +### What happens when `inputs.id` is reused + +When AMP receives a kickoff for a flow whose `inputs.id` matches an existing +execution, it resolves to the existing record rather than creating a new one. From +the deployment dashboard you'll see: + +- **Execution status** — the new run's status overwrites the previous run's. A + finished execution can flip back to `running`, or a `completed` run can flip to + `error` if the new kickoff fails — either way the dashboard no longer reflects + the original run. +- **Traces** — OTel traces stack across kickoffs because they share the same + execution id; the previous run's traces are either replaced by, or mixed with, + the new run's. A step-by-step replay no longer corresponds to a single execution. +- **Executions list** — kickoffs that should appear as separate rows collapse into + a single entry, hiding history. + +Migrating to `restoreFromStateId` keeps every kickoff as its own execution — with +its own status, traces, and row in the list — while still hydrating state from a +previous run. + + + Contact our support team if you're unsure which mode your flow needs or hit issues + during the migration. + diff --git a/docs/v1.15.13/en/guides/flows/mastering-flow-state.mdx b/docs/v1.15.13/en/guides/flows/mastering-flow-state.mdx new file mode 100644 index 0000000000..648a82dbd9 --- /dev/null +++ b/docs/v1.15.13/en/guides/flows/mastering-flow-state.mdx @@ -0,0 +1,841 @@ +--- +title: Mastering Flow State Management +description: A comprehensive guide to managing, persisting, and leveraging state in CrewAI Flows for building robust AI applications. +icon: diagram-project +mode: "wide" +--- + +## Understanding the Power of State in Flows + +State management is the backbone of any sophisticated AI workflow. In CrewAI Flows, the state system allows you to maintain context, share data between steps, and build complex application logic. Mastering state management is essential for creating reliable, maintainable, and powerful AI applications. + +This guide will walk you through everything you need to know about managing state in CrewAI Flows, from basic concepts to advanced techniques, with practical code examples along the way. + +### Why State Management Matters + +Effective state management enables you to: + +1. **Maintain context across execution steps** - Pass information seamlessly between different stages of your workflow +2. **Build complex conditional logic** - Make decisions based on accumulated data +3. **Create persistent applications** - Save and restore workflow progress +4. **Handle errors gracefully** - Implement recovery patterns for more robust applications +5. **Scale your applications** - Support complex workflows with proper data organization +6. **Enable conversational applications** - Store and access conversation history for context-aware AI interactions + +For multi-turn chat (`kickoff` per user line, `ChatState`, intent routing, deferred tracing, and `ChatSession`), see [Conversational Flows](/en/guides/flows/conversational-flows). + +Let's explore how to leverage these capabilities effectively. + +## State Management Fundamentals + +### The Flow State Lifecycle + +In CrewAI Flows, the state follows a predictable lifecycle: + +1. **Initialization** - When a flow is created, its state is initialized (either as an empty dictionary or a Pydantic model instance) +2. **Modification** - Flow methods access and modify the state as they execute +3. **Transmission** - State is passed automatically between flow methods +4. **Persistence** (optional) - State can be saved to storage and later retrieved +5. **Completion** - The final state reflects the cumulative changes from all executed methods + +Understanding this lifecycle is crucial for designing effective flows. + +### Two Approaches to State Management + +CrewAI offers two ways to manage state in your flows: + +1. **Unstructured State** - Using dictionary-like objects for flexibility +2. **Structured State** - Using Pydantic models for type safety and validation + +Let's examine each approach in detail. + +## Unstructured State Management + +Unstructured state uses a dictionary-like approach, offering flexibility and simplicity for straightforward applications. + +### How It Works + +With unstructured state: +- You access state via `self.state` which behaves like a dictionary +- You can freely add, modify, or remove keys at any point +- All state is automatically available to all flow methods + +### Basic Example + +Here's a simple example of unstructured state management: + +```python +from crewai.flow.flow import Flow, listen, start + +class UnstructuredStateFlow(Flow): + @start() + def initialize_data(self): + print("Initializing flow data") + # Add key-value pairs to state + self.state["user_name"] = "Alex" + self.state["preferences"] = { + "theme": "dark", + "language": "English" + } + self.state["items"] = [] + + # The flow state automatically gets a unique ID + print(f"Flow ID: {self.state['id']}") + + return "Initialized" + + @listen(initialize_data) + def process_data(self, previous_result): + print(f"Previous step returned: {previous_result}") + + # Access and modify state + user = self.state["user_name"] + print(f"Processing data for {user}") + + # Add items to a list in state + self.state["items"].append("item1") + self.state["items"].append("item2") + + # Add a new key-value pair + self.state["processed"] = True + + return "Processed" + + @listen(process_data) + def generate_summary(self, previous_result): + # Access multiple state values + user = self.state["user_name"] + theme = self.state["preferences"]["theme"] + items = self.state["items"] + processed = self.state.get("processed", False) + + summary = f"User {user} has {len(items)} items with {theme} theme. " + summary += "Data is processed." if processed else "Data is not processed." + + return summary + +# Run the flow +flow = UnstructuredStateFlow() +result = flow.kickoff() +print(f"Final result: {result}") +print(f"Final state: {flow.state}") +``` + +### When to Use Unstructured State + +Unstructured state is ideal for: +- Quick prototyping and simple flows +- Dynamically evolving state needs +- Cases where the structure may not be known in advance +- Flows with simple state requirements + +While flexible, unstructured state lacks type checking and schema validation, which can lead to errors in complex applications. + +## Structured State Management + +Structured state uses Pydantic models to define a schema for your flow's state, providing type safety, validation, and better developer experience. + +### How It Works + +With structured state: +- You define a Pydantic model that represents your state structure +- You pass this model type to your Flow class as a type parameter +- You access state via `self.state`, which behaves like a Pydantic model instance +- All fields are validated according to their defined types +- You get IDE autocompletion and type checking support + +### Basic Example + +Here's how to implement structured state management: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel, Field +from typing import List, Dict, Optional + +# Define your state model +class UserPreferences(BaseModel): + theme: str = "light" + language: str = "English" + +class AppState(BaseModel): + user_name: str = "" + preferences: UserPreferences = UserPreferences() + items: List[str] = [] + processed: bool = False + completion_percentage: float = 0.0 + +# Create a flow with typed state +class StructuredStateFlow(Flow[AppState]): + @start() + def initialize_data(self): + print("Initializing flow data") + # Set state values (type-checked) + self.state.user_name = "Taylor" + self.state.preferences.theme = "dark" + + # The ID field is automatically available + print(f"Flow ID: {self.state.id}") + + return "Initialized" + + @listen(initialize_data) + def process_data(self, previous_result): + print(f"Processing data for {self.state.user_name}") + + # Modify state (with type checking) + self.state.items.append("item1") + self.state.items.append("item2") + self.state.processed = True + self.state.completion_percentage = 50.0 + + return "Processed" + + @listen(process_data) + def generate_summary(self, previous_result): + # Access state (with autocompletion) + summary = f"User {self.state.user_name} has {len(self.state.items)} items " + summary += f"with {self.state.preferences.theme} theme. " + summary += "Data is processed." if self.state.processed else "Data is not processed." + summary += f" Completion: {self.state.completion_percentage}%" + + return summary + +# Run the flow +flow = StructuredStateFlow() +result = flow.kickoff() +print(f"Final result: {result}") +print(f"Final state: {flow.state}") +``` + +### Benefits of Structured State + +Using structured state provides several advantages: + +1. **Type Safety** - Catch type errors at development time +2. **Self-Documentation** - The state model clearly documents what data is available +3. **Validation** - Automatic validation of data types and constraints +4. **IDE Support** - Get autocomplete and inline documentation +5. **Default Values** - Easily define fallbacks for missing data + +### When to Use Structured State + +Structured state is recommended for: +- Complex flows with well-defined data schemas +- Team projects where multiple developers work on the same code +- Applications where data validation is important +- Flows that need to enforce specific data types and constraints + +## The Automatic State ID + +Both unstructured and structured states automatically receive a unique identifier (UUID) to help track and manage state instances. + +### How It Works + +- For unstructured state, the ID is accessible as `self.state["id"]` +- For structured state, the ID is accessible as `self.state.id` +- This ID is generated automatically when the flow is created +- The ID remains the same throughout the flow's lifecycle +- The ID can be used for tracking, logging, and retrieving persisted states + +This UUID is particularly valuable when implementing persistence or tracking multiple flow executions. + +## Dynamic State Updates + +Regardless of whether you're using structured or unstructured state, you can update state dynamically throughout your flow's execution. + +### Passing Data Between Steps + +Flow methods can return values that are then passed as arguments to listening methods: + +```python +from crewai.flow.flow import Flow, listen, start + +class DataPassingFlow(Flow): + @start() + def generate_data(self): + # This return value will be passed to listening methods + return "Generated data" + + @listen(generate_data) + def process_data(self, data_from_previous_step): + print(f"Received: {data_from_previous_step}") + # You can modify the data and pass it along + processed_data = f"{data_from_previous_step} - processed" + # Also update state + self.state["last_processed"] = processed_data + return processed_data + + @listen(process_data) + def finalize_data(self, processed_data): + print(f"Received processed data: {processed_data}") + # Access both the passed data and state + last_processed = self.state.get("last_processed", "") + return f"Final: {processed_data} (from state: {last_processed})" +``` + +This pattern allows you to combine direct data passing with state updates for maximum flexibility. + +## Persisting Flow State + +One of CrewAI's most powerful features is the ability to persist flow state across executions. This enables workflows that can be paused, resumed, and even recovered after failures. + +### The @persist() Decorator + +The `@persist()` decorator automates state persistence, saving your flow's state at key points in execution. + +#### Class-Level Persistence + +When applied at the class level, `@persist()` saves state after every method execution: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + value: int = 0 + +@persist() # Apply to the entire flow class +class PersistentCounterFlow(Flow[CounterState]): + @start() + def increment(self): + self.state.value += 1 + print(f"Incremented to {self.state.value}") + return self.state.value + + @listen(increment) + def double(self, value): + self.state.value = value * 2 + print(f"Doubled to {self.state.value}") + return self.state.value + +# First run +flow1 = PersistentCounterFlow() +result1 = flow1.kickoff() +print(f"First run result: {result1}") + +# Second run - pass the ID to load the persisted state +flow2 = PersistentCounterFlow() +result2 = flow2.kickoff(inputs={"id": flow1.state.id}) +print(f"Second run result: {result2}") # Will be higher due to persisted state +``` + +#### Method-Level Persistence + +For more granular control, you can apply `@persist()` to specific methods: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai.flow.persistence import persist + +class SelectivePersistFlow(Flow): + @start() + def first_step(self): + self.state["count"] = 1 + return "First step" + + @persist() # Only persist after this method + @listen(first_step) + def important_step(self, prev_result): + self.state["count"] += 1 + self.state["important_data"] = "This will be persisted" + return "Important step completed" + + @listen(important_step) + def final_step(self, prev_result): + self.state["count"] += 1 + return f"Complete with count {self.state['count']}" +``` + +#### Forking Persisted State + +`@persist` supports two distinct hydration modes on `kickoff` / `kickoff_async`. Use **resume** (`inputs["id"]`) to continue the same lineage; use **fork** (`restore_from_state_id`) to start a new lineage seeded from a snapshot: + +| | `state.id` after kickoff | `@persist` writes land under | +|---|---|---| +| `inputs["id"]` (resume) | supplied id | supplied id (extends history) | +| `restore_from_state_id` (fork) | fresh id, or `inputs["id"]` if pinned | new id (source preserved) | + +```python +from crewai.flow.flow import Flow, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + id: str = "" + counter: int = 0 + +@persist +class CounterFlow(Flow[CounterState]): + @start() + def step(self): + self.state.counter += 1 + +# Run 1: fresh state, counter 0 -> 1 +flow_1 = CounterFlow() +flow_1.kickoff() + +# Fork: hydrate from flow_1's latest snapshot, but write under a NEW state.id +flow_2 = CounterFlow() +flow_2.kickoff(restore_from_state_id=flow_1.state.id) +# flow_2 starts with counter=1 (hydrated), then step() bumps it to 2. +# flow_1's flow_uuid history is unchanged. +``` + +Behavior notes: + +- `restore_from_state_id` not found in persistence → the kickoff falls back silently to default behavior (mirrors the existing `inputs["id"]` resume not-found behavior). No exception is raised. +- Combining `restore_from_state_id` with `from_checkpoint` raises a `ValueError` — they target different state systems (`@persist` vs. Checkpointing) and cannot be combined. +- `restore_from_state_id=None` (default) is byte-identical to a kickoff without the parameter. +- Pinning `inputs["id"]` while forking means the new run shares a persistence key with another flow — usually you want only `restore_from_state_id`. + + +## Advanced State Patterns + +### Conditional starts and resumable execution + +Flows support conditional `@start()` and resumable execution for HITL/cyclic scenarios: + +```python +from crewai.flow.flow import Flow, start, listen, and_, or_ + +class ResumableFlow(Flow): + @start() # unconditional start + def init(self): + ... + + # Conditional start: run after "init" or external trigger name + @start("init") + def maybe_begin(self): + ... + + @listen(and_(init, maybe_begin)) + def proceed(self): + ... +``` + +- Conditional `@start()` accepts a method name, a router label, or a callable condition. +- During resume, listeners continue from prior checkpoints; cycle/router branches honor resumption flags. + +### State-Based Conditional Logic + +You can use state to implement complex conditional logic in your flows: + +```python +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +class PaymentState(BaseModel): + amount: float = 0.0 + is_approved: bool = False + retry_count: int = 0 + +class PaymentFlow(Flow[PaymentState]): + @start() + def process_payment(self): + # Simulate payment processing + self.state.amount = 100.0 + self.state.is_approved = self.state.amount < 1000 + return "Payment processed" + + @router(process_payment) + def check_approval(self, previous_result): + if self.state.is_approved: + return "approved" + elif self.state.retry_count < 3: + return "retry" + else: + return "rejected" + + @listen("approved") + def handle_approval(self): + return f"Payment of ${self.state.amount} approved!" + + @listen("retry") + def handle_retry(self): + self.state.retry_count += 1 + print(f"Retrying payment (attempt {self.state.retry_count})...") + # Could implement retry logic here + return "Retry initiated" + + @listen("rejected") + def handle_rejection(self): + return f"Payment of ${self.state.amount} rejected after {self.state.retry_count} retries." +``` + +### Handling Complex State Transformations + +For complex state transformations, you can create dedicated methods: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel +from typing import List, Dict + +class UserData(BaseModel): + name: str + active: bool = True + login_count: int = 0 + +class ComplexState(BaseModel): + users: Dict[str, UserData] = {} + active_user_count: int = 0 + +class TransformationFlow(Flow[ComplexState]): + @start() + def initialize(self): + # Add some users + self.add_user("alice", "Alice") + self.add_user("bob", "Bob") + self.add_user("charlie", "Charlie") + return "Initialized" + + @listen(initialize) + def process_users(self, _): + # Increment login counts + for user_id in self.state.users: + self.increment_login(user_id) + + # Deactivate one user + self.deactivate_user("bob") + + # Update active count + self.update_active_count() + + return f"Processed {len(self.state.users)} users" + + # Helper methods for state transformations + def add_user(self, user_id: str, name: str): + self.state.users[user_id] = UserData(name=name) + self.update_active_count() + + def increment_login(self, user_id: str): + if user_id in self.state.users: + self.state.users[user_id].login_count += 1 + + def deactivate_user(self, user_id: str): + if user_id in self.state.users: + self.state.users[user_id].active = False + self.update_active_count() + + def update_active_count(self): + self.state.active_user_count = sum( + 1 for user in self.state.users.values() if user.active + ) +``` + +This pattern of creating helper methods keeps your flow methods clean while enabling complex state manipulations. + +## State Management with Crews + +One of the most powerful patterns in CrewAI is combining flow state management with crew execution. + +### Passing State to Crews + +You can use flow state to parameterize crews: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + +class ResearchState(BaseModel): + topic: str = "" + depth: str = "medium" + results: str = "" + +class ResearchFlow(Flow[ResearchState]): + @start() + def get_parameters(self): + # In a real app, this might come from user input + self.state.topic = "Artificial Intelligence Ethics" + self.state.depth = "deep" + return "Parameters set" + + @listen(get_parameters) + def execute_research(self, _): + # Create agents + researcher = Agent( + role="Research Specialist", + goal=f"Research {self.state.topic} in {self.state.depth} detail", + backstory="You are an expert researcher with a talent for finding accurate information." + ) + + writer = Agent( + role="Content Writer", + goal="Transform research into clear, engaging content", + backstory="You excel at communicating complex ideas clearly and concisely." + ) + + # Create tasks + research_task = Task( + description=f"Research {self.state.topic} with {self.state.depth} analysis", + expected_output="Comprehensive research notes in markdown format", + agent=researcher + ) + + writing_task = Task( + description=f"Create a summary on {self.state.topic} based on the research", + expected_output="Well-written article in markdown format", + agent=writer, + context=[research_task] + ) + + # Create and run crew + research_crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + verbose=True + ) + + # Run crew and store result in state + result = research_crew.kickoff() + self.state.results = result.raw + + return "Research completed" + + @listen(execute_research) + def summarize_results(self, _): + # Access the stored results + result_length = len(self.state.results) + return f"Research on {self.state.topic} completed with {result_length} characters of results." +``` + +### Handling Crew Outputs in State + +When a crew completes, you can process its output and store it in your flow state: + +```python +@listen(execute_crew) +def process_crew_results(self, _): + # Parse the raw results (assuming JSON output) + import json + try: + results_dict = json.loads(self.state.raw_results) + self.state.processed_results = { + "title": results_dict.get("title", ""), + "main_points": results_dict.get("main_points", []), + "conclusion": results_dict.get("conclusion", "") + } + return "Results processed successfully" + except json.JSONDecodeError: + self.state.error = "Failed to parse crew results as JSON" + return "Error processing results" +``` + +## Best Practices for State Management + +### 1. Keep State Focused + +Design your state to contain only what's necessary: + +```python +# Too broad +class BloatedState(BaseModel): + user_data: Dict = {} + system_settings: Dict = {} + temporary_calculations: List = [] + debug_info: Dict = {} + # ...many more fields + +# Better: Focused state +class FocusedState(BaseModel): + user_id: str + preferences: Dict[str, str] + completion_status: Dict[str, bool] +``` + +### 2. Use Structured State for Complex Flows + +As your flows grow in complexity, structured state becomes increasingly valuable: + +```python +# Simple flow can use unstructured state +class SimpleGreetingFlow(Flow): + @start() + def greet(self): + self.state["name"] = "World" + return f"Hello, {self.state['name']}!" + +# Complex flow benefits from structured state +class UserRegistrationState(BaseModel): + username: str + email: str + verification_status: bool = False + registration_date: datetime = Field(default_factory=datetime.now) + last_login: Optional[datetime] = None + +class RegistrationFlow(Flow[UserRegistrationState]): + # Methods with strongly-typed state access +``` + +### 3. Document State Transitions + +For complex flows, document how state changes throughout the execution: + +```python +@start() +def initialize_order(self): + """ + Initialize order state with empty values. + + State before: {} + State after: {order_id: str, items: [], status: 'new'} + """ + self.state.order_id = str(uuid.uuid4()) + self.state.items = [] + self.state.status = "new" + return "Order initialized" +``` + +### 4. Handle State Errors Gracefully + +Implement error handling for state access: + +```python +@listen(previous_step) +def process_data(self, _): + try: + # Try to access a value that might not exist + user_preference = self.state.preferences.get("theme", "default") + except (AttributeError, KeyError): + # Handle the error gracefully + self.state.errors = self.state.get("errors", []) + self.state.errors.append("Failed to access preferences") + user_preference = "default" + + return f"Used preference: {user_preference}" +``` + +### 5. Use State for Progress Tracking + +Leverage state to track progress in long-running flows: + +```python +class ProgressTrackingFlow(Flow): + @start() + def initialize(self): + self.state["total_steps"] = 3 + self.state["current_step"] = 0 + self.state["progress"] = 0.0 + self.update_progress() + return "Initialized" + + def update_progress(self): + """Helper method to calculate and update progress""" + if self.state.get("total_steps", 0) > 0: + self.state["progress"] = (self.state.get("current_step", 0) / + self.state["total_steps"]) * 100 + print(f"Progress: {self.state['progress']:.1f}%") + + @listen(initialize) + def step_one(self, _): + # Do work... + self.state["current_step"] = 1 + self.update_progress() + return "Step 1 complete" + + # Additional steps... +``` + +### 6. Use Immutable Operations When Possible + +Especially with structured state, prefer immutable operations for clarity: + +```python +# Instead of modifying lists in place: +self.state.items.append(new_item) # Mutable operation + +# Consider creating new state: +from pydantic import BaseModel +from typing import List + +class ItemState(BaseModel): + items: List[str] = [] + +class ImmutableFlow(Flow[ItemState]): + @start() + def add_item(self): + # Create new list with the added item + self.state.items = [*self.state.items, "new item"] + return "Item added" +``` + +## Debugging Flow State + +### Logging State Changes + +When developing, add logging to track state changes: + +```python +import logging +logging.basicConfig(level=logging.INFO) + +class LoggingFlow(Flow): + def log_state(self, step_name): + logging.info(f"State after {step_name}: {self.state}") + + @start() + def initialize(self): + self.state["counter"] = 0 + self.log_state("initialize") + return "Initialized" + + @listen(initialize) + def increment(self, _): + self.state["counter"] += 1 + self.log_state("increment") + return f"Incremented to {self.state['counter']}" +``` + +### State Visualization + +You can add methods to visualize your state for debugging: + +```python +def visualize_state(self): + """Create a simple visualization of the current state""" + import json + from rich.console import Console + from rich.panel import Panel + + console = Console() + + if hasattr(self.state, "model_dump"): + # Pydantic v2 + state_dict = self.state.model_dump() + elif hasattr(self.state, "dict"): + # Pydantic v1 + state_dict = self.state.dict() + else: + # Unstructured state + state_dict = dict(self.state) + + # Remove id for cleaner output + if "id" in state_dict: + state_dict.pop("id") + + state_json = json.dumps(state_dict, indent=2, default=str) + console.print(Panel(state_json, title="Current Flow State")) +``` + +## Conclusion + +Mastering state management in CrewAI Flows gives you the power to build sophisticated, robust AI applications that maintain context, make complex decisions, and deliver consistent results. + +Whether you choose unstructured or structured state, implementing proper state management practices will help you create flows that are maintainable, extensible, and effective at solving real-world problems. + +As you develop more complex flows, remember that good state management is about finding the right balance between flexibility and structure, making your code both powerful and easy to understand. + + +You've now mastered the concepts and practices of state management in CrewAI Flows! With this knowledge, you can create robust AI workflows that effectively maintain context, share data between steps, and build sophisticated application logic. + + +## Next Steps + +- Experiment with both structured and unstructured state in your flows +- Try implementing state persistence for long-running workflows +- Explore [building your first crew](/en/guides/crews/first-crew) to see how crews and flows can work together +- Check out the [Flow reference documentation](/en/concepts/flows) for more advanced features diff --git a/docs/v1.15.13/en/guides/migration/migrating-from-langgraph.mdx b/docs/v1.15.13/en/guides/migration/migrating-from-langgraph.mdx new file mode 100644 index 0000000000..192aa53e43 --- /dev/null +++ b/docs/v1.15.13/en/guides/migration/migrating-from-langgraph.mdx @@ -0,0 +1,518 @@ +--- +title: "Moving from LangGraph to CrewAI: A Practical Guide for Engineers" +description: If you already have built with LangGraph, learn how to quickly port your projects to CrewAI +icon: switch +mode: "wide" +--- + +You've built agents with LangGraph. You've wrestled with `StateGraph`, wired up conditional edges, and debugged state dictionaries at 2 AM. It works — but somewhere along the way, you started wondering if there's a better path to production. + +There is. **CrewAI Flows** gives you the same power — event-driven orchestration, conditional routing, shared state — with dramatically less boilerplate and a mental model that maps cleanly to how you actually think about multi-step AI workflows. + +This article walks through the core concepts side by side, shows real code comparisons, and demonstrates why CrewAI Flows is the framework you'll want to reach for next. + +--- + +## The Mental Model Shift + +LangGraph asks you to think in **graphs**: nodes, edges, and state dictionaries. Every workflow is a directed graph where you explicitly wire transitions between computation steps. It's powerful, but the abstraction carries overhead — especially when your workflow is fundamentally sequential with a few decision points. + +CrewAI Flows asks you to think in **events**: methods that start things, methods that listen for results, and methods that route execution. The topology of your workflow emerges from decorator annotations rather than explicit graph construction. This isn't just syntactic sugar — it changes how you design, read, and maintain your pipelines. + +Here's the core mapping: + +| LangGraph Concept | CrewAI Flows Equivalent | +| --- | --- | +| `StateGraph` class | `Flow` class | +| `add_node()` | Methods decorated with `@start`, `@listen` | +| `add_edge()` / `add_conditional_edges()` | `@listen()` / `@router()` decorators | +| `TypedDict` state | Pydantic `BaseModel` state | +| `START` / `END` constants | `@start()` decorator / natural method return | +| `graph.compile()` | `flow.kickoff()` | +| Checkpointer / persistence | Built-in memory (LanceDB-backed) | + +Let's see what this looks like in practice. + +--- + +## Demo 1: A Simple Sequential Pipeline + +Imagine you're building a pipeline that takes a topic, researches it, writes a summary, and formats the output. Here's how each framework handles it. + +### LangGraph Approach + +```python +from typing import TypedDict +from langgraph.graph import StateGraph, START, END + +class ResearchState(TypedDict): + topic: str + raw_research: str + summary: str + formatted_output: str + +def research_topic(state: ResearchState) -> dict: + # Call an LLM or search API + result = llm.invoke(f"Research the topic: {state['topic']}") + return {"raw_research": result} + +def write_summary(state: ResearchState) -> dict: + result = llm.invoke( + f"Summarize this research:\n{state['raw_research']}" + ) + return {"summary": result} + +def format_output(state: ResearchState) -> dict: + result = llm.invoke( + f"Format this summary as a polished article section:\n{state['summary']}" + ) + return {"formatted_output": result} + +# Build the graph +graph = StateGraph(ResearchState) +graph.add_node("research", research_topic) +graph.add_node("summarize", write_summary) +graph.add_node("format", format_output) + +graph.add_edge(START, "research") +graph.add_edge("research", "summarize") +graph.add_edge("summarize", "format") +graph.add_edge("format", END) + +# Compile and run +app = graph.compile() +result = app.invoke({"topic": "quantum computing advances in 2026"}) +print(result["formatted_output"]) +``` + +You define functions, register them as nodes, and manually wire every transition. For a simple sequence like this, there's a lot of ceremony. + +### CrewAI Flows Approach + +```python +from crewai import LLM, Agent, Crew, Process, Task +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class ResearchState(BaseModel): + topic: str = "" + raw_research: str = "" + summary: str = "" + formatted_output: str = "" + +class ResearchFlow(Flow[ResearchState]): + @start() + def research_topic(self): + # Option 1: Direct LLM call + result = llm.call(f"Research the topic: {self.state.topic}") + self.state.raw_research = result + return result + + @listen(research_topic) + def write_summary(self, research_output): + # Option 2: A single agent + summarizer = Agent( + role="Research Summarizer", + goal="Produce concise, accurate summaries of research content", + backstory="You are an expert at distilling complex research into clear, " + "digestible summaries.", + llm=llm, + verbose=True, + ) + result = summarizer.kickoff( + f"Summarize this research:\n{self.state.raw_research}" + ) + self.state.summary = str(result) + return self.state.summary + + @listen(write_summary) + def format_output(self, summary_output): + # Option 3: a complete crew (with one or more agents) + formatter = Agent( + role="Content Formatter", + goal="Transform research summaries into polished, publication-ready article sections", + backstory="You are a skilled editor with expertise in structuring and " + "presenting technical content for a general audience.", + llm=llm, + verbose=True, + ) + format_task = Task( + description=f"Format this summary as a polished article section:\n{self.state.summary}", + expected_output="A well-structured, polished article section ready for publication.", + agent=formatter, + ) + crew = Crew( + agents=[formatter], + tasks=[format_task], + process=Process.sequential, + verbose=True, + ) + result = crew.kickoff() + self.state.formatted_output = str(result) + return self.state.formatted_output + +# Run the flow +flow = ResearchFlow() +flow.state.topic = "quantum computing advances in 2026" +result = flow.kickoff() +print(flow.state.formatted_output) + +``` + +Notice what's different: no graph construction, no edge wiring, no compile step. The execution order is declared right where the logic lives. `@start()` marks the entry point, and `@listen(method_name)` chains steps together. The state is a proper Pydantic model with type safety, validation, and IDE auto-completion. + +--- + +## Demo 2: Conditional Routing + +This is where things get interesting. Say you're building a content pipeline that routes to different processing paths based on the type of content detected. + +### LangGraph Approach + +```python +from typing import TypedDict, Literal +from langgraph.graph import StateGraph, START, END + +class ContentState(TypedDict): + input_text: str + content_type: str + result: str + +def classify_content(state: ContentState) -> dict: + content_type = llm.invoke( + f"Classify this content as 'technical', 'creative', or 'business':\n{state['input_text']}" + ) + return {"content_type": content_type.strip().lower()} + +def process_technical(state: ContentState) -> dict: + result = llm.invoke(f"Process as technical doc:\n{state['input_text']}") + return {"result": result} + +def process_creative(state: ContentState) -> dict: + result = llm.invoke(f"Process as creative writing:\n{state['input_text']}") + return {"result": result} + +def process_business(state: ContentState) -> dict: + result = llm.invoke(f"Process as business content:\n{state['input_text']}") + return {"result": result} + +# Routing function +def route_content(state: ContentState) -> Literal["technical", "creative", "business"]: + return state["content_type"] + +# Build the graph +graph = StateGraph(ContentState) +graph.add_node("classify", classify_content) +graph.add_node("technical", process_technical) +graph.add_node("creative", process_creative) +graph.add_node("business", process_business) + +graph.add_edge(START, "classify") +graph.add_conditional_edges( + "classify", + route_content, + { + "technical": "technical", + "creative": "creative", + "business": "business", + } +) +graph.add_edge("technical", END) +graph.add_edge("creative", END) +graph.add_edge("business", END) + +app = graph.compile() +result = app.invoke({"input_text": "Explain how TCP handshakes work"}) +``` + +You need a separate routing function, explicit conditional edge mapping, and termination edges for every branch. The routing logic is decoupled from the node that produces the routing decision. + +### CrewAI Flows Approach + +```python +from crewai import LLM, Agent +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class ContentState(BaseModel): + input_text: str = "" + content_type: str = "" + result: str = "" + +class ContentFlow(Flow[ContentState]): + @start() + def classify_content(self): + self.state.content_type = ( + llm.call( + f"Classify this content as 'technical', 'creative', or 'business':\n" + f"{self.state.input_text}" + ) + .strip() + .lower() + ) + return self.state.content_type + + @router(classify_content) + def route_content(self, classification): + if classification == "technical": + return "process_technical" + elif classification == "creative": + return "process_creative" + else: + return "process_business" + + @listen("process_technical") + def handle_technical(self): + agent = Agent( + role="Technical Writer", + goal="Produce clear, accurate technical documentation", + backstory="You are an expert technical writer who specializes in " + "explaining complex technical concepts precisely.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as technical doc:\n{self.state.input_text}") + ) + + @listen("process_creative") + def handle_creative(self): + agent = Agent( + role="Creative Writer", + goal="Craft engaging and imaginative creative content", + backstory="You are a talented creative writer with a flair for " + "compelling storytelling and vivid expression.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as creative writing:\n{self.state.input_text}") + ) + + @listen("process_business") + def handle_business(self): + agent = Agent( + role="Business Writer", + goal="Produce professional, results-oriented business content", + backstory="You are an experienced business writer who communicates " + "strategy and value clearly to professional audiences.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as business content:\n{self.state.input_text}") + ) + +flow = ContentFlow() +flow.state.input_text = "Explain how TCP handshakes work" +flow.kickoff() +print(flow.state.result) + +``` + +The `@router()` decorator turns a method into a decision point. It returns a string that matches a listener — no mapping dictionaries, no separate routing functions. The branching logic reads like a Python `if` statement because it *is* one. + +--- + +## Demo 3: Integrating AI Agent Crews into Flows + +Here's where CrewAI's real power shines. Flows aren't just for chaining LLM calls — they orchestrate full **Crews** of autonomous agents. This is something LangGraph simply doesn't have a native equivalent for. + +```python +from crewai import Agent, Task, Crew +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ArticleState(BaseModel): + topic: str = "" + research: str = "" + draft: str = "" + final_article: str = "" + +class ArticleFlow(Flow[ArticleState]): + + @start() + def run_research_crew(self): + """A full Crew of agents handles research.""" + researcher = Agent( + role="Senior Research Analyst", + goal=f"Produce comprehensive research on: {self.state.topic}", + backstory="You're a veteran analyst known for thorough, " + "well-sourced research reports.", + llm="gpt-4o" + ) + + research_task = Task( + description=f"Research '{self.state.topic}' thoroughly. " + "Cover key trends, data points, and expert opinions.", + expected_output="A detailed research brief with sources.", + agent=researcher + ) + + crew = Crew(agents=[researcher], tasks=[research_task]) + result = crew.kickoff() + self.state.research = result.raw + return result.raw + + @listen(run_research_crew) + def run_writing_crew(self, research_output): + """A different Crew handles writing.""" + writer = Agent( + role="Technical Writer", + goal="Write a compelling article based on provided research.", + backstory="You turn complex research into engaging, clear prose.", + llm="gpt-4o" + ) + + editor = Agent( + role="Senior Editor", + goal="Review and polish articles for publication quality.", + backstory="20 years of editorial experience at top tech publications.", + llm="gpt-4o" + ) + + write_task = Task( + description=f"Write an article based on this research:\n{self.state.research}", + expected_output="A well-structured draft article.", + agent=writer + ) + + edit_task = Task( + description="Review, fact-check, and polish the draft article.", + expected_output="A publication-ready article.", + agent=editor + ) + + crew = Crew(agents=[writer, editor], tasks=[write_task, edit_task]) + result = crew.kickoff() + self.state.final_article = result.raw + return result.raw + +# Run the full pipeline +flow = ArticleFlow() +flow.state.topic = "The Future of Edge AI" +flow.kickoff() +print(flow.state.final_article) +``` + +This is the key insight: **Flows provide the orchestration layer, and Crews provide the intelligence layer.** Each step in a Flow can spin up a full team of collaborating agents, each with their own roles, goals, and tools. You get structured, predictable control flow *and* autonomous agent collaboration — the best of both worlds. + +In LangGraph, achieving something similar means manually implementing agent communication protocols, tool-calling loops, and delegation logic inside your node functions. It's possible, but it's plumbing you're building from scratch every time. + +--- + +## Demo 4: Parallel Execution and Synchronization + +Real-world pipelines often need to fan out work and join the results. CrewAI Flows handles this elegantly with `and_` and `or_` operators. + +```python +from crewai import LLM +from crewai.flow.flow import Flow, and_, listen, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class AnalysisState(BaseModel): + topic: str = "" + market_data: str = "" + tech_analysis: str = "" + competitor_intel: str = "" + final_report: str = "" + +class ParallelAnalysisFlow(Flow[AnalysisState]): + @start() + def start_method(self): + pass + + @listen(start_method) + def gather_market_data(self): + # Your agentic or deterministic code + pass + + @listen(start_method) + def run_tech_analysis(self): + # Your agentic or deterministic code + pass + + @listen(start_method) + def gather_competitor_intel(self): + # Your agentic or deterministic code + pass + + @listen(and_(gather_market_data, run_tech_analysis, gather_competitor_intel)) + def synthesize_report(self): + # Your agentic or deterministic code + pass + +flow = ParallelAnalysisFlow() +flow.state.topic = "AI-powered developer tools" +flow.kickoff() + +``` + +Multiple `@start()` decorators fire in parallel. The `and_()` combinator on the `@listen` decorator ensures `synthesize_report` only executes after *all three* upstream methods complete. There's also `or_()` for when you want to proceed as soon as *any* upstream task finishes. + +In LangGraph, you'd need to build a fan-out/fan-in pattern with parallel branches, a synchronization node, and careful state merging — all wired explicitly through edges. + +--- + +## Why CrewAI Flows for Production + +Beyond cleaner syntax, Flows deliver several production-critical advantages: + +**Built-in state persistence.** Flow state is backed by LanceDB, meaning your workflows can survive crashes, be resumed, and accumulate knowledge across runs. LangGraph requires you to configure a separate checkpointer. + +**Type-safe state management.** Pydantic models give you validation, serialization, and IDE support out of the box. LangGraph's `TypedDict` states don't validate at runtime. + +**First-class agent orchestration.** Crews are a native primitive. You define agents with roles, goals, backstories, and tools — and they collaborate autonomously within the structured envelope of a Flow. No need to reinvent multi-agent coordination. + +**Simpler mental model.** Decorators declare intent. `@start` means "begin here." `@listen(x)` means "run after x." `@router(x)` means "decide where to go after x." The code reads like the workflow it describes. + +**CLI integration.** Run flows with `crewai run`. No separate compilation step, no graph serialization. Your Flow is a Python class, and it runs like one. + +--- + +## Migration Cheat Sheet + +If you're sitting on a LangGraph codebase and want to move to CrewAI Flows, here's a practical conversion guide: + +1. **Map your state.** Convert your `TypedDict` to a Pydantic `BaseModel`. Add default values for all fields. +2. **Convert nodes to methods.** Each `add_node` function becomes a method on your `Flow` subclass. Replace `state["field"]` reads with `self.state.field`. +3. **Replace edges with decorators.** Your `add_edge(START, "first_node")` becomes `@start()` on the first method. Sequential `add_edge("a", "b")` becomes `@listen(a)` on method `b`. +4. **Replace conditional edges with `@router`.** Your routing function and `add_conditional_edges()` mapping become a single `@router()` method that returns a route string. +5. **Replace compile + invoke with kickoff.** Drop `graph.compile()`. Call `flow.kickoff()` instead. +6. **Consider where Crews fit.** Any node where you have complex multi-step agent logic is a candidate for extraction into a Crew. This is where you'll see the biggest quality improvement. + +--- + +## Getting Started + +Install CrewAI and scaffold a new Flow project: + +```bash +pip install crewai +crewai create flow my_first_flow +cd my_first_flow +``` + +This generates a project structure with a ready-to-edit Flow class, configuration files, and a `pyproject.toml` with `type = "flow"` already set. Run it with: + +```bash +crewai run +``` + +From there, add your agents, wire up your listeners, and ship it. + +--- + +## Final Thoughts + +LangGraph taught the ecosystem that AI workflows need structure. That was an important lesson. But CrewAI Flows takes that lesson and delivers it in a form that's faster to write, easier to read, and more powerful in production — especially when your workflows involve multiple collaborating agents. + +If you're building anything beyond a single-agent chain, give Flows a serious look. The decorator-driven model, native Crew integration, and built-in state management mean you'll spend less time on plumbing and more time on the problems that matter. + +Start with `crewai create flow`. You won't look back. diff --git a/docs/v1.15.13/en/guides/migration/upgrading-crewai.mdx b/docs/v1.15.13/en/guides/migration/upgrading-crewai.mdx new file mode 100644 index 0000000000..48895a2549 --- /dev/null +++ b/docs/v1.15.13/en/guides/migration/upgrading-crewai.mdx @@ -0,0 +1,190 @@ +--- +title: "Upgrading CrewAI" +description: "How to upgrade CrewAI in your project and adapt to breaking changes between versions." +icon: "arrow-up-circle" +--- + +## Overview + +CrewAI releases ship new capabilities regularly. This guide walks you through the practical steps to keep your installation up to date — both the CLI and your project's virtual environment. + +If you're starting fresh, see [Installation](/en/installation). If you're coming from another framework, see [Migrating from LangGraph](/en/guides/migration/migrating-from-langgraph). + +--- + +## The Two Things You Might Want to Upgrade + +CrewAI lives in two places on your machine, and they upgrade independently: + +| What | How it's installed | How to upgrade | +|---|---|---| +| The **global `crewai` CLI** | `uv tool install crewai` | `uv tool install crewai --upgrade` | +| The **project venv** (what your code runs) | `crewai install` / `uv sync` | `uv add "crewai[...]>=X.Y.Z"` then `crewai install` | + +These can — and often do — get out of sync. Running `crewai --version` tells you the CLI version. Running `uv pip show crewai` inside your project tells you the venv version. If they differ, that's normal; what matters for your running code is the venv version. + +## Why `crewai install` Alone Doesn't Upgrade + +`crewai install` is a thin wrapper around `uv sync`. It installs exactly what the current `uv.lock` file says — it does **not** bump any version constraints. + +If your `pyproject.toml` says `crewai>=1.11.1` and the lock file resolved to `1.11.1`, running `crewai install` will keep you on `1.11.1` forever, even if `1.14.4` is available. + +To actually upgrade, you need to: + +1. Update the version constraint in `pyproject.toml` +2. Re-solve the lock file +3. Sync the venv + +`uv add` does all three in one shot. + +## How to Upgrade Your Project + +```bash +# Bump the constraint and re-lock in one command +uv add "crewai[tools]>=1.14.4" + +# Sync the venv (crewai install calls uv sync under the hood) +crewai install + +# Verify +uv pip show crewai +# → Version: 1.14.4 +``` + +Replace `[tools]` with whatever extras your project uses (e.g. `[tools,anthropic]`). Check your `pyproject.toml` `dependencies` list if you're unsure. + + + `uv add` updates both `pyproject.toml` **and** `uv.lock` atomically. If you edit `pyproject.toml` manually, you still need to run `uv lock --upgrade-package crewai` to re-solve the lock file before `crewai install` will pick up the new version. + + +## Upgrading the Global CLI + +The global CLI is separate from your project. Upgrade it with: + +```bash +uv tool install crewai --upgrade +``` + +If your shell warns about `PATH` after the upgrade, refresh it: + +```bash +uv tool update-shell +``` + +This does **not** touch your project's venv — you still need `uv add` + `crewai install` inside the project. + +## Verify Both Are in Sync + +```bash +# Global CLI version +crewai --version + +# Project venv version +uv pip show crewai | grep Version +``` + +They don't need to match — but your project venv version is what matters for runtime behavior. + + + CrewAI requires `Python >=3.10, <3.14`. If `uv` was installed against an older interpreter, recreate the project venv with a supported Python before running `crewai install`. + + +--- + +## Breaking Changes & Migration Notes + +Most upgrades only require small adjustments. The areas below are the ones that break silently or with confusing tracebacks. + +### Import paths: tools and `BaseTool` + +The canonical import location for tools is `crewai.tools`. Older paths still surface in tutorials but should be updated. + +```python +# Before +from crewai_tools import BaseTool +from crewai.agents.tools import tool + +# After +from crewai.tools import BaseTool, tool +``` + +The `@tool` decorator and `BaseTool` subclass both live in `crewai.tools`. `AgentFinish` and other internal-agent symbols are no longer part of the public surface — if you were importing them, switch to event listeners or `Task` callbacks instead. + +### `Agent` parameter changes + +```python +from crewai import Agent + +agent = Agent( + role="Researcher", + goal="Find authoritative sources on {topic}", + backstory="You are a careful, source-driven researcher.", + llm="gpt-4o-mini", # string model name OR an LLM object + verbose=True, # bool, not an int level + max_iter=15, # default has changed across versions — set explicitly + allow_delegation=False, +) +``` + +- `llm` accepts either a string model name (resolved via the configured provider) or an `LLM` object for fine-grained control. +- `verbose` is a plain `bool`. Passing an integer no longer toggles log levels. +- `max_iter` defaults have shifted between releases. If your agent silently stops looping after the first tool call, set `max_iter` explicitly. + +### `Crew` parameters + +```python +from crewai import Crew, Process + +crew = Crew( + agents=[...], + tasks=[...], + process=Process.sequential, # or Process.hierarchical + memory=True, + cache=True, + embedder={"provider": "openai", "config": {"model": "text-embedding-3-large"}}, +) +``` + +- `process=Process.hierarchical` requires either `manager_llm=` or `manager_agent=`. Without one, kickoff raises at validation time. +- `memory=True` with a non-default embedding provider needs an `embedder` dict — see [Memory & embedder config](#memory-embedder-config) below. + +### `Task` structured output + +Use `output_pydantic`, `output_json`, or `output_file` to coerce a task's result into a typed shape: + +```python +from pydantic import BaseModel +from crewai import Task + +class Article(BaseModel): + title: str + body: str + +write = Task( + description="Write an article about {topic}", + expected_output="A short article with a title and body", + agent=writer, + output_pydantic=Article, # the class, NOT an instance + output_file="output/article.md", +) +``` + +`output_pydantic` takes the **class** itself. Passing `Article(title="", body="")` is a common mistake and fails with a confusing validation error. + +### Memory & embedder config {#memory-embedder-config} + +If `memory=True` and you're not using the default OpenAI `text-embedding-3-large` embeddings, you must pass an `embedder`: + +```python +crew = Crew( + agents=[...], + tasks=[...], + memory=True, + embedder={ + "provider": "ollama", + "config": {"model": "nomic-embed-text"}, + }, +) +``` + +Set the relevant provider credentials (`OPENAI_API_KEY`, `OLLAMA_HOST`, etc.) in your `.env` file. Memory storage paths are project-local by default. Existing local memory stores created with 1536-dimensional embeddings may not be compatible with the default OpenAI `text-embedding-3-large` embedder, which uses 3072 dimensions. If you hit a dimension mismatch, delete the project's memory directory, run `crewai reset-memories -m`, or explicitly configure the older embedder model until you migrate. diff --git a/docs/v1.15.13/en/guides/tools/publish-custom-tools.mdx b/docs/v1.15.13/en/guides/tools/publish-custom-tools.mdx new file mode 100644 index 0000000000..71dbfd6221 --- /dev/null +++ b/docs/v1.15.13/en/guides/tools/publish-custom-tools.mdx @@ -0,0 +1,305 @@ +--- +title: Publish Custom Tools +description: How to build, package, and publish your own CrewAI-compatible tools to PyPI so any CrewAI user can install and use them. +icon: box-open +mode: "wide" +--- + +## Overview + +CrewAI's tool system is designed to be extended. If you've built a tool that could benefit others, you can package it as a standalone Python library, publish it to PyPI, and make it available to any CrewAI user — no PR to the CrewAI repo required. + +This guide walks through the full process: implementing the tools contract, structuring your package, and publishing to PyPI. + + +If you just need a custom tool for your own project, see the [Create Custom Tools](/en/learn/create-custom-tools) guide instead. + + +## The Tools Contract + +Every CrewAI tool must satisfy one of two interfaces: + +### Option 1: Subclass `BaseTool` + +Subclass `crewai.tools.BaseTool` and implement the `_run` method. Define `name`, `description`, and optionally an `args_schema` for input validation. + +```python +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + + +class GeolocateInput(BaseModel): + """Input schema for GeolocateTool.""" + address: str = Field(..., description="The street address to geolocate.") + + +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converts a street address into latitude/longitude coordinates." + args_schema: type[BaseModel] = GeolocateInput + + def _run(self, address: str) -> str: + # Your implementation here + return f"40.7128, -74.0060" +``` + +### Option 2: Use the `@tool` Decorator + +For simpler tools, the `@tool` decorator turns a function into a CrewAI tool. The function **must** have a docstring (used as the tool description) and type annotations. + +```python +from crewai.tools import tool + + +@tool("Geolocate") +def geolocate(address: str) -> str: + """Converts a street address into latitude/longitude coordinates.""" + return "40.7128, -74.0060" +``` + +### Key Requirements + +Regardless of which approach you use, your tool must: + +- Have a **`name`** — a short, descriptive identifier. +- Have a **`description`** — tells the agent when and how to use the tool. This directly affects how well agents use your tool, so be clear and specific. +- Implement **`_run`** (BaseTool) or provide a **function body** (@tool) — the synchronous execution logic. +- Use **type annotations** on all parameters and return values. +- Return a **string** result, or define an optional Pydantic output schema for structured results. + +### Optional: Async Support + +If your tool performs I/O-bound work, implement `_arun` for async execution: + +```python +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converts a street address into latitude/longitude coordinates." + + def _run(self, address: str) -> str: + # Sync implementation + ... + + async def _arun(self, address: str) -> str: + # Async implementation + ... +``` + +### Optional: Input Validation with `args_schema` + +Define a Pydantic model as your `args_schema` to get automatic input validation and clear error messages. If you don't provide one, CrewAI will infer it from your `_run` method's signature. + +```python +from pydantic import BaseModel, Field + + +class TranslateInput(BaseModel): + """Input schema for TranslateTool.""" + text: str = Field(..., description="The text to translate.") + target_language: str = Field( + default="en", + description="ISO 639-1 language code for the target language.", + ) +``` + +Explicit schemas are recommended for published tools — they produce better agent behavior and clearer documentation for your users. + +### Optional: Typed Outputs with `result_schema` + +If your tool returns structured data, define a Pydantic output model. This is a good default for published tools because users and agents can rely on named fields. + +Direct Python calls still receive the value your tool returns. When an agent uses the tool, CrewAI sends the agent JSON based on the output model. + +CrewAI can infer the output schema from a Pydantic return annotation: + +```python +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + + +class GeolocateResult(BaseModel): + latitude: float = Field(..., description="Latitude in decimal degrees.") + longitude: float = Field(..., description="Longitude in decimal degrees.") + + +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converts a street address into latitude/longitude coordinates." + + def _run(self, address: str) -> GeolocateResult: + if "1600 Pennsylvania" in address: + return GeolocateResult(latitude=38.8977, longitude=-77.0365) + return GeolocateResult(latitude=40.7128, longitude=-74.0060) +``` + +Set `result_schema` explicitly when your tool returns a dictionary: + +```python +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converts a street address into latitude/longitude coordinates." + result_schema: type[BaseModel] = GeolocateResult + + def _run(self, address: str) -> dict[str, float]: + if "1600 Pennsylvania" in address: + return {"latitude": 38.8977, "longitude": -77.0365} + return {"latitude": 40.7128, "longitude": -74.0060} +``` + +If agents should receive a short text summary instead of JSON, override `format_output_for_agent` on your `BaseTool` subclass. + +```python +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converts a street address into latitude/longitude coordinates." + + def _run(self, address: str) -> GeolocateResult: + if "1600 Pennsylvania" in address: + return GeolocateResult(latitude=38.8977, longitude=-77.0365) + return GeolocateResult(latitude=40.7128, longitude=-74.0060) + + def format_output_for_agent(self, raw_result: object) -> str: + result = GeolocateResult.model_validate(raw_result) + return f"Latitude {result.latitude}, longitude {result.longitude}" +``` + +The override only changes what the agent sees. Direct users of your package still receive the normal value from `tool.run(...)`. + +### Optional: Environment Variables + +If your tool requires API keys or other configuration, declare them with `env_vars` so users know what to set: + +```python +from crewai.tools import BaseTool, EnvVar + + +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converts a street address into latitude/longitude coordinates." + env_vars: list[EnvVar] = [ + EnvVar( + name="GEOCODING_API_KEY", + description="API key for the geocoding service.", + required=True, + ), + ] + + def _run(self, address: str) -> str: + ... +``` + +## Package Structure + +Structure your project as a standard Python package. Here's a recommended layout: + +``` +crewai-geolocate/ +├── pyproject.toml +├── LICENSE +├── README.md +└── src/ + └── crewai_geolocate/ + ├── __init__.py + └── tools.py +``` + +### `pyproject.toml` + +```toml +[project] +name = "crewai-geolocate" +version = "0.1.0" +description = "A CrewAI tool for geolocating street addresses." +requires-python = ">=3.10" +dependencies = [ + "crewai", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" +``` + +Declare `crewai` as a dependency so users get a compatible version automatically. + +### `__init__.py` + +Re-export your tool classes so users can import them directly: + +```python +from crewai_geolocate.tools import GeolocateTool + +__all__ = ["GeolocateTool"] +``` + +### Naming Conventions + +- **Package name**: Use the prefix `crewai-` (e.g., `crewai-geolocate`). This makes your tool discoverable when users search PyPI. +- **Module name**: Use underscores (e.g., `crewai_geolocate`). +- **Tool class name**: Use PascalCase ending in `Tool` (e.g., `GeolocateTool`). + +## Testing Your Tool + +Before publishing, verify your tool works within a crew: + +```python +from crewai import Agent, Crew, Task +from crewai_geolocate import GeolocateTool + +agent = Agent( + role="Location Analyst", + goal="Find coordinates for given addresses.", + backstory="An expert in geospatial data.", + tools=[GeolocateTool()], +) + +task = Task( + description="Find the coordinates of 1600 Pennsylvania Avenue, Washington, DC.", + expected_output="The latitude and longitude of the address.", + agent=agent, +) + +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() +print(result) +``` + +## Publishing to PyPI + +Once your tool is tested and ready: + +```bash +# Build the package +uv build + +# Publish to PyPI +uv publish +``` + +If this is your first time publishing, you'll need a [PyPI account](https://pypi.org/account/register/) and an [API token](https://pypi.org/help/#apitoken). + +### After Publishing + +Users can install your tool with: + +```bash +pip install crewai-geolocate +``` + +Or with uv: + +```bash +uv add crewai-geolocate +``` + +Then use it in their crews: + +```python +from crewai_geolocate import GeolocateTool + +agent = Agent( + role="Location Analyst", + tools=[GeolocateTool()], + # ... +) +``` diff --git a/docs/v1.15.13/en/index.mdx b/docs/v1.15.13/en/index.mdx new file mode 100644 index 0000000000..a6b00d966f --- /dev/null +++ b/docs/v1.15.13/en/index.mdx @@ -0,0 +1,159 @@ +--- +title: "CrewAI Documentation" +description: "Build collaborative AI agents, crews, and flows — production ready from day one." +icon: "house" +mode: "wide" +--- + +
+ CrewAI +
+

Ship multi‑agent systems with confidence

+

+ Design agents, orchestrate crews, and automate flows with guardrails, memory, knowledge, and observability baked in. +

+
+ +
+ Get started + + View changelog + API Reference +
+ +
+ +
+ +## Get started + + + + Overview of CrewAI concepts, architecture, and what you can build with agents, crews, and flows. + + + Install via `uv`, configure API keys, and set up the CLI for local development. + + + Spin up your first crew in minutes. Learn the core runtime, project layout, and dev loop. + + + +## Build the basics + + + + Compose agents with tools, memory, knowledge, and structured outputs using Pydantic. Includes templates and best practices. + + + Orchestrate start/listen/router steps, manage state, persist execution, and resume long-running workflows. + + + Define sequential, hierarchical, or hybrid processes with guardrails, callbacks, and human-in-the-loop triggers. + + + +## Enterprise journey + + + + Manage environments, redeploy safely, and monitor live runs directly from the Enterprise console. + + + Connect Gmail, Slack, Salesforce, and more. Pass trigger payloads into crews and flows automatically. + + + Invite teammates, configure RBAC, and control access to production automations. + + + +## What’s new + + + + Unified overview for Gmail, Drive, Outlook, Teams, OneDrive, HubSpot, and more — now with sample payloads and crews. + + + Call existing CrewAI automations or Amazon Bedrock Agents directly from your crews using the updated integration toolkit. + + + + + Browse the examples and cookbooks for end-to-end reference implementations across agents, flows, and enterprise automations. + + +## Stay connected + + + + If CrewAI helps you ship faster, give us a star and share your builds with the community. + + + Ask questions, showcase workflows, and request features alongside other builders. + + diff --git a/docs/v1.15.13/en/installation.mdx b/docs/v1.15.13/en/installation.mdx new file mode 100644 index 0000000000..381b92c8ad --- /dev/null +++ b/docs/v1.15.13/en/installation.mdx @@ -0,0 +1,337 @@ +--- +title: Installation +description: Get started with CrewAI - Install, configure, and build your first AI crew +icon: wrench +mode: "wide" +--- + +
+
+

+ Coding agent setup +

+

Set up CrewAI in your coding agent

+

+ Copy a ready-to-paste setup prompt for Claude Code, Codex, Cursor, or any coding agent. It installs the official CrewAI skills, checks the CLI, and points the agent at the right docs before it edits code. +

+
+ +
+ + + View coding-agent guide + +
+
+ +### Watch: Building CrewAI Agents & Flows with Coding Agent Skills + + + +## Video Tutorial + +Watch this video tutorial for a step-by-step demonstration of the installation process: + + + +## Text Tutorial + + + **Python Version Requirements** + +CrewAI requires `Python >=3.10 and <3.14`. Here's how to check your version: + +```bash +python3 --version +``` + +If you need to update Python, visit [python.org/downloads](https://python.org/downloads) + + + + + **OpenAI SDK Requirement** + +CrewAI 0.175.0 requires `openai >= 1.13.3`. If you manage dependencies yourself, ensure your environment satisfies this constraint to avoid import/runtime issues. + + + +CrewAI uses the `uv` as its dependency management and package handling tool. It simplifies project setup and execution, offering a seamless experience. + +If you haven't installed `uv` yet, follow **step 1** to quickly get it set up on your system, else you can skip to **step 2**. + + + + - **On macOS/Linux:** + + Use `curl` to download the script and execute it with `sh`: + + ```shell + curl -LsSf https://astral.sh/uv/install.sh | sh + ``` + If your system doesn't have `curl`, you can use `wget`: + + ```shell + wget -qO- https://astral.sh/uv/install.sh | sh + ``` + + - **On Windows:** + + Use `irm` to download the script and `iex` to execute it: + + ```shell + powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" + ``` + If you run into any issues, refer to [UV's installation guide](https://docs.astral.sh/uv/getting-started/installation/) for more information. + + + + - Run the following command to install `crewai` CLI: + ```shell + uv tool install crewai + ``` + + If you encounter a `PATH` warning, run this command to update your shell: + ```shell + uv tool update-shell + ``` + + + + If you encounter the `chroma-hnswlib==0.7.6` build error (`fatal error C1083: Cannot open include file: 'float.h'`) on Windows, install [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/) with *Desktop development with C++*. + + + - To verify that `crewai` is installed, run: + ```shell + uv tool list + ``` + - You should see something like: + ```shell + crewai v0.102.0 + - crewai + ``` + - If you need to update `crewai`, run: + ```shell + uv tool install crewai --upgrade + ``` + + This upgrades the **global `crewai` CLI tool** only. To upgrade the `crewai` version inside your project's virtual environment, see [Upgrading CrewAI in a project](/en/guides/migration/upgrading-crewai). + + Installation successful! You're ready to create your first crew! 🎉 + + + + +# Creating a CrewAI Project + +`crewai create crew` now creates a JSON-first crew project. Agents live in `agents/*.jsonc`, tasks and crew-level settings live in `crew.jsonc`, and `crewai run` loads that JSON definition directly. + + + + - Run the `crewai` CLI command: + ```shell + crewai create crew + ``` + + - This creates a new project with the following structure: + ``` + my_project/ + ├── .gitignore + ├── .env + ├── agents/ + │ └── researcher.jsonc + ├── crew.jsonc + ├── knowledge/ + ├── pyproject.toml + ├── README.md + ├── skills/ + └── tools/ + ``` + + - If you need the older Python/YAML scaffold with `crew.py`, `config/agents.yaml`, and `config/tasks.yaml`, run: + ```shell + crewai create crew --classic + ``` + + + + + - Your project will contain these essential files: + | File | Purpose | + | --- | --- | + | `crew.jsonc` | Configure the crew, task order, process, and input defaults | + | `agents/*.jsonc` | Define each agent's role, goal, backstory, LLM, tools, and behavior | + | `.env` | Store API keys and environment variables | + | `tools/` | Optional Python files for `custom:` tools | + | `knowledge/` | Optional knowledge files for agents | + | `skills/` | Optional skill files applied to the crew | + + - Start by editing `crew.jsonc` and the files in `agents/` to define your crew's behavior. + - Use `{placeholder}` values in agent and task text, then set defaults in `crew.jsonc` under `inputs`. When you run `crewai run`, the CLI prompts for any missing values. + - Keep sensitive information like API keys in `.env`. + + + + + - Before you run your crew, make sure to run: + ```bash + crewai install + ``` + - If you need to install additional packages, use: + ```shell + uv add + ``` + + As a supply-chain security measure, CrewAI's internal packages use `exclude-newer = "3 days"` in their `pyproject.toml` files. This means transitive dependencies pulled in by CrewAI won't resolve packages released less than 3 days ago. Your own direct dependencies are not affected by this policy. If you notice a transitive dependency is behind, you can pin the version you want explicitly in your project's dependencies. + + - To run your crew, execute the following command in the root of your project: + ```bash + crewai run + ``` + + + +## Enterprise Installation Options + + +For teams and organizations, CrewAI offers enterprise deployment options that eliminate setup complexity: + +### CrewAI AMP (SaaS) + +- Zero installation required - just sign up for free at [app.crewai.com](https://app.crewai.com) +- Automatic updates and maintenance +- Managed infrastructure and scaling +- Build Crews with no Code + +### CrewAI Factory (Self-hosted) + +- Containerized deployment for your infrastructure +- Supports any hyperscaler including on prem deployments +- Integration with your existing security systems + + + Learn about CrewAI's enterprise offerings and schedule a demo + + + +## Next Steps + + + + Follow the quickstart to scaffold a Flow, run a one-agent crew, and produce a report. + + + Connect with other developers, get help, and share your CrewAI experiences. + + diff --git a/docs/v1.15.13/en/introduction.mdx b/docs/v1.15.13/en/introduction.mdx new file mode 100644 index 0000000000..a2550ca480 --- /dev/null +++ b/docs/v1.15.13/en/introduction.mdx @@ -0,0 +1,152 @@ +--- +title: Introduction +description: Build AI agent teams that work together to tackle complex tasks +icon: handshake +mode: "wide" +--- + +# What is CrewAI? + +**CrewAI is the leading open-source framework for orchestrating autonomous AI agents and building complex workflows.** + +It empowers developers to build production-ready multi-agent systems by combining the collaborative intelligence of **Crews** with the precise control of **Flows**. + +- **[CrewAI Flows](/en/guides/flows/first-flow)**: The backbone of your AI application. Flows allow you to create structured, event-driven workflows that manage state and control execution. They provide the scaffolding for your AI agents to work within. +- **[CrewAI Crews](/en/guides/crews/first-crew)**: The units of work within your Flow. Crews are teams of autonomous agents that collaborate to solve specific tasks delegated to them by the Flow. + +With over 100,000 developers certified through our community courses, CrewAI is the standard for enterprise-ready AI automation. + +### Watch: Building CrewAI Agents & Flows with Coding Agent Skills + +Install our coding agent skills (Claude Code, Codex, ...) to quickly get your coding agents up and running with CrewAI. + +You can install it with `npx skills add crewaiinc/skills` + + + +## The CrewAI Architecture + +CrewAI's architecture is designed to balance autonomy with control. + +### 1. Flows: The Backbone + + + Think of a Flow as the "manager" or the "process definition" of your application. It defines the steps, the logic, and how data moves through your system. + + + + CrewAI Framework Overview + + +Flows provide: +- **State Management**: Persist data across steps and executions. +- **Event-Driven Execution**: Trigger actions based on events or external inputs. +- **Control Flow**: Use conditional logic, loops, and branching. + +### 2. Crews: The Intelligence + + + Crews are the "teams" that do the heavy lifting. Within a Flow, you can trigger a Crew to tackle a complex problem requiring creativity and collaboration. + + + + CrewAI Framework Overview + + +Crews provide: +- **Role-Playing Agents**: Specialized agents with specific goals and tools. +- **Autonomous Collaboration**: Agents work together to solve tasks. +- **Task Delegation**: Tasks are assigned and executed based on agent capabilities. + +## How It All Works Together + +1. **The Flow** triggers an event or starts a process. +2. **The Flow** manages the state and decides what to do next. +3. **The Flow** delegates a complex task to a **Crew**. +4. **The Crew**'s agents collaborate to complete the task. +5. **The Crew** returns the result to the **Flow**. +6. **The Flow** continues execution based on the result. + +## Key Features + + + + Build reliable, stateful workflows that can handle long-running processes and complex logic. + + + Deploy teams of agents that can plan, execute, and collaborate to achieve high-level goals. + + + Connect your agents to any API, database, or local tool. + + + Designed with security and compliance in mind for enterprise deployments. + + + +## When to Use Crews vs. Flows + +**The short answer: Use both.** + +For any production-ready application, **start with a Flow**. + +- **Use a Flow** to define the overall structure, state, and logic of your application. +- **Use a Crew** within a Flow step when you need a team of agents to perform a specific, complex task that requires autonomy. + +| Use Case | Architecture | +| :--- | :--- | +| **Simple Automation** | Single Flow with Python tasks | +| **Complex Research** | Flow managing state -> Crew performing research | +| **Application Backend** | Flow handling API requests -> Crew generating content -> Flow saving to DB | + +## Why Choose CrewAI? + +- 🧠 **Autonomous Operation**: Agents make intelligent decisions based on their roles and available tools +- 📝 **Natural Interaction**: Agents communicate and collaborate like human team members +- 🛠️ **Extensible Design**: Easy to add new tools, roles, and capabilities +- 🚀 **Production Ready**: Built for reliability and scalability in real-world applications +- 🔒 **Security-Focused**: Designed with enterprise security requirements in mind +- 💰 **Cost-Efficient**: Optimized to minimize token usage and API calls + +## Ready to Start Building? + + + + Learn how to create structured, event-driven workflows with precise control over execution. + + + Step-by-step tutorial to create a collaborative AI team that works together to solve complex problems. + + + + + + Get started with CrewAI in your development environment. + + + Scaffold a Flow, run a crew with one agent, and generate a report end to end. + + + Connect with other developers, get help, and share your CrewAI experiences. + + diff --git a/docs/v1.15.13/en/learn/a2a-agent-delegation.mdx b/docs/v1.15.13/en/learn/a2a-agent-delegation.mdx new file mode 100644 index 0000000000..961c9eac31 --- /dev/null +++ b/docs/v1.15.13/en/learn/a2a-agent-delegation.mdx @@ -0,0 +1,550 @@ +--- +title: Agent-to-Agent (A2A) Protocol +description: Agents delegate tasks to remote A2A agents and/or operate as A2A-compliant server agents. +icon: network-wired +mode: "wide" +--- + +## A2A Agent Delegation + + + Deploying A2A agents to production? See [A2A on AMP](https://docs-platform.crewai.com/platform/en/features/a2a) for distributed state, enterprise authentication, gRPC transport, and horizontal scaling. + + +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 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 + + + A2A delegation requires the `a2a-sdk` package. Install with: `uv add 'crewai[a2a]'` or `pip install 'crewai[a2a]'` + + +## Basic Configuration + + + `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. + + +Configure an agent for A2A delegation by setting the `a2a` parameter: + +```python Code +from crewai import Agent, Crew, Task +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=A2AClientConfig( + endpoint="https://example.com/.well-known/agent-card.json", + timeout=120, + max_turns=10 + ) +) + +task = Task( + description="Research the latest developments in quantum computing", + expected_output="A comprehensive research report", + agent=agent +) + +crew = Crew(agents=[agent], tasks=[task], verbose=True) +result = crew.kickoff() +``` + +## Client Configuration Options + +The `A2AClientConfig` class accepts the following parameters: + + + The A2A agent endpoint URL (typically points to `.well-known/agent-card.json`) + + + + Authentication scheme for the A2A agent. Supports Bearer tokens, OAuth2, API keys, and HTTP authentication. + + + + Request timeout in seconds + + + + Maximum number of conversation turns with the A2A agent + + + + Optional Pydantic model for requesting structured output from an A2A agent. A2A protocol does not + enforce this, so an A2A agent does not need to honor this request. + + + + Whether to raise an error immediately if agent connection fails. When `False`, the agent continues with available agents and informs the LLM about unavailable ones. + + + + When `True`, returns the A2A agent's result directly when it signals completion. When `False`, allows the server agent to review the result and potentially continue the conversation. + + + + Update mechanism for receiving task status. Options: `StreamingConfig`, `PollingConfig`, or `PushNotificationConfig`. + + + + Media types the client can accept in responses. + + + + A2A protocol extension URIs the client supports. + + + + Client-side processing hooks for tool injection, prompt augmentation, and response modification. + + + + Transport configuration including preferred transport, supported transports for negotiation, and protocol-specific settings (gRPC message sizes, keepalive, etc.). + + + + **Deprecated**: Use `transport=ClientTransportConfig(preferred=...)` instead. + + + + **Deprecated**: Use `transport=ClientTransportConfig(supported=...)` instead. + + +## Authentication + +For A2A agents that require authentication, use one of the provided auth schemes: + + + +```python bearer_token_auth.py lines +from crewai.a2a import A2AClientConfig +from crewai.a2a.auth import BearerTokenAuth + +agent = Agent( + role="Secure Coordinator", + goal="Coordinate tasks with secured agents", + backstory="Manages secure agent communications", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://secure-agent.example.com/.well-known/agent-card.json", + auth=BearerTokenAuth(token="your-bearer-token"), + timeout=120 + ) +) +``` + + + +```python api_key_auth.py lines +from crewai.a2a import A2AClientConfig +from crewai.a2a.auth import APIKeyAuth + +agent = Agent( + role="API Coordinator", + goal="Coordinate with API-based agents", + backstory="Manages API-authenticated communications", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://api-agent.example.com/.well-known/agent-card.json", + auth=APIKeyAuth( + api_key="your-api-key", + location="header", # or "query" or "cookie" + name="X-API-Key" + ), + timeout=120 + ) +) +``` + + + +```python oauth2_auth.py lines +from crewai.a2a import A2AClientConfig +from crewai.a2a.auth import OAuth2ClientCredentials + +agent = Agent( + role="OAuth Coordinator", + goal="Coordinate with OAuth-secured agents", + backstory="Manages OAuth-authenticated communications", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://oauth-agent.example.com/.well-known/agent-card.json", + auth=OAuth2ClientCredentials( + token_url="https://auth.example.com/oauth/token", + client_id="your-client-id", + client_secret="your-client-secret", + scopes=["read", "write"] + ), + timeout=120 + ) +) +``` + + + +```python http_basic_auth.py lines +from crewai.a2a import A2AClientConfig +from crewai.a2a.auth import HTTPBasicAuth + +agent = Agent( + role="Basic Auth Coordinator", + goal="Coordinate with basic auth agents", + backstory="Manages basic authentication communications", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://basic-agent.example.com/.well-known/agent-card.json", + auth=HTTPBasicAuth( + username="your-username", + password="your-password" + ), + timeout=120 + ) +) +``` + + + +## Multiple A2A Agents + +Configure multiple A2A agents for delegation by passing a list: + +```python Code +from crewai.a2a import A2AClientConfig +from crewai.a2a.auth import BearerTokenAuth + +agent = Agent( + role="Multi-Agent Coordinator", + goal="Coordinate with multiple specialized agents", + backstory="Expert at delegating to the right specialist", + llm="gpt-4o", + a2a=[ + A2AClientConfig( + endpoint="https://research.example.com/.well-known/agent-card.json", + timeout=120 + ), + A2AClientConfig( + endpoint="https://data.example.com/.well-known/agent-card.json", + auth=BearerTokenAuth(token="data-token"), + timeout=90 + ) + ] +) +``` + +The LLM will automatically choose which A2A agent to delegate to based on the task requirements. + +## Error Handling + +Control how agent connection failures are handled using the `fail_fast` parameter: + +```python Code +from crewai.a2a import A2AClientConfig + +# Fail immediately on connection errors (default) +agent = Agent( + role="Research Coordinator", + goal="Coordinate research tasks", + backstory="Expert at delegation", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://research.example.com/.well-known/agent-card.json", + fail_fast=True + ) +) + +# Continue with available agents +agent = Agent( + role="Multi-Agent Coordinator", + goal="Coordinate with multiple agents", + backstory="Expert at working with available resources", + llm="gpt-4o", + a2a=[ + A2AClientConfig( + endpoint="https://primary.example.com/.well-known/agent-card.json", + fail_fast=False + ), + A2AClientConfig( + endpoint="https://backup.example.com/.well-known/agent-card.json", + fail_fast=False + ) + ] +) +``` + +When `fail_fast=False`: +- If some agents fail, the LLM is informed which agents are unavailable and can delegate to working agents +- If all agents fail, the LLM receives a notice about unavailable agents and handles the task directly +- Connection errors are captured and included in the context for better decision-making + +## Update Mechanisms + +Control how your agent receives task status updates from remote A2A agents: + + + +```python streaming_config.py lines +from crewai.a2a import A2AClientConfig +from crewai.a2a.updates import StreamingConfig + +agent = Agent( + role="Research Coordinator", + goal="Coordinate research tasks", + backstory="Expert at delegation", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://research.example.com/.well-known/agent-card.json", + updates=StreamingConfig() + ) +) +``` + + + +```python polling_config.py lines +from crewai.a2a import A2AClientConfig +from crewai.a2a.updates import PollingConfig + +agent = Agent( + role="Research Coordinator", + goal="Coordinate research tasks", + backstory="Expert at delegation", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://research.example.com/.well-known/agent-card.json", + updates=PollingConfig( + interval=2.0, + timeout=300.0, + max_polls=100 + ) + ) +) +``` + + + +```python push_notifications_config.py lines +from crewai.a2a import A2AClientConfig +from crewai.a2a.updates import PushNotificationConfig + +agent = Agent( + role="Research Coordinator", + goal="Coordinate research tasks", + backstory="Expert at delegation", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://research.example.com/.well-known/agent-card.json", + updates=PushNotificationConfig( + url="{base_url}/a2a/callback", + token="your-validation-token", + timeout=300.0 + ) + ) +) +``` + + + +## 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 + + + Human-readable name for the agent. Defaults to the agent's role if not provided. + + + + Human-readable description. Defaults to the agent's goal and backstory if not provided. + + + + Version string for the agent card. + + + + List of agent skills. Auto-generated from agent tools if not provided. + + + + Declaration of optional capabilities supported by the agent. + + + + Supported input MIME types. + + + + Supported output MIME types. + + + + Preferred endpoint URL. If set, overrides the URL passed to `to_agent_card()`. + + + + A2A protocol version this agent supports. + + + + Information about the agent's service provider. + + + + URL to the agent's documentation. + + + + URL to an icon for the agent. + + + + Additional supported interfaces (transport and URL combinations). + + + + Security requirement objects for all agent interactions. + + + + Security schemes available to authorize requests. + + + + Whether agent provides extended card to authenticated users. + + + + Additional skills visible only to authenticated users in the extended agent card. + + + + Configuration for signing the AgentCard with JWS. Supports RS256, ES256, PS256, and related algorithms. + + + + Server-side A2A protocol extensions with `on_request`/`on_response` hooks that modify agent behavior. + + + + Configuration for outgoing push notifications, including HMAC-SHA256 signing secret. + + + + Transport configuration including preferred transport, gRPC server settings, JSON-RPC paths, and HTTP+JSON settings. + + + + Authentication scheme for incoming A2A requests. Defaults to `SimpleTokenAuth` using the `AUTH_TOKEN` environment variable. + + + + **Deprecated**: Use `transport=ServerTransportConfig(preferred=...)` instead. + + + + **Deprecated**: Use `signing_config=AgentCardSigningConfig(...)` instead. + + +### 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") + ] +) +``` + +### File Inputs and Structured Output + +A2A supports passing files and requesting structured output in both directions. + +**Client side**: When delegating to a remote A2A agent, files from the task's `input_files` are sent as `FilePart`s in the outgoing message. If `response_model` is set on the `A2AClientConfig`, the Pydantic model's JSON schema is embedded in the message metadata, requesting structured output from the remote agent. + +**Server side**: Incoming `FilePart`s are extracted and passed to the agent's task as `input_files`. If the client included a JSON schema, the server creates a response model from it and applies it to the task. When the agent returns structured data, the response is sent back as a `DataPart` rather than plain text. + +## Best Practices + + + + Configure timeouts based on expected A2A agent response times. Longer-running tasks may need higher timeout values. + + + + Use `max_turns` to prevent excessive back-and-forth. The agent will automatically conclude conversations before hitting the limit. + + + + Set `fail_fast=False` for production environments with multiple agents to gracefully handle connection failures and maintain workflow continuity. + + + + Store authentication tokens and credentials as environment variables, not in code. + + + + Use verbose mode to observe when the LLM chooses to delegate versus handle tasks directly. + + + +## Supported Authentication Methods + +- **Bearer Token** - Simple token-based authentication +- **OAuth2 Client Credentials** - OAuth2 flow for machine-to-machine communication +- **OAuth2 Authorization Code** - OAuth2 flow requiring user authorization +- **API Key** - Key-based authentication (header, query param, or cookie) +- **HTTP Basic** - Username/password authentication +- **HTTP Digest** - Digest authentication (requires `httpx-auth` package) + +## Learn More + +For more information about the A2A protocol and reference implementations: + +- [A2A Protocol Documentation](https://a2a-protocol.org) +- [A2A Sample Implementations](https://github.com/a2aproject/a2a-samples) +- [A2A Python SDK](https://github.com/a2aproject/a2a-python) diff --git a/docs/v1.15.13/en/learn/a2ui.mdx b/docs/v1.15.13/en/learn/a2ui.mdx new file mode 100644 index 0000000000..c34dd4b8ec --- /dev/null +++ b/docs/v1.15.13/en/learn/a2ui.mdx @@ -0,0 +1,344 @@ +--- +title: Agent-to-UI (A2UI) Protocol +description: Enable agents to generate declarative UI surfaces for rich client rendering via the A2UI extension. +icon: window-restore +mode: "wide" +--- + +## A2UI Overview + +A2UI is a declarative UI protocol extension for [A2A](/en/learn/a2a-agent-delegation) that lets agents emit structured JSON messages describing interactive surfaces. Clients receive these messages and render them as rich UI components — forms, cards, lists, modals, and more — without the agent needing to know anything about the client's rendering stack. + +A2UI is built on the A2A extension mechanism and identified by the URI `https://a2ui.org/a2a-extension/a2ui/v0.8`. + + + A2UI requires the `a2a-sdk` package. Install with: `uv add 'crewai[a2a]'` or `pip install 'crewai[a2a]'` + + +## How It Works + +1. The **server extension** scans agent output for A2UI JSON objects +2. Valid messages are wrapped as `DataPart` entries with the `application/json+a2ui` MIME type +3. The **client extension** augments the agent's system prompt with A2UI instructions and the component catalog +4. The client tracks surface state (active surfaces and data models) across conversation turns + +## Server Setup + +Add `A2UIServerExtension` to your `A2AServerConfig` to enable A2UI output: + +```python Code +from crewai import Agent +from crewai.a2a import A2AServerConfig +from crewai.a2a.extensions.a2ui import A2UIServerExtension + +agent = Agent( + role="Dashboard Agent", + goal="Present data through interactive UI surfaces", + backstory="Expert at building clear, actionable dashboards", + llm="gpt-4o", + a2a=A2AServerConfig( + url="https://your-server.com", + server_extensions=[A2UIServerExtension()], + ), +) +``` + +### Server Extension Options + + + Component catalog identifiers the server supports. When set, only these catalogs are advertised to clients. + + + + Whether to accept inline catalog definitions from clients in addition to named catalogs. + + +## Client Setup + +Add `A2UIClientExtension` to your `A2AClientConfig` to enable A2UI rendering: + +```python Code +from crewai import Agent +from crewai.a2a import A2AClientConfig +from crewai.a2a.extensions.a2ui import A2UIClientExtension + +agent = Agent( + role="UI Coordinator", + goal="Coordinate tasks and render agent responses as rich UI", + backstory="Expert at presenting agent output in interactive formats", + llm="gpt-4o", + a2a=A2AClientConfig( + endpoint="https://dashboard-agent.example.com/.well-known/agent-card.json", + client_extensions=[A2UIClientExtension()], + ), +) +``` + +### Client Extension Options + + + Preferred component catalog identifier. Defaults to `"standard (v0.8)"` when not set. + + + + Restrict which components the agent may use. When `None`, all 18 standard catalog components are available. + + +## Message Types + +A2UI defines four server-to-client message types. Each message targets a **surface** identified by `surfaceId`. + + + + Initializes a new surface with a root component and optional styles. + + ```json + { + "beginRendering": { + "surfaceId": "dashboard-1", + "root": "main-column", + "catalogId": "standard (v0.8)", + "styles": { + "primaryColor": "#EB6658" + } + } + } + ``` + + + + Sends or updates one or more components on an existing surface. + + ```json + { + "surfaceUpdate": { + "surfaceId": "dashboard-1", + "components": [ + { + "id": "main-column", + "component": { + "Column": { + "children": { "explicitList": ["title", "content"] }, + "alignment": "start" + } + } + }, + { + "id": "title", + "component": { + "Text": { + "text": { "literalString": "Dashboard" }, + "usageHint": "h1" + } + } + } + ] + } + } + ``` + + + + Updates the data model bound to a surface, enabling dynamic content. + + ```json + { + "dataModelUpdate": { + "surfaceId": "dashboard-1", + "path": "/data/model", + "contents": [ + { + "key": "userName", + "valueString": "Alice" + }, + { + "key": "score", + "valueNumber": 42 + } + ] + } + } + ``` + + + + Removes a surface and all its components. + + ```json + { + "deleteSurface": { + "surfaceId": "dashboard-1" + } + } + ``` + + + +## Component Catalog + +A2UI ships with 18 standard components organized into three categories: + +### Content + +| Component | Description | Required Fields | +|-----------|-------------|-----------------| +| **Text** | Renders text with optional heading/body hints | `text` (StringBinding) | +| **Image** | Displays an image with fit and size options | `url` (StringBinding) | +| **Icon** | Renders a named icon from a set of 47 icons | `name` (IconBinding) | +| **Video** | Embeds a video player | `url` (StringBinding) | +| **AudioPlayer** | Embeds an audio player with optional description | `url` (StringBinding) | + +### Layout + +| Component | Description | Required Fields | +|-----------|-------------|-----------------| +| **Row** | Horizontal flex container | `children` (ChildrenDef) | +| **Column** | Vertical flex container | `children` (ChildrenDef) | +| **List** | Scrollable list (vertical or horizontal) | `children` (ChildrenDef) | +| **Card** | Elevated container for a single child | `child` (str) | +| **Tabs** | Tabbed container | `tabItems` (list of TabItem) | +| **Divider** | Visual separator (horizontal or vertical) | — | +| **Modal** | Overlay triggered by an entry point | `entryPointChild`, `contentChild` (str) | + +### Interactive + +| Component | Description | Required Fields | +|-----------|-------------|-----------------| +| **Button** | Clickable button that triggers an action | `child` (str), `action` (Action) | +| **CheckBox** | Boolean toggle with a label | `label` (StringBinding), `value` (BooleanBinding) | +| **TextField** | Text input with type and validation options | `label` (StringBinding) | +| **DateTimeInput** | Date and/or time picker | `value` (StringBinding) | +| **MultipleChoice** | Selection from a list of options | `selections` (ArrayBinding), `options` (list) | +| **Slider** | Numeric range slider | `value` (NumberBinding) | + +## Data Binding + +Components reference values through **bindings** rather than raw literals. This allows surfaces to update dynamically when the data model changes. + +There are two ways to bind a value: + +- **Literal values** — hardcoded directly in the component definition +- **Path references** — point to a key in the surface's data model + +```json +{ + "surfaceUpdate": { + "surfaceId": "profile-1", + "components": [ + { + "id": "greeting", + "component": { + "Text": { + "text": { "path": "/data/model/userName" }, + "usageHint": "h2" + } + } + }, + { + "id": "status", + "component": { + "Text": { + "text": { "literalString": "Online" }, + "usageHint": "caption" + } + } + } + ] + } +} +``` + +In this example, `greeting` reads the user's name from the data model (updated via `dataModelUpdate`), while `status` uses a hardcoded literal. + +## Handling User Actions + +Interactive components like `Button` trigger `userAction` events that flow back to the server. Each action includes a `name`, the originating `surfaceId` and `sourceComponentId`, and an optional `context` with key-value pairs. + +```json +{ + "userAction": { + "name": "submitForm", + "surfaceId": "form-1", + "sourceComponentId": "submit-btn", + "timestamp": "2026-03-12T10:00:00Z", + "context": { + "selectedOption": "optionA" + } + } +} +``` + +Action context values can also use path bindings to send current data model values back to the server: + +```json +{ + "Button": { + "child": "confirm-label", + "action": { + "name": "confirm", + "context": [ + { + "key": "currentScore", + "value": { "path": "/data/model/score" } + } + ] + } + } +} +``` + +## Validation + +Use `validate_a2ui_message` to validate server-to-client messages and `validate_a2ui_event` for client-to-server events: + +```python Code +from crewai.a2a.extensions.a2ui import validate_a2ui_message +from crewai.a2a.extensions.a2ui.validator import ( + validate_a2ui_event, + A2UIValidationError, +) + +# Validate a server message +try: + msg = validate_a2ui_message({"beginRendering": {"surfaceId": "s1", "root": "r1"}}) +except A2UIValidationError as exc: + print(exc.errors) + +# Validate a client event +try: + event = validate_a2ui_event({ + "userAction": { + "name": "click", + "surfaceId": "s1", + "sourceComponentId": "btn-1", + "timestamp": "2026-03-12T10:00:00Z", + } + }) +except A2UIValidationError as exc: + print(exc.errors) +``` + +## Best Practices + + + + Begin with a `beginRendering` message and a single `surfaceUpdate`. Add data binding and interactivity once the basic flow works. + + + + Prefer path bindings over literal values for content that changes. Use `dataModelUpdate` to push new values without resending the full component tree. + + + + Use the `allowed_components` option on `A2UIClientExtension` to restrict which components the agent may emit, reducing prompt size and keeping output predictable. + + + + Use `validate_a2ui_message` and `validate_a2ui_event` to catch malformed payloads early, especially when building custom integrations. + + + +## Learn More + +- [A2A Agent Delegation](/en/learn/a2a-agent-delegation) — configure agents for remote delegation via the A2A protocol +- [A2A Protocol Documentation](https://a2a-protocol.org) — official protocol specification diff --git a/docs/v1.15.13/en/learn/before-and-after-kickoff-hooks.mdx b/docs/v1.15.13/en/learn/before-and-after-kickoff-hooks.mdx new file mode 100644 index 0000000000..a9ce1af6ef --- /dev/null +++ b/docs/v1.15.13/en/learn/before-and-after-kickoff-hooks.mdx @@ -0,0 +1,62 @@ +--- +title: Before and After Kickoff Hooks +description: Learn how to use before and after kickoff hooks in CrewAI +mode: "wide" +--- + +CrewAI provides hooks that allow you to execute code before and after a crew's kickoff. These hooks are useful for preprocessing inputs or post-processing results. + +## Before Kickoff Hook + +The before kickoff hook is executed before the crew starts its tasks. It receives the input dictionary and can modify it before passing it to the crew. You can use this hook to set up your environment, load necessary data, or preprocess your inputs. This is useful in scenarios where the input data might need enrichment or validation before being processed by the crew. + +Here's an example of defining a before kickoff function in your `crew.py`: + +```python +from crewai import CrewBase +from crewai.project import before_kickoff + +@CrewBase +class MyCrew: + @before_kickoff + def prepare_data(self, inputs): + # Preprocess or modify inputs + inputs['processed'] = True + return inputs + +#... +``` + +In this example, the prepare_data function modifies the inputs by adding a new key-value pair indicating that the inputs have been processed. + +## After Kickoff Hook + +The after kickoff hook is executed after the crew has completed its tasks. It receives the result object, which contains the outputs of the crew's execution. This hook is ideal for post-processing results, such as logging, data transformation, or further analysis. + +Here's how you can define an after kickoff function in your `crew.py`: + +```python +from crewai import CrewBase +from crewai.project import after_kickoff + +@CrewBase +class MyCrew: + @after_kickoff + def log_results(self, result): + # Log or modify the results + print("Crew execution completed with result:", result) + return result + +# ... +``` + + +In the `log_results` function, the results of the crew execution are simply printed out. You can extend this to perform more complex operations such as sending notifications or integrating with other services. + +## Utilizing Both Hooks + +Both hooks can be used together to provide a comprehensive setup and teardown process for your crew's execution. They are particularly useful in maintaining clean code architecture by separating concerns and enhancing the modularity of your CrewAI implementations. + +## Conclusion + +Before and after kickoff hooks in CrewAI offer powerful ways to interact with the lifecycle of a crew's execution. By understanding and utilizing these hooks, you can greatly enhance the robustness and flexibility of your AI agents. diff --git a/docs/v1.15.13/en/learn/bring-your-own-agent.mdx b/docs/v1.15.13/en/learn/bring-your-own-agent.mdx new file mode 100644 index 0000000000..fb7b22dc21 --- /dev/null +++ b/docs/v1.15.13/en/learn/bring-your-own-agent.mdx @@ -0,0 +1,444 @@ +--- +title: Bring your own agent +description: Learn how to bring your own agents that work within a Crew. +icon: robots +mode: "wide" +--- + +Interoperability is a core concept in CrewAI. This guide will show you how to bring your own agents that work within a Crew. + + +## Adapter Guide for Bringing your own agents (Langgraph Agents, OpenAI Agents, etc...) +We require 3 adapters to turn any agent from different frameworks to work within crew. + +1. BaseAgentAdapter +2. BaseToolAdapter +3. BaseConverter + + +## BaseAgentAdapter +This abstract class defines the common interface and functionality that all +agent adapters must implement. It extends BaseAgent to maintain compatibility +with the CrewAI framework while adding adapter-specific requirements. + +Required Methods: + +1. `def configure_tools` +2. `def configure_structured_output` + +## Creating your own Adapter +To integrate an agent from a different framework (e.g., LangGraph, Autogen, OpenAI Assistants) into CrewAI, you need to create a custom adapter by inheriting from `BaseAgentAdapter`. This adapter acts as a compatibility layer, translating between the CrewAI interfaces and the specific requirements of your external agent. + +Here's how you implement your custom adapter: + +1. **Inherit from `BaseAgentAdapter`**: + ```python + from crewai.agents.agent_adapters.base_agent_adapter import BaseAgentAdapter + from crewai.tools import BaseTool + from typing import List, Optional, Any, Dict + + class MyCustomAgentAdapter(BaseAgentAdapter): + # ... implementation details ... + ``` + +2. **Implement `__init__`**: + The constructor should call the parent class constructor `super().__init__(**kwargs)` and perform any initialization specific to your external agent. You can use the optional `agent_config` dictionary passed during CrewAI's `Agent` initialization to configure your adapter and the underlying agent. + + ```python + def __init__(self, agent_config: Optional[Dict[str, Any]] = None, **kwargs: Any): + super().__init__(agent_config=agent_config, **kwargs) + # Initialize your external agent here, possibly using agent_config + # Example: self.external_agent = initialize_my_agent(agent_config) + print(f"Initializing MyCustomAgentAdapter with config: {agent_config}") + ``` + +3. **Implement `configure_tools`**: + This abstract method is crucial. It receives a list of CrewAI `BaseTool` instances. Your implementation must convert or adapt these tools into the format expected by your external agent framework. This might involve wrapping them, extracting specific attributes, or registering them with the external agent instance. + + ```python + def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None: + if tools: + adapted_tools = [] + for tool in tools: + # Adapt CrewAI BaseTool to the format your agent expects + # Example: adapted_tool = adapt_to_my_framework(tool) + # adapted_tools.append(adapted_tool) + pass # Replace with your actual adaptation logic + + # Configure the external agent with the adapted tools + # Example: self.external_agent.set_tools(adapted_tools) + print(f"Configuring tools for MyCustomAgentAdapter: {adapted_tools}") # Placeholder + else: + # Handle the case where no tools are provided + # Example: self.external_agent.set_tools([]) + print("No tools provided for MyCustomAgentAdapter.") + ``` + +4. **Implement `configure_structured_output`**: + This method is called when the CrewAI `Agent` is configured with structured output requirements (e.g., `output_json` or `output_pydantic`). Your adapter needs to ensure the external agent is set up to comply with these requirements. This might involve setting specific parameters on the external agent or ensuring its underlying model supports the requested format. If the external agent doesn't support structured output in a way compatible with CrewAI's expectations, you might need to handle the conversion or raise an appropriate error. + + ```python + def configure_structured_output(self, structured_output: Any) -> None: + # Configure your external agent to produce output in the specified format + # Example: self.external_agent.set_output_format(structured_output) + self.adapted_structured_output = True # Signal that structured output is handled + print(f"Configuring structured output for MyCustomAgentAdapter: {structured_output}") + ``` + +By implementing these methods, your `MyCustomAgentAdapter` will allow your custom agent implementation to function correctly within a CrewAI crew, interacting with tasks and tools seamlessly. Remember to replace the example comments and print statements with your actual adaptation logic specific to the external agent framework you are integrating. + +## BaseToolAdapter implementation +The `BaseToolAdapter` class is responsible for converting CrewAI's native `BaseTool` objects into a format that your specific external agent framework can understand and utilize. Different agent frameworks (like LangGraph, OpenAI Assistants, etc.) have their own unique ways of defining and handling tools, and the `BaseToolAdapter` acts as the translator. + +Here's how you implement your custom tool adapter: + +1. **Inherit from `BaseToolAdapter`**: + ```python + from crewai.agents.agent_adapters.base_tool_adapter import BaseToolAdapter + from crewai.tools import BaseTool + from typing import List, Any + + class MyCustomToolAdapter(BaseToolAdapter): + # ... implementation details ... + ``` + +2. **Implement `configure_tools`**: + This is the core abstract method you must implement. It receives a list of CrewAI `BaseTool` instances provided to the agent. Your task is to iterate through this list, adapt each `BaseTool` into the format expected by your external framework, and store the converted tools in the `self.converted_tools` list (which is initialized in the base class constructor). + + ```python + def configure_tools(self, tools: List[BaseTool]) -> None: + """Configure and convert CrewAI tools for the specific implementation.""" + self.converted_tools = [] # Reset in case it's called multiple times + for tool in tools: + # Sanitize the tool name if required by the target framework + sanitized_name = self.sanitize_tool_name(tool.name) + + # --- Your Conversion Logic Goes Here --- + # Example: Convert BaseTool to a dictionary format for LangGraph + # converted_tool = { + # "name": sanitized_name, + # "description": tool.description, + # "parameters": tool.args_schema.schema() if tool.args_schema else {}, + # # Add any other framework-specific fields + # } + + # Example: Convert BaseTool to an OpenAI function definition + # converted_tool = { + # "type": "function", + # "function": { + # "name": sanitized_name, + # "description": tool.description, + # "parameters": tool.args_schema.schema() if tool.args_schema else {"type": "object", "properties": {}}, + # } + # } + + # --- Replace above examples with your actual adaptation --- + converted_tool = self.adapt_tool_to_my_framework(tool, sanitized_name) # Placeholder + + self.converted_tools.append(converted_tool) + print(f"Adapted tool '{tool.name}' to '{sanitized_name}' for MyCustomToolAdapter") # Placeholder + + print(f"MyCustomToolAdapter finished configuring tools: {len(self.converted_tools)} adapted.") # Placeholder + + # --- Helper method for adaptation (Example) --- + def adapt_tool_to_my_framework(self, tool: BaseTool, sanitized_name: str) -> Any: + # Replace this with the actual logic to convert a CrewAI BaseTool + # to the format needed by your specific external agent framework. + # This will vary greatly depending on the target framework. + adapted_representation = { + "framework_specific_name": sanitized_name, + "framework_specific_description": tool.description, + "inputs": tool.args_schema.schema() if tool.args_schema else None, + "implementation_reference": tool.run # Or however the framework needs to call it + } + # Also ensure the tool works both sync and async + async def async_tool_wrapper(*args, **kwargs): + output = tool.run(*args, **kwargs) + if inspect.isawaitable(output): + return await output + else: + return output + + adapted_tool = MyFrameworkTool( + name=sanitized_name, + description=tool.description, + inputs=tool.args_schema.schema() if tool.args_schema else None, + implementation_reference=async_tool_wrapper + ) + + return adapted_representation + + ``` + +3. **Using the Adapter**: + Typically, you would instantiate your `MyCustomToolAdapter` within your `MyCustomAgentAdapter`'s `configure_tools` method and use it to process the tools before configuring your external agent. + + ```python + # Inside MyCustomAgentAdapter.configure_tools + def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None: + if tools: + tool_adapter = MyCustomToolAdapter() # Instantiate your tool adapter + tool_adapter.configure_tools(tools) # Convert the tools + adapted_tools = tool_adapter.tools() # Get the converted tools + + # Now configure your external agent with the adapted_tools + # Example: self.external_agent.set_tools(adapted_tools) + print(f"Configuring external agent with adapted tools: {adapted_tools}") # Placeholder + else: + # Handle no tools case + print("No tools provided for MyCustomAgentAdapter.") + ``` + +By creating a `BaseToolAdapter`, you decouple the tool conversion logic from the agent adaptation, making the integration cleaner and more modular. Remember to replace the placeholder examples with the actual conversion logic required by your specific external agent framework. + +## BaseConverter +The `BaseConverterAdapter` plays a crucial role when a CrewAI `Task` requires an agent to return its final output in a specific structured format, such as JSON or a Pydantic model. It bridges the gap between CrewAI's structured output requirements and the capabilities of your external agent. + +Its primary responsibilities are: +1. **Configuring the Agent for Structured Output:** Based on the `Task`'s requirements (`output_json` or `output_pydantic`), it instructs the associated `BaseAgentAdapter` (and indirectly, the external agent) on what format is expected. +2. **Enhancing the System Prompt:** It modifies the agent's system prompt to include clear instructions on *how* to generate the output in the required structure. +3. **Post-processing the Result:** It takes the raw output from the agent and attempts to parse, validate, and format it according to the required structure, ultimately returning a string representation (e.g., a JSON string). + +Here's how you implement your custom converter adapter: + +1. **Inherit from `BaseConverterAdapter`**: + ```python + from crewai.agents.agent_adapters.base_converter_adapter import BaseConverterAdapter + # Assuming you have your MyCustomAgentAdapter defined + # from .my_custom_agent_adapter import MyCustomAgentAdapter + from crewai.task import Task + from typing import Any + + class MyCustomConverterAdapter(BaseConverterAdapter): + # Store the expected output type (e.g., 'json', 'pydantic', 'text') + _output_type: str = 'text' + _output_schema: Any = None # Store JSON schema or Pydantic model + + # ... implementation details ... + ``` + +2. **Implement `__init__`**: + The constructor must accept the corresponding `agent_adapter` instance it will work with. + + ```python + def __init__(self, agent_adapter: Any): # Use your specific AgentAdapter type hint + self.agent_adapter = agent_adapter + print(f"Initializing MyCustomConverterAdapter for agent adapter: {type(agent_adapter).__name__}") + ``` + +3. **Implement `configure_structured_output`**: + This method receives the CrewAI `Task` object. You need to check the task's `output_json` and `output_pydantic` attributes to determine the required output structure. Store this information (e.g., in `_output_type` and `_output_schema`) and potentially call configuration methods on your `self.agent_adapter` if the external agent needs specific setup for structured output (which might have been partially handled in the agent adapter's `configure_structured_output` already). + + ```python + def configure_structured_output(self, task: Task) -> None: + """Configure the expected structured output based on the task.""" + if task.output_pydantic: + self._output_type = 'pydantic' + self._output_schema = task.output_pydantic + print(f"Converter: Configured for Pydantic output: {self._output_schema.__name__}") + elif task.output_json: + self._output_type = 'json' + self._output_schema = task.output_json + print(f"Converter: Configured for JSON output with schema: {self._output_schema}") + else: + self._output_type = 'text' + self._output_schema = None + print("Converter: Configured for standard text output.") + + # Optionally, inform the agent adapter if needed + # self.agent_adapter.set_output_mode(self._output_type, self._output_schema) + ``` + +4. **Implement `enhance_system_prompt`**: + This method takes the agent's base system prompt string and should append instructions tailored to the currently configured `_output_type` and `_output_schema`. The goal is to guide the LLM powering the agent to produce output in the correct format. + + ```python + def enhance_system_prompt(self, base_prompt: str) -> str: + """Enhance the system prompt with structured output instructions.""" + if self._output_type == 'text': + return base_prompt # No enhancement needed for plain text + + instructions = "\n\nYour final answer MUST be formatted as " + if self._output_type == 'json': + schema_str = json.dumps(self._output_schema, indent=2) + instructions += f"a JSON object conforming to the following schema:\n```json\n{schema_str}\n```" + elif self._output_type == 'pydantic': + schema_str = json.dumps(self._output_schema.model_json_schema(), indent=2) + instructions += f"a JSON object conforming to the Pydantic model '{self._output_schema.__name__}' with the following schema:\n```json\n{schema_str}\n```" + + instructions += "\nEnsure your entire response is ONLY the valid JSON object, without any introductory text, explanations, or concluding remarks." + + print(f"Converter: Enhancing prompt for {self._output_type} output.") + return base_prompt + instructions + ``` + *Note: The exact prompt engineering might need tuning based on the agent/LLM being used.* + +5. **Implement `post_process_result`**: + This method receives the raw string output from the agent. If structured output was requested (`json` or `pydantic`), you should attempt to parse the string into the expected format. Handle potential parsing errors (e.g., log them, attempt simple fixes, or raise an exception). Crucially, the method must **always return a string**, even if the intermediate format was a dictionary or Pydantic object (e.g., by serializing it back to a JSON string). + + ```python + import json + from pydantic import ValidationError + + def post_process_result(self, result: str) -> str: + """Post-process the agent's result to ensure it matches the expected format.""" + print(f"Converter: Post-processing result for {self._output_type} output.") + if self._output_type == 'json': + try: + # Attempt to parse and re-serialize to ensure validity and consistent format + parsed_json = json.loads(result) + # Optional: Validate against self._output_schema if it's a JSON schema dictionary + # from jsonschema import validate + # validate(instance=parsed_json, schema=self._output_schema) + return json.dumps(parsed_json) + except json.JSONDecodeError as e: + print(f"Error: Failed to parse JSON output: {e}\nRaw output:\n{result}") + # Handle error: return raw, raise exception, or try to fix + return result # Example: return raw output on failure + # except Exception as e: # Catch validation errors if using jsonschema + # print(f"Error: JSON output failed schema validation: {e}\nRaw output:\n{result}") + # return result + elif self._output_type == 'pydantic': + try: + # Attempt to parse into the Pydantic model + model_instance = self._output_schema.model_validate_json(result) + # Return the model serialized back to JSON + return model_instance.model_dump_json() + except ValidationError as e: + print(f"Error: Failed to validate Pydantic output: {e}\nRaw output:\n{result}") + # Handle error + return result # Example: return raw output on failure + except json.JSONDecodeError as e: + print(f"Error: Failed to parse JSON for Pydantic model: {e}\nRaw output:\n{result}") + return result + else: # 'text' + return result # No processing needed for plain text + ``` + +By implementing these methods, your `MyCustomConverterAdapter` ensures that structured output requests from CrewAI tasks are correctly handled by your integrated external agent, improving the reliability and usability of your custom agent within the CrewAI framework. + +## Out of the Box Adapters + +We provide out of the box adapters for the following frameworks: +1. LangGraph +2. OpenAI Agents + +## Kicking off a crew with adapted agents: + +```python +import json +import os +from typing import List + +from crewai_tools import SerperDevTool +from src.crewai import Agent, Crew, Task +from langchain_openai import ChatOpenAI +from pydantic import BaseModel + +from crewai.agents.agent_adapters.langgraph.langgraph_adapter import ( + LangGraphAgentAdapter, +) +from crewai.agents.agent_adapters.openai_agents.openai_adapter import OpenAIAgentAdapter + +# CrewAI Agent +code_helper_agent = Agent( + role="Code Helper", + goal="Help users solve coding problems effectively and provide clear explanations.", + backstory="You are an experienced programmer with deep knowledge across multiple programming languages and frameworks. You specialize in solving complex coding challenges and explaining solutions clearly.", + allow_delegation=False, + verbose=True, +) +# OpenAI Agent Adapter +link_finder_agent = OpenAIAgentAdapter( + role="Link Finder", + goal="Find the most relevant and high-quality resources for coding tasks.", + backstory="You are a research specialist with a talent for finding the most helpful resources. You're skilled at using search tools to discover documentation, tutorials, and examples that directly address the user's coding needs.", + tools=[SerperDevTool()], + allow_delegation=False, + verbose=True, +) + +# LangGraph Agent Adapter +reporter_agent = LangGraphAgentAdapter( + role="Reporter", + goal="Report the results of the tasks.", + backstory="You are a reporter who reports the results of the other tasks", + llm=ChatOpenAI(model="gpt-4o"), + allow_delegation=True, + verbose=True, +) + + +class Code(BaseModel): + code: str + + +task = Task( + description="Give an answer to the coding question: {task}", + expected_output="A thorough answer to the coding question: {task}", + agent=code_helper_agent, + output_json=Code, +) +task2 = Task( + description="Find links to resources that can help with coding tasks. Use the serper tool to find resources that can help.", + expected_output="A list of links to resources that can help with coding tasks", + agent=link_finder_agent, +) + + +class Report(BaseModel): + code: str + links: List[str] + + +task3 = Task( + description="Report the results of the tasks.", + expected_output="A report of the results of the tasks. this is the code produced and then the links to the resources that can help with the coding task.", + agent=reporter_agent, + output_json=Report, +) +# Use in CrewAI +crew = Crew( + agents=[code_helper_agent, link_finder_agent, reporter_agent], + tasks=[task, task2, task3], + verbose=True, +) + +result = crew.kickoff( + inputs={"task": "How do you implement an abstract class in python?"} +) + +# Print raw result first +print("Raw result:", result) + +# Handle result based on its type +if hasattr(result, "json_dict") and result.json_dict: + json_result = result.json_dict + print("\nStructured JSON result:") + print(f"{json.dumps(json_result, indent=2)}") + + # Access fields safely + if isinstance(json_result, dict): + if "code" in json_result: + print("\nCode:") + print( + json_result["code"][:200] + "..." + if len(json_result["code"]) > 200 + else json_result["code"] + ) + + if "links" in json_result: + print("\nLinks:") + for link in json_result["links"][:5]: # Print first 5 links + print(f"- {link}") + if len(json_result["links"]) > 5: + print(f"...and {len(json_result['links']) - 5} more links") +elif hasattr(result, "pydantic") and result.pydantic: + print("\nPydantic model result:") + print(result.pydantic.model_dump_json(indent=2)) +else: + # Fallback to raw output + print("\nNo structured result available, using raw output:") + print(result.raw[:500] + "..." if len(result.raw) > 500 else result.raw) + +``` \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/coding-agents.mdx b/docs/v1.15.13/en/learn/coding-agents.mdx new file mode 100644 index 0000000000..3bf454ac48 --- /dev/null +++ b/docs/v1.15.13/en/learn/coding-agents.mdx @@ -0,0 +1,96 @@ +--- +title: Coding Agents +description: Learn how to enable your CrewAI Agents to write and execute code, and explore advanced features for enhanced functionality. +icon: rectangle-code +mode: "wide" +--- + +## Introduction + +CrewAI Agents now have the powerful ability to write and execute code, significantly enhancing their problem-solving capabilities. This feature is particularly useful for tasks that require computational or programmatic solutions. + +## Enabling Code Execution + +To enable code execution for an agent, set the `allow_code_execution` parameter to `True` when creating the agent. + +Here's an example: + +```python Code +from crewai import Agent + +coding_agent = Agent( + role="Senior Python Developer", + goal="Craft well-designed and thought-out code", + backstory="You are a senior Python developer with extensive experience in software architecture and best practices.", + allow_code_execution=True +) +``` + + +Note that `allow_code_execution` parameter defaults to `False`. + + +## Important Considerations + +1. **Model Selection**: It is strongly recommended to use more capable models like Claude 3.5 Sonnet and GPT-4 when enabling code execution. +These models have a better understanding of programming concepts and are more likely to generate correct and efficient code. + +2. **Error Handling**: The code execution feature includes error handling. If executed code raises an exception, the agent will receive the error message and can attempt to correct the code or +provide alternative solutions. The `max_retry_limit` parameter, which defaults to 2, controls the maximum number of retries for a task. + +3. **Dependencies**: To use the code execution feature, you need to install the `crewai_tools` package. If not installed, the agent will log an info message: +"Coding tools not available. Install crewai_tools." + +## Code Execution Process + +When an agent with code execution enabled encounters a task requiring programming: + + + + The agent analyzes the task and determines that code execution is necessary. + + + It formulates the Python code needed to solve the problem. + + + The code is sent to the internal code execution tool (`CodeInterpreterTool`). + + + The agent interprets the result and incorporates it into its response or uses it for further problem-solving. + + + +## Example Usage + +Here's a detailed example of creating an agent with code execution capabilities and using it in a task: + +```python Code +from crewai import Agent, Task, Crew + +# Create an agent with code execution enabled +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task that requires code execution +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants.", + agent=coding_agent +) + +# Create a crew and add the task +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +# Execute the crew +result = analysis_crew.kickoff() + +print(result) +``` + +In this example, the `coding_agent` can write and execute Python code to perform data analysis tasks. \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/conditional-tasks.mdx b/docs/v1.15.13/en/learn/conditional-tasks.mdx new file mode 100644 index 0000000000..5c7914fae2 --- /dev/null +++ b/docs/v1.15.13/en/learn/conditional-tasks.mdx @@ -0,0 +1,90 @@ +--- +title: Conditional Tasks +description: Learn how to use conditional tasks in a crewAI kickoff +icon: diagram-subtask +mode: "wide" +--- + +## Introduction + +Conditional Tasks in crewAI allow for dynamic workflow adaptation based on the outcomes of previous tasks. +This powerful feature enables crews to make decisions and execute tasks selectively, enhancing the flexibility and efficiency of your AI-driven processes. + +## Example Usage + +```python Code +from typing import List +from pydantic import BaseModel +from crewai import Agent, Crew +from crewai.tasks.conditional_task import ConditionalTask +from crewai.tasks.task_output import TaskOutput +from crewai.task import Task +from crewai_tools import SerperDevTool + +# Define a condition function for the conditional task +# If false, the task will be skipped, if true, then execute the task. +def is_data_missing(output: TaskOutput) -> bool: + return len(output.pydantic.events) < 10 # this will skip this task + +# Define the agents +data_fetcher_agent = Agent( + role="Data Fetcher", + goal="Fetch data online using Serper tool", + backstory="Backstory 1", + verbose=True, + tools=[SerperDevTool()] +) + +data_processor_agent = Agent( + role="Data Processor", + goal="Process fetched data", + backstory="Backstory 2", + verbose=True +) + +summary_generator_agent = Agent( + role="Summary Generator", + goal="Generate summary from fetched data", + backstory="Backstory 3", + verbose=True +) + +class EventOutput(BaseModel): + events: List[str] + +task1 = Task( + description="Fetch data about events in San Francisco using Serper tool", + expected_output="List of 10 things to do in SF this week", + agent=data_fetcher_agent, + output_pydantic=EventOutput, +) + +conditional_task = ConditionalTask( + description=""" + Check if data is missing. If we have less than 10 events, + fetch more events using Serper tool so that + we have a total of 10 events in SF this week.. + """, + expected_output="List of 10 Things to do in SF this week", + condition=is_data_missing, + agent=data_processor_agent, +) + +task3 = Task( + description="Generate summary of events in San Francisco from fetched data", + expected_output="A complete report on the customer and their customers and competitors, including their demographics, preferences, market positioning and audience engagement.", + agent=summary_generator_agent, +) + +# Create a crew with the tasks +crew = Crew( + agents=[data_fetcher_agent, data_processor_agent, summary_generator_agent], + tasks=[task1, conditional_task, task3], + verbose=True, + planning=True +) + +# Run the crew +result = crew.kickoff() +print("results", result) +``` \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/consuming-streams.mdx b/docs/v1.15.13/en/learn/consuming-streams.mdx new file mode 100644 index 0000000000..6ece26f3a1 --- /dev/null +++ b/docs/v1.15.13/en/learn/consuming-streams.mdx @@ -0,0 +1,177 @@ +--- +title: Consuming Streams +description: Print LLM chunks, observe tool events, and read final results from CrewAI streams. +icon: square-terminal +mode: "wide" +--- + +## Overview + +Use this guide when you want to subscribe to a CrewAI stream and print or route frames as they arrive. + +The basic pattern is: + +```python +stream = flow.stream_events(inputs={"topic": "AI agents"}) + +with stream: + for frame in stream: + ... + +result = stream.result +``` + +Always consume the stream before reading `stream.result`. + +## Print LLM Output + +If you only care about text generated by LLM calls, subscribe to the `llm` projection and print `frame.content`: + +```python +stream = flow.stream_events(inputs={"topic": "AI agents"}) + +with stream: + for frame in stream.llm: + print(frame.content, end="", flush=True) + +print() +result = stream.result +``` + +`frame.content` is an empty string for frames that do not carry printable text, so this is also safe: + +```python +with flow.stream_events(inputs={"topic": "AI agents"}) as stream: + for frame in stream.events: + if frame.channel == "llm" and frame.content: + print(frame.content, end="", flush=True) + +result = stream.result +``` + +## Print Tool Activity + +Tool events arrive on the `tools` channel. Use `frame.type` to distinguish starts, finishes, and errors. + +```python +with flow.stream_events(inputs={"topic": "AI agents"}) as stream: + for frame in stream.events: + if frame.channel == "llm" and frame.content: + print(frame.content, end="", flush=True) + + if frame.channel == "tools" and frame.type == "tool_usage_started": + print(f"\nTool started: {frame.event.get('tool_name')}") + + if frame.channel == "tools" and frame.type == "tool_usage_finished": + print(f"\nTool finished: {frame.event.get('tool_name')}") + +result = stream.result +``` + +`frame.event` is the structured payload for the source event. Use it for metadata such as tool names, arguments, message roles, and runtime identifiers. + +## Watch Flow Progress + +Flow lifecycle and method execution frames arrive on the `flow` channel: + +```python +with flow.stream_events(inputs={"topic": "AI agents"}) as stream: + for frame in stream.flow: + print(frame.type, frame.namespace) + +result = stream.result +``` + +Use this when you want a progress log instead of token-level output. + +## Interleave Selected Channels + +Use `interleave()` when you want a subset of channels while preserving their relative order: + +```python +with flow.stream_events(inputs={"topic": "AI agents"}) as stream: + for frame in stream.interleave(["llm", "tools"]): + if frame.channel == "llm": + print(frame.content, end="", flush=True) + elif frame.type == "tool_usage_started": + print(f"\nTool: {frame.event.get('tool_name')}") + +result = stream.result +``` + +## Stream a Direct LLM Call + +Direct `llm.call(...)` returns the final assembled result. To stream a direct LLM call, use `llm.stream_events(...)`: + +```python +from crewai import LLM + + +llm = LLM(model="gpt-4o-mini") +stream = llm.stream_events("Explain streaming in one sentence.") + +with stream: + for frame in stream.llm: + print(frame.content, end="", flush=True) + +print() +result = stream.result +``` + +## Stream a Conversational Turn + +Conversational Flows expose `stream_turn()` for one user message: + +```python +stream = flow.stream_turn( + "What can you help me with?", + session_id="session-1", +) + +with stream: + for frame in stream.interleave(["llm", "messages"]): + if frame.channel == "llm": + print(frame.content, end="", flush=True) + elif frame.channel == "messages": + print(f"\n{frame.event.get('role')}: {frame.event.get('content')}") + +reply = stream.result +``` + +## Async Consumers + +Async streams use the same channel projections: + +```python +stream = flow.astream(inputs={"topic": "AI agents"}) + +async with stream: + async for frame in stream.llm: + print(frame.content, end="", flush=True) + +result = stream.result +``` + +## Cleanup + +Use the stream as a context manager when possible. If a client disconnects or you stop consuming early, close the stream: + +```python +stream = flow.stream_events(inputs={"topic": "AI agents"}) + +try: + for frame in stream.events: + print(frame.content, end="", flush=True) +finally: + if not stream.is_exhausted: + stream.close() +``` + +For async streams, call `await stream.aclose()`. + +## See Also + +- [Streaming](/edge/en/concepts/streaming) +- [Streaming Runtime Contract](/edge/en/learn/streaming-runtime-contract) +- [Streaming Flow Execution](/edge/en/learn/streaming-flow-execution) +- [Streaming Crew Execution](/edge/en/learn/streaming-crew-execution) diff --git a/docs/v1.15.13/en/learn/create-custom-tools.mdx b/docs/v1.15.13/en/learn/create-custom-tools.mdx new file mode 100644 index 0000000000..78205bf994 --- /dev/null +++ b/docs/v1.15.13/en/learn/create-custom-tools.mdx @@ -0,0 +1,229 @@ +--- +title: Create Custom Tools +description: Comprehensive guide on crafting, using, and managing custom tools within the CrewAI framework, including new functionalities and error handling. +icon: hammer +mode: "wide" +--- + +## Creating and Utilizing Tools in CrewAI + +This guide provides detailed instructions on creating custom tools for the CrewAI framework and how to efficiently manage and utilize these tools, +incorporating the latest functionalities such as tool delegation, error handling, and dynamic tool calling. It also highlights the importance of collaboration tools, +enabling agents to perform a wide range of actions. + + + **Want to publish your tool for the community?** If you're building a tool that others could benefit from, check out the [Publish Custom Tools](/en/guides/tools/publish-custom-tools) guide to learn how to package and distribute your tool on PyPI. + + +### Subclassing `BaseTool` + +To create a personalized tool, inherit from `BaseTool` and define the necessary attributes, including the `args_schema` for input validation, and the `_run` method. + +```python Code +from typing import Type +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class MyToolInput(BaseModel): + """Input schema for MyCustomTool.""" + argument: str = Field(..., description="Description of the argument.") + +class MyCustomTool(BaseTool): + name: str = "Name of my tool" + description: str = "What this tool does. It's vital for effective utilization." + args_schema: Type[BaseModel] = MyToolInput + + def _run(self, argument: str) -> str: + # Your tool's logic here + return "Tool's result" +``` + +### Using the `tool` Decorator + +Alternatively, you can use the tool decorator `@tool`. This approach allows you to define the tool's attributes and functionality directly within a function, +offering a concise and efficient way to create specialized tools tailored to your needs. + +```python Code +from crewai.tools import tool + +@tool("Tool Name") +def my_simple_tool(question: str) -> str: + """Tool description for clarity.""" + # Tool logic here + return "Tool output" +``` + +### Best Practice: Define Typed Outputs + +When a tool returns structured data, define a Pydantic output model. This helps the agent read the result as clear fields instead of guessing from plain text. + +Typed outputs are useful for results with stable fields, such as IDs, status values, scores, prices, or lists. Plain strings are still fine for short prose results. + +Direct Python calls still receive the value your tool returns. When an agent uses a typed tool, CrewAI sends the agent JSON based on the output model. + +#### Return a Pydantic Model + +CrewAI infers the output schema when your `BaseTool` has a Pydantic return annotation. + +```python Code +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class InventoryResult(BaseModel): + sku: str = Field(description="The product SKU.") + quantity: int = Field(description="Units available.") + needs_reorder: bool = Field(description="Whether the item should be reordered.") + +class InventoryTool(BaseTool): + name: str = "Inventory Check" + description: str = "Check current stock for a product SKU." + + def _run(self, sku: str) -> InventoryResult: + quantity = {"SKU-123": 14, "SKU-456": 0}.get(sku, 0) + return InventoryResult(sku=sku, quantity=quantity, needs_reorder=quantity < 5) + +tool = InventoryTool() +result = tool.run(sku="SKU-123") + +# Direct Python calls receive the raw Pydantic object. +print(result.quantity) +``` + +When an agent calls `InventoryTool`, it receives JSON like this: + +```json +{"sku":"SKU-123","quantity":14,"needs_reorder":false} +``` + +#### Use `result_schema` with Dictionary Results + +If your tool returns a dictionary, set `result_schema` explicitly. You can do this on a `BaseTool` subclass or with the `@tool` decorator: + +```python Code +from crewai.tools import tool +from pydantic import BaseModel, Field + +class ProductResult(BaseModel): + sku: str = Field(description="The product SKU.") + name: str = Field(description="The product name.") + in_stock: bool = Field(description="Whether the product is available.") + +@tool("Product Lookup", result_schema=ProductResult) +def product_lookup(sku: str) -> dict[str, object]: + """Look up product availability by SKU.""" + catalog = { + "SKU-123": ("Noise-canceling headset", True), + "SKU-456": ("USB-C dock", False), + } + name, in_stock = catalog.get(sku, ("Unknown product", False)) + return { + "sku": sku, + "name": name, + "in_stock": in_stock, + } +``` + +#### Customize the Text Sent to the Agent + +By default, typed tool outputs are sent to the agent as JSON. If the agent should receive a short summary instead, subclass `BaseTool` and override `format_output_for_agent`. + +```python Code +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class InventoryResult(BaseModel): + sku: str = Field(description="The product SKU.") + quantity: int = Field(description="Units available.") + needs_reorder: bool = Field(description="Whether the item should be reordered.") + +class InventoryTool(BaseTool): + name: str = "Inventory Check" + description: str = "Check current stock for a product SKU." + + def _run(self, sku: str) -> InventoryResult: + quantity = {"SKU-123": 14, "SKU-456": 0}.get(sku, 0) + return InventoryResult(sku=sku, quantity=quantity, needs_reorder=quantity < 5) + + def format_output_for_agent(self, raw_result: object) -> str: + result = InventoryResult.model_validate(raw_result) + status = "reorder needed" if result.needs_reorder else "stock is healthy" + return f"{result.sku}: {result.quantity} units. {status}." + +tool = InventoryTool() +result = tool.run(sku="SKU-123") + +# Direct Python calls receive the raw Pydantic object. +print(result.quantity) +``` + +The override only changes what the agent sees. Direct calls to `tool.run(...)` still return the normal Python value. + +### Defining a Cache Function for the Tool + +To optimize tool performance with caching, define custom caching strategies using the `cache_function` attribute. + +```python Code +@tool("Tool with Caching") +def cached_tool(argument: str) -> str: + """Tool functionality description.""" + return "Cacheable result" + +def my_cache_strategy(arguments: dict, result: str) -> bool: + # Define custom caching logic + return True if some_condition else False + +cached_tool.cache_function = my_cache_strategy +``` + +### Creating Async Tools + +CrewAI supports async tools for non-blocking I/O operations. This is useful when your tool needs to make HTTP requests, database queries, or other I/O-bound operations. + +#### Using the `@tool` Decorator with Async Functions + +The simplest way to create an async tool is using the `@tool` decorator with an async function: + +```python Code +import aiohttp +from crewai.tools import tool + +@tool("Async Web Fetcher") +async def fetch_webpage(url: str) -> str: + """Fetch content from a webpage asynchronously.""" + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.text() +``` + +#### Subclassing `BaseTool` with Async Support + +For more control, subclass `BaseTool` and implement both `_run` (sync) and `_arun` (async) methods: + +```python Code +import requests +import aiohttp +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class WebFetcherInput(BaseModel): + """Input schema for WebFetcher.""" + url: str = Field(..., description="The URL to fetch") + +class WebFetcherTool(BaseTool): + name: str = "Web Fetcher" + description: str = "Fetches content from a URL" + args_schema: type[BaseModel] = WebFetcherInput + + def _run(self, url: str) -> str: + """Synchronous implementation.""" + return requests.get(url).text + + async def _arun(self, url: str) -> str: + """Asynchronous implementation for non-blocking I/O.""" + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.text() +``` + +By adhering to these guidelines and incorporating new functionalities and collaboration tools into your tool creation and management processes, +you can leverage the full capabilities of the CrewAI framework, enhancing both the development experience and the efficiency of your AI agents. diff --git a/docs/v1.15.13/en/learn/custom-llm.mdx b/docs/v1.15.13/en/learn/custom-llm.mdx new file mode 100644 index 0000000000..0eee2387a9 --- /dev/null +++ b/docs/v1.15.13/en/learn/custom-llm.mdx @@ -0,0 +1,351 @@ +--- +title: Custom LLM Implementation +description: Learn how to create custom LLM implementations in CrewAI. +icon: code +mode: "wide" +--- + +## Overview + +CrewAI supports custom LLM implementations through the `BaseLLM` abstract base class. This allows you to integrate any LLM provider that doesn't have built-in support in LiteLLM, or implement custom authentication mechanisms. + +## Quick Start + +Here's a minimal custom LLM implementation: + +```python +from crewai import BaseLLM +from typing import Any, Dict, List, Optional, Union +import requests + +class CustomLLM(BaseLLM): + def __init__(self, model: str, api_key: str, endpoint: str, temperature: Optional[float] = None): + # IMPORTANT: Call super().__init__() with required parameters + super().__init__(model=model, temperature=temperature) + + self.api_key = api_key + self.endpoint = endpoint + + def call( + self, + messages: Union[str, List[Dict[str, str]]], + tools: Optional[List[dict]] = None, + callbacks: Optional[List[Any]] = None, + available_functions: Optional[Dict[str, Any]] = None, + ) -> Union[str, Any]: + """Call the LLM with the given messages.""" + # Convert string to message format if needed + if isinstance(messages, str): + messages = [{"role": "user", "content": messages}] + + # Prepare request + payload = { + "model": self.model, + "messages": messages, + "temperature": self.temperature, + } + + # Add tools if provided and supported + if tools and self.supports_function_calling(): + payload["tools"] = tools + + # Make API call + response = requests.post( + self.endpoint, + headers={ + "Authorization": f"Bearer {self.api_key}", + "Content-Type": "application/json" + }, + json=payload, + timeout=30 + ) + response.raise_for_status() + + result = response.json() + return result["choices"][0]["message"]["content"] + + def supports_function_calling(self) -> bool: + """Override if your LLM supports function calling.""" + return True # Change to False if your LLM doesn't support tools + + def get_context_window_size(self) -> int: + """Return the context window size of your LLM.""" + return 8192 # Adjust based on your model's actual context window +``` + +## Using Your Custom LLM + +```python +from crewai import Agent, Task, Crew + +# Assuming you have the CustomLLM class defined above +# Create your custom LLM +custom_llm = CustomLLM( + model="my-custom-model", + api_key="your-api-key", + endpoint="https://api.example.com/v1/chat/completions", + temperature=0.7 +) + +# Use with an agent +agent = Agent( + role="Research Assistant", + goal="Find and analyze information", + backstory="You are a research assistant.", + llm=custom_llm +) + +# Create and execute tasks +task = Task( + description="Research the latest developments in AI", + expected_output="A comprehensive summary", + agent=agent +) + +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() +``` + +## Required Methods + +### Constructor: `__init__()` + +**Critical**: You must call `super().__init__(model, temperature)` with the required parameters: + +```python +def __init__(self, model: str, api_key: str, temperature: Optional[float] = None): + # REQUIRED: Call parent constructor with model and temperature + super().__init__(model=model, temperature=temperature) + + # Your custom initialization + self.api_key = api_key +``` + +### Abstract Method: `call()` + +The `call()` method is the heart of your LLM implementation. It must: + +- Accept messages (string or list of dicts with 'role' and 'content') +- Return a string response +- Handle tools and function calling if supported +- Raise appropriate exceptions for errors + +### Optional Methods + +```python +def supports_function_calling(self) -> bool: + """Return True if your LLM supports function calling.""" + return True # Default is True + +def supports_stop_words(self) -> bool: + """Return True if your LLM supports stop sequences.""" + return True # Default is True + +def get_context_window_size(self) -> int: + """Return the context window size.""" + return 4096 # Default is 4096 +``` + +## Common Patterns + +### Error Handling + +```python +import requests + +def call(self, messages, tools=None, callbacks=None, available_functions=None): + try: + response = requests.post( + self.endpoint, + headers={"Authorization": f"Bearer {self.api_key}"}, + json=payload, + timeout=30 + ) + response.raise_for_status() + return response.json()["choices"][0]["message"]["content"] + + except requests.Timeout: + raise TimeoutError("LLM request timed out") + except requests.RequestException as e: + raise RuntimeError(f"LLM request failed: {str(e)}") + except (KeyError, IndexError) as e: + raise ValueError(f"Invalid response format: {str(e)}") +``` + +### Custom Authentication + +```python +from crewai import BaseLLM +from typing import Optional + +class CustomAuthLLM(BaseLLM): + def __init__(self, model: str, auth_token: str, endpoint: str, temperature: Optional[float] = None): + super().__init__(model=model, temperature=temperature) + self.auth_token = auth_token + self.endpoint = endpoint + + def call(self, messages, tools=None, callbacks=None, available_functions=None): + headers = { + "Authorization": f"Custom {self.auth_token}", # Custom auth format + "Content-Type": "application/json" + } + # Rest of implementation... +``` + +### Stop Words Support + +CrewAI automatically adds `"\nObservation:"` as a stop word to control agent behavior. If your LLM supports stop words: + +```python +def call(self, messages, tools=None, callbacks=None, available_functions=None): + payload = { + "model": self.model, + "messages": messages, + "stop": self.stop # Include stop words in API call + } + # Make API call... + +def supports_stop_words(self) -> bool: + return True # Your LLM supports stop sequences +``` + +If your LLM doesn't support stop words natively: + +```python +def call(self, messages, tools=None, callbacks=None, available_functions=None): + response = self._make_api_call(messages, tools) + content = response["choices"][0]["message"]["content"] + + # Manually truncate at stop words + if self.stop: + for stop_word in self.stop: + if stop_word in content: + content = content.split(stop_word)[0] + break + + return content + +def supports_stop_words(self) -> bool: + return False # Tell CrewAI we handle stop words manually +``` + +## Function Calling + +If your LLM supports function calling, implement the complete flow: + +```python +import json + +def call(self, messages, tools=None, callbacks=None, available_functions=None): + # Convert string to message format + if isinstance(messages, str): + messages = [{"role": "user", "content": messages}] + + # Make API call + response = self._make_api_call(messages, tools) + message = response["choices"][0]["message"] + + # Check for function calls + if "tool_calls" in message and available_functions: + return self._handle_function_calls( + message["tool_calls"], messages, tools, available_functions + ) + + return message["content"] + +def _handle_function_calls(self, tool_calls, messages, tools, available_functions): + """Handle function calling with proper message flow.""" + for tool_call in tool_calls: + function_name = tool_call["function"]["name"] + + if function_name in available_functions: + # Parse and execute function + function_args = json.loads(tool_call["function"]["arguments"]) + function_result = available_functions[function_name](**function_args) + + # Add function call and result to message history + messages.append({ + "role": "assistant", + "content": None, + "tool_calls": [tool_call] + }) + messages.append({ + "role": "tool", + "tool_call_id": tool_call["id"], + "name": function_name, + "content": str(function_result) + }) + + # Call LLM again with updated context + return self.call(messages, tools, None, available_functions) + + return "Function call failed" +``` + +## Troubleshooting + +### Common Issues + +**Constructor Errors** +```python +# ❌ Wrong - missing required parameters +def __init__(self, api_key: str): + super().__init__() + +# ✅ Correct +def __init__(self, model: str, api_key: str, temperature: Optional[float] = None): + super().__init__(model=model, temperature=temperature) +``` + +**Function Calling Not Working** +- Ensure `supports_function_calling()` returns `True` +- Check that you handle `tool_calls` in the response +- Verify `available_functions` parameter is used correctly + +**Authentication Failures** +- Verify API key format and permissions +- Check authentication header format +- Ensure endpoint URLs are correct + +**Response Parsing Errors** +- Validate response structure before accessing nested fields +- Handle cases where content might be None +- Add proper error handling for malformed responses + +## Testing Your Custom LLM + +```python +from crewai import Agent, Task, Crew + +def test_custom_llm(): + llm = CustomLLM( + model="test-model", + api_key="test-key", + endpoint="https://api.test.com" + ) + + # Test basic call + result = llm.call("Hello, world!") + assert isinstance(result, str) + assert len(result) > 0 + + # Test with CrewAI agent + agent = Agent( + role="Test Agent", + goal="Test custom LLM", + backstory="A test agent.", + llm=llm + ) + + task = Task( + description="Say hello", + expected_output="A greeting", + agent=agent + ) + + crew = Crew(agents=[agent], tasks=[task]) + result = crew.kickoff() + assert "hello" in result.raw.lower() +``` + +This guide covers the essentials of implementing custom LLMs in CrewAI. diff --git a/docs/v1.15.13/en/learn/custom-manager-agent.mdx b/docs/v1.15.13/en/learn/custom-manager-agent.mdx new file mode 100644 index 0000000000..7b936da187 --- /dev/null +++ b/docs/v1.15.13/en/learn/custom-manager-agent.mdx @@ -0,0 +1,91 @@ +--- +title: Custom Manager Agent +description: Learn how to set a custom agent as the manager in CrewAI, providing more control over task management and coordination. +icon: user-shield +mode: "wide" +--- + +# Setting a Specific Agent as Manager in CrewAI + +CrewAI allows users to set a specific agent as the manager of the crew, providing more control over the management and coordination of tasks. +This feature enables the customization of the managerial role to better fit your project's requirements. + +## Using the `manager_agent` Attribute + +### Custom Manager Agent + +The `manager_agent` attribute allows you to define a custom agent to manage the crew. This agent will oversee the entire process, ensuring that tasks are completed efficiently and to the highest standard. + +### Example + +```python Code +import os +from crewai import Agent, Task, Crew, Process + +# Define your agents +researcher = Agent( + role="Researcher", + goal="Conduct thorough research and analysis on AI and AI agents", + backstory="You're an expert researcher, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently researching for a new client.", + allow_delegation=False, +) + +writer = Agent( + role="Senior Writer", + goal="Create compelling content about AI and AI agents", + backstory="You're a senior writer, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently writing content for a new client.", + allow_delegation=False, +) + +# Define your task +task = Task( + description="Generate a list of 5 interesting ideas for an article, then write one captivating paragraph for each idea that showcases the potential of a full article on this topic. Return the list of ideas with their paragraphs and your notes.", + expected_output="5 bullet points, each with a paragraph and accompanying notes.", +) + +# Define the manager agent +manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success. Your role is to coordinate the efforts of the crew members, ensuring that each task is completed on time and to the highest standard.", + allow_delegation=True, +) + +# Instantiate your crew with a custom manager +crew = Crew( + agents=[researcher, writer], + tasks=[task], + manager_agent=manager, + process=Process.hierarchical, +) + +# Start the crew's work +result = crew.kickoff() +``` + +## Benefits of a Custom Manager Agent + +- **Enhanced Control**: Tailor the management approach to fit the specific needs of your project. +- **Improved Coordination**: Ensure efficient task coordination and management by an experienced agent. +- **Customizable Management**: Define managerial roles and responsibilities that align with your project's goals. + +## Setting a Manager LLM + +If you're using the hierarchical process and don't want to set a custom manager agent, you can specify the language model for the manager: + +```python Code +from crewai import LLM + +manager_llm = LLM(model="gpt-4o") + +crew = Crew( + agents=[researcher, writer], + tasks=[task], + process=Process.hierarchical, + manager_llm=manager_llm +) +``` + + +Either `manager_agent` or `manager_llm` must be set when using the hierarchical process. + \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/customizing-agents.mdx b/docs/v1.15.13/en/learn/customizing-agents.mdx new file mode 100644 index 0000000000..8364b5637a --- /dev/null +++ b/docs/v1.15.13/en/learn/customizing-agents.mdx @@ -0,0 +1,112 @@ +--- +title: Customize Agents +description: A comprehensive guide to tailoring agents for specific roles, tasks, and advanced customizations within the CrewAI framework. +icon: user-pen +mode: "wide" +--- + +## Customizable Attributes + +Crafting an efficient CrewAI team hinges on the ability to dynamically tailor your AI agents to meet the unique requirements of any project. This section covers the foundational attributes you can customize. + +### Key Attributes for Customization + +| Attribute | Description | +|:-----------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Role** | Specifies the agent's job within the crew, such as 'Analyst' or 'Customer Service Rep'. | +| **Goal** | Defines the agent’s objectives, aligned with its role and the crew’s overarching mission. | +| **Backstory** | Provides depth to the agent's persona, enhancing motivations and engagements within the crew. | +| **Tools** *(Optional)* | Represents the capabilities or methods the agent uses for tasks, from simple functions to complex integrations. | +| **Cache** *(Optional)* | Determines if the agent should use a cache for tool usage. | +| **Max RPM** | Sets the maximum requests per minute (`max_rpm`). Can be set to `None` for unlimited requests to external services. | +| **Verbose** *(Optional)* | Enables detailed logging for debugging and optimization, providing insights into execution processes. | +| **Allow Delegation** *(Optional)* | Controls task delegation to other agents, default is `False`. | +| **Max Iter** *(Optional)* | Limits the maximum number of iterations (`max_iter`) for a task to prevent infinite loops, with a default of 25. | +| **Max Execution Time** *(Optional)* | Sets the maximum time allowed for an agent to complete a task. | +| **System Template** *(Optional)* | Defines the system format for the agent. | +| **Prompt Template** *(Optional)* | Defines the prompt format for the agent. | +| **Response Template** *(Optional)* | Defines the response format for the agent. | +| **Use System Prompt** *(Optional)* | Controls whether the agent will use a system prompt during task execution. | +| **Respect Context Window** | Enables a sliding context window by default, maintaining context size. | +| **Max Retry Limit** | Sets the maximum number of retries (`max_retry_limit`) for an agent in case of errors. | + +## Advanced Customization Options + +Beyond the basic attributes, CrewAI allows for deeper customization to enhance an agent's behavior and capabilities significantly. + +### Language Model Customization + +Agents can be customized with specific language models (`llm`) and function-calling language models (`function_calling_llm`), offering advanced control over their processing and decision-making abilities. +It's important to note that setting the `function_calling_llm` allows for overriding the default crew function-calling language model, providing a greater degree of customization. + +## Performance and Debugging Settings + +Adjusting an agent's performance and monitoring its operations are crucial for efficient task execution. + +### Verbose Mode and RPM Limit + +- **Verbose Mode**: Enables detailed logging of an agent's actions, useful for debugging and optimization. Specifically, it provides insights into agent execution processes, aiding in the optimization of performance. +- **RPM Limit**: Sets the maximum number of requests per minute (`max_rpm`). This attribute is optional and can be set to `None` for no limit, allowing for unlimited queries to external services if needed. + +### Maximum Iterations for Task Execution + +The `max_iter` attribute allows users to define the maximum number of iterations an agent can perform for a single task, preventing infinite loops or excessively long executions. +The default value is set to 25, providing a balance between thoroughness and efficiency. Once the agent approaches this number, it will try its best to give a good answer. + +## Customizing Agents and Tools + +Agents are customized by defining their attributes and tools during initialization. Tools are critical for an agent's functionality, enabling them to perform specialized tasks. +The `tools` attribute should be an array of tools the agent can utilize, and it's initialized as an empty list by default. Tools can be added or modified post-agent initialization to adapt to new requirements. + +```shell +pip install 'crewai[tools]' +``` + +### Example: Assigning Tools to an Agent + +```python Code +import os +from crewai import Agent +from crewai_tools import SerperDevTool + +# Set API keys for tool initialization +os.environ["OPENAI_API_KEY"] = "Your Key" +os.environ["SERPER_API_KEY"] = "Your Key" + +# Initialize a search tool +search_tool = SerperDevTool() + +# Initialize the agent with advanced options +agent = Agent( + role='Research Analyst', + goal='Provide up-to-date market analysis', + backstory='An expert analyst with a keen eye for market trends.', + tools=[search_tool], + memory=True, # Enable memory + verbose=True, + max_rpm=None, # No limit on requests per minute + max_iter=25, # Default value for maximum iterations +) +``` + +## Delegation and Autonomy + +Controlling an agent's ability to delegate tasks or ask questions is vital for tailoring its autonomy and collaborative dynamics within the CrewAI framework. By default, +the `allow_delegation` attribute is now set to `False`, disabling agents to seek assistance or delegate tasks as needed. This default behavior can be changed to promote collaborative problem-solving and +efficiency within the CrewAI ecosystem. If needed, delegation can be enabled to suit specific operational requirements. + +### Example: Disabling Delegation for an Agent + +```python Code +agent = Agent( + role='Content Writer', + goal='Write engaging content on market trends', + backstory='A seasoned writer with expertise in market analysis.', + allow_delegation=True # Enabling delegation +) +``` + +## Conclusion + +Customizing agents in CrewAI by setting their roles, goals, backstories, and tools, alongside advanced options like language model customization, memory, performance settings, and delegation preferences, +equips a nuanced and capable AI team ready for complex challenges. \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/dalle-image-generation.mdx b/docs/v1.15.13/en/learn/dalle-image-generation.mdx new file mode 100644 index 0000000000..a39e3d899b --- /dev/null +++ b/docs/v1.15.13/en/learn/dalle-image-generation.mdx @@ -0,0 +1,74 @@ +--- +title: "Image Generation with DALL-E" +description: "Learn how to use DALL-E for AI-powered image generation in your CrewAI projects" +icon: "image" +mode: "wide" +--- + +CrewAI supports integration with OpenAI's DALL-E, allowing your AI agents to generate images as part of their tasks. This guide will walk you through how to set up and use the DALL-E tool in your CrewAI projects. + +## Prerequisites + +- crewAI installed (latest version) +- OpenAI API key with access to DALL-E + +## Setting Up the DALL-E Tool + + + + ```python + from crewai_tools import DallETool + ``` + + + + ```python + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + tools=[SerperDevTool(), DallETool()], # Add DallETool to the list of tools + allow_delegation=False, + verbose=True + ) + ``` + + + +## Using the DALL-E Tool + +Once you've added the DALL-E tool to your agent, it can generate images based on text prompts. The tool will return a URL to the generated image, which can be used in the agent's output or passed to other agents for further processing. + +### Example Agent Configuration + +```yaml +role: > + LinkedIn Profile Senior Data Researcher +goal: > + Uncover detailed LinkedIn profiles based on provided name {name} and domain {domain} + Generate a Dall-e image based on domain {domain} +backstory: > + You're a seasoned researcher with a knack for uncovering the most relevant LinkedIn profiles. + Known for your ability to navigate LinkedIn efficiently, you excel at gathering and presenting + professional information clearly and concisely. +``` + +### Expected Output + +The agent with the DALL-E tool will be able to generate the image and provide a URL in its response. You can then download the image. + + + DALL-E Image + + +## Best Practices + +1. **Be specific in your image generation prompts** to get the best results. +2. **Consider generation time** - Image generation can take some time, so factor this into your task planning. +3. **Follow usage policies** - Always comply with OpenAI's usage policies when generating images. + +## Troubleshooting + +1. **Check API access** - Ensure your OpenAI API key has access to DALL-E. +2. **Version compatibility** - Check that you're using the latest version of crewAI and crewai-tools. +3. **Tool configuration** - Verify that the DALL-E tool is correctly added to the agent's tool list. \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/execution-boundary-hooks.mdx b/docs/v1.15.13/en/learn/execution-boundary-hooks.mdx new file mode 100644 index 0000000000..80e2b382e0 --- /dev/null +++ b/docs/v1.15.13/en/learn/execution-boundary-hooks.mdx @@ -0,0 +1,187 @@ +--- +title: Execution Boundary Hooks +description: Intercept the start, inputs, output, and end of crew and flow executions with the @on decorator +mode: "wide" +--- + +Execution boundary hooks intercept the outermost edges of a run — before any +work starts, when inputs are resolved, when the final result is ready, and when +the execution finishes. They fire for both crews and flows and are the right +place for run-level policy checks, input rewriting, and output sanitization. + +## Overview + +Four interception points cover the boundaries: + +| Point | When | `ctx.payload` | +|-------|------|---------------| +| `EXECUTION_START` | A crew or flow is about to begin | inputs `dict` | +| `INPUT` | Resolved inputs for the execution | inputs `dict` | +| `OUTPUT` | The final result is ready | the output object | +| `EXECUTION_END` | The execution has finished (success or failure) | the output object, or `None` on failure | + +For a crew, the output payload is a `CrewOutput`. For a flow, it is the final +flow-method result. + +## Hook Signature + +```python +from crewai.hooks import on, HookAborted, InterceptionPoint + +@on(InterceptionPoint.EXECUTION_START) +def boundary_hook(ctx) -> Any | None: + # Mutate ctx.payload in place, or + # return a non-None value to replace it, or + # raise HookAborted(reason, source) to stop the run + return None +``` + +Boundary hooks follow the standard contract: proceed (`return None`), mutate in +place, replace by returning, or abort by raising +[`HookAborted`](/edge/en/learn/execution-hooks#aborting-an-operation). An abort at any +boundary propagates out of `kickoff()` with its reason. + +## Context Schema + +Each point receives a typed context. All contexts share the base fields: + +```python +class InterceptionContext: + payload: Any # The interceptable value (see table above) + agent: Any = None # Not populated at execution boundaries + agent_role: str | None # Not populated at execution boundaries + task: Any = None # Not populated at execution boundaries + crew: Any = None # The Crew instance (crew runs only) + flow: Any = None # The Flow instance (flow runs only) +``` + +The per-point contexts add a named alias for the payload: + +```python +class ExecutionStartContext(InterceptionContext): + inputs: dict # Same dict as payload + +class InputContext(InterceptionContext): + inputs: dict # Same dict as payload + +class OutputContext(InterceptionContext): + output: Any # The output object + +class ExecutionEndContext(InterceptionContext): + output: Any # The output object (None when status == "failed") + status: str # "completed" or "failed" + error: BaseException | None # The exception when status == "failed" +``` + + +`ctx.inputs` aliases the **original** inputs dict, so in-place edits through +either name are equivalent. If an earlier hook *replaced* the payload by +returning a new dict, only `ctx.payload` is rebound — always read and write +`ctx.payload` when hooks might chain. + + +## Crew Runs vs. Flow Runs + +Boundary hooks fire on both runtimes, and crew execution internally rides on a +flow runtime. During a `crew.kickoff()`, a global boundary hook therefore fires +for the crew boundary (`ctx.crew` set, `ctx.flow` `None`) **and** for the +internal flow (`ctx.flow` set, `ctx.crew` `None`). Discriminate by runtime: + +```python +@on(InterceptionPoint.OUTPUT) +def crew_output_only(ctx): + if ctx.crew is None: + return None # Skip the internal flow (or a bare flow) + ctx.payload.raw = ctx.payload.raw.strip() +``` + +## Common Use Cases + +### Policy Check at Start + +```python +@on(InterceptionPoint.EXECUTION_START) +def enforce_policy(ctx): + if ctx.crew is not None and not ctx.payload.get("authorized"): + raise HookAborted(reason="unauthorized execution", source="access-control") +``` + +### Input Rewriting + +```python +@on(InterceptionPoint.INPUT) +def add_defaults(ctx): + if ctx.crew is None: + return None + ctx.payload.setdefault("locale", "en-US") + ctx.payload["topic"] = ctx.payload["topic"].strip().lower() +``` + +Rewritten inputs flow into task interpolation, so the run behaves as if it was +kicked off with the modified dict. + +### Output Sanitization + +```python +import re + +@on(InterceptionPoint.OUTPUT) +def redact_emails(ctx): + if ctx.crew is None: + return None + ctx.payload.raw = re.sub( + r"\b[\w.+-]+@[\w-]+\.[\w.]+\b", "[EMAIL-REDACTED]", ctx.payload.raw + ) +``` + +`OUTPUT` runs before `EXECUTION_END`, and both see the (possibly replaced) +payload from earlier hooks; the final rewritten value is what `kickoff()` +returns. + +### Observing Failures + +`EXECUTION_END` fires exactly once per execution, on success and on failure +alike. When the run raises — a task error, a flow-method exception, or a +`HookAborted` from an earlier point — the hook receives `status="failed"` with +the exception in `ctx.error`, and the original exception still propagates out +of `kickoff()` unchanged: + +```python +@on(InterceptionPoint.EXECUTION_END) +def report_outcome(ctx): + if ctx.status == "failed": + notify_policy_engine(status="failed", error=repr(ctx.error)) + else: + notify_policy_engine(status="completed") +``` + +Two caveats: `EXECUTION_END` does not fire when `EXECUTION_START` never +dispatched (an abort at start counts as the execution never beginning), and +raising `HookAborted` from a failure-path `EXECUTION_END` dispatch is ignored — +there is nothing left to abort, and the original error wins. + +## Ordering + +For a crew run the boundary order is: + +``` +EXECUTION_START → before_kickoff callbacks → INPUT → tasks execute → OUTPUT → EXECUTION_END +``` + +Hooks at the same point run in registration order, global hooks first, then +crew-scoped hooks. Telemetry (`HookDispatchedEvent`) is emitted per dispatch. + +## Managing Hooks in Tests + +```python +from crewai.hooks import clear_all_hooks + +clear_all_hooks() # Clears every point, including boundaries +``` + +## Related Documentation + +- [Execution Hooks Overview →](/edge/en/learn/execution-hooks) +- [Step Hooks →](/edge/en/learn/step-hooks) +- [LLM Call Hooks →](/edge/en/learn/llm-hooks) +- [Tool Call Hooks →](/edge/en/learn/tool-hooks) diff --git a/docs/v1.15.13/en/learn/execution-hooks.mdx b/docs/v1.15.13/en/learn/execution-hooks.mdx new file mode 100644 index 0000000000..1c54dc8d23 --- /dev/null +++ b/docs/v1.15.13/en/learn/execution-hooks.mdx @@ -0,0 +1,281 @@ +--- +title: Execution Hooks +description: Intercept, modify, and control CrewAI's runtime with the @on decorator - one contract covering every interception point +mode: "wide" +--- + +Execution hooks provide fine-grained control over the runtime behavior of your +CrewAI agents. Unlike kickoff hooks that run before and after crew execution, +execution hooks intercept specific operations during execution — from the moment +a run starts, through every model call, tool call, and task or flow-method step, +down to the final output. + +Hooks are written with the `@on` decorator: one registration API and one +contract cover every interception point in the framework. + +```python +from crewai.hooks import on, HookAborted, InterceptionPoint + +@on(InterceptionPoint.PRE_TOOL_CALL, tools=["delete_file"]) +def guard_deletes(ctx): + raise HookAborted(reason="file deletion is not allowed", source="policy") +``` + + +The point-specific decorators (`@before_llm_call`, `@after_tool_call`, ...) keep +working unchanged — they are adapters over the same engine. See +[Point-specific decorators (legacy)](#point-specific-decorators-legacy) at the +end of this page. + + +## The contract + +Every hook is a **synchronous** callable that receives a single typed context: + +```python +from crewai.hooks import on, HookAborted, InterceptionPoint + +@on(InterceptionPoint.INPUT) +def add_defaults(ctx): + # 1. Observe: read anything off the context. + # 2. Mutate in place: change ctx.payload or nested fields directly. + ctx.payload.setdefault("locale", "en-US") + # 3. Or replace: return a new value to swap ctx.payload. + # 4. Or abort: raise HookAborted(reason, source) to stop the operation. + return None +``` + +A hook may do any of four things: + +| Action | How | Effect | +|--------|-----|--------| +| **Proceed** | `return None` (or nothing) | Operation continues unchanged | +| **Mutate** | Change `ctx.payload` / fields in place | Change is visible downstream | +| **Replace** | `return new_payload` | A non-`None` return replaces `ctx.payload` | +| **Abort** | `raise HookAborted(reason, source)` | Operation is stopped; the reason propagates | + +## Registering hooks + +Use `@on` for global hooks. It accepts `agents=` / `tools=` filters to scope a +hook to specific agent roles or tool names: + +```python +from crewai.hooks import on, InterceptionPoint + +@on(InterceptionPoint.POST_TOOL_CALL, agents=["researcher"], tools=["web_search"]) +def log_search_results(ctx): + print(f"search returned: {(ctx.tool_result or '')[:80]}") +``` + +Applied to a method inside a `@CrewBase` class, `@on` registers a +**crew-scoped** hook, active only while that crew runs: + +```python +from crewai import CrewBase +from crewai.hooks import on, InterceptionPoint + +@CrewBase +class MyProjCrew: + @on(InterceptionPoint.PRE_MODEL_CALL) + def validate_inputs(self, ctx): + # Only applies to this crew + return None +``` + +## Interception point catalog + +Each family has a detailed guide covering its context schema, payload +semantics, and examples. + +### [Execution boundaries](/edge/en/learn/execution-boundary-hooks) + +| Point | When | `ctx.payload` | +|-------|------|---------------| +| `EXECUTION_START` | A crew or flow is about to begin | inputs `dict` | +| `INPUT` | Resolved inputs for the execution | inputs `dict` | +| `OUTPUT` | Final result is ready | the output object | +| `EXECUTION_END` | A crew or flow has finished | the output object | + +### [Model boundaries](/edge/en/learn/llm-hooks) & [tool boundaries](/edge/en/learn/tool-hooks) + +| Point | When | Hook receives | +|-------|------|---------------| +| `PRE_MODEL_CALL` | Before an LLM call | `LLMCallHookContext` | +| `POST_MODEL_CALL` | After an LLM call | `LLMCallHookContext` (with `response` set) | +| `PRE_TOOL_CALL` | Before a tool runs | `ToolCallHookContext` | +| `POST_TOOL_CALL` | After a tool runs | `ToolCallHookContext` (with results set) | + +At these four points the hook receives the rich legacy context **directly** as +its argument — there is no separate `ctx.payload`. Mutate `ctx.messages` / +`ctx.tool_input` in place, and return a string from a post hook to replace the +response / tool result. + +### [Step points](/edge/en/learn/step-hooks) + +| Point | When | `ctx.payload` | +|-------|------|---------------| +| `PRE_STEP` | Before a task or flow-method step | step input | +| `POST_STEP` | After a task or flow-method step | step output | + +`PRE_STEP` / `POST_STEP` carry `ctx.kind` (`"task"` or `"flow_method"`) and +`ctx.step_name`. + +## Aborting an operation + +`HookAborted` carries a `reason` and an optional `source`. The `source` defaults +to the aborting hook when omitted, which is useful for telemetry and failure +messages: + +```python +@on(InterceptionPoint.EXECUTION_START) +def enforce_policy(ctx): + if not ctx.payload.get("authorized"): + raise HookAborted(reason="unauthorized execution", source="access-control") +``` + +## Composition, ordering, and fail-open + +- Multiple hooks on the same point run in **registration order**, global hooks + first, then execution-scoped hooks. Legacy hooks registered for the same point + participate in the same chain. +- The (possibly mutated) payload flows from one hook to the next. +- `HookAborted` **propagates by design** and stops the chain. +- Any *other* exception raised by a hook is **swallowed** (fail-open) so a single + buggy hook can't crash a run. +- When no hook is registered for a point, dispatch is a single dict lookup + (no-op fast path), so unused points cost effectively nothing. + +## Common patterns + +### Safety guardrails + +```python +@on(InterceptionPoint.PRE_TOOL_CALL) +def block_dangerous_tools(ctx): + dangerous = {"delete_file", "drop_table", "system_shutdown"} + if ctx.tool_name in dangerous: + raise HookAborted(reason=f"{ctx.tool_name} is blocked", source="safety-policy") + +@on(InterceptionPoint.PRE_MODEL_CALL) +def iteration_limit(ctx): + if ctx.iterations > 15: + raise HookAborted(reason="maximum iterations exceeded", source="loop-guard") +``` + +### Human-in-the-loop approval + +```python +@on(InterceptionPoint.PRE_TOOL_CALL, tools=["send_email", "make_payment"]) +def require_approval(ctx): + response = ctx.request_human_input( + prompt=f"Approve {ctx.tool_name}?", + default_message="Type 'yes' to approve:", + ) + if response.lower() != "yes": + raise HookAborted(reason="rejected by operator", source="approval-gate") +``` + +### Sanitizing outputs + +A non-`None` return value replaces the interceptable value, so transformations +are plain return statements: + +```python +import re + +@on(InterceptionPoint.POST_MODEL_CALL) +def redact_keys(ctx): + return re.sub( + r'(api[_-]?key)["\']?\s*[:=]\s*["\']?[\w-]+', + r"\1: [REDACTED]", + ctx.response, + flags=re.IGNORECASE, + ) +``` + +### Observing steps + +```python +@on(InterceptionPoint.POST_STEP) +def trace_steps(ctx): + print(f"{ctx.kind} '{ctx.step_name}' finished") +``` + +## Telemetry + +Whenever a point actually dispatches to at least one hook, CrewAI emits a +`HookDispatchedEvent` on the event bus with the point, the outcome +(`proceeded` / `modified` / `aborted`), the hook count, the duration, and — for +aborts — the reason and source. The no-op fast path emits nothing. + +## Managing hooks in tests + +Global hooks persist for the lifetime of the process. Reset them between tests: + +```python +import pytest +from crewai.hooks import clear_all_hooks + +@pytest.fixture(autouse=True) +def reset_hooks(): + clear_all_hooks() + yield + clear_all_hooks() +``` + +## Best practices + +1. **Keep hooks focused** — one clear responsibility per hook; register several + small hooks rather than one that does everything. +2. **Keep hooks fast** — hooks run on every dispatch of their point; avoid heavy + computation and lazy-import heavy dependencies. +3. **Prefer scoping** — use `agents=` / `tools=` filters and crew-scoped + registration instead of unconditional global hooks. +4. **Abort loudly** — raise `HookAborted` with a meaningful `reason` and + `source`; that context surfaces in error messages and telemetry. Remember + that any other exception is swallowed (fail-open), so don't rely on raising + `ValueError` to stop a run. + +## Point-specific decorators (legacy) + +Before `@on`, LLM and tool calls were hooked with dedicated decorator pairs. +These keep working unchanged — they are adapters over the same dispatcher, so +they compose with `@on` hooks in the same registration-order chain: + +```python +from crewai.hooks import before_llm_call, after_llm_call, before_tool_call, after_tool_call + +@before_llm_call +def limit_iterations(context): + if context.iterations > 10: + return False # Block execution + +@after_tool_call +def log_tool_result(context): + print(f"Tool {context.tool_name} completed") +``` + +Differences from `@on`: + +- They cover **only** the four model/tool points — no execution boundaries, no + steps. +- Blocking is `return False`, with no abort reason or source attached. +- They receive the same rich contexts — `LLMCallHookContext` (with full + executor access) and `ToolCallHookContext` — that `@on` hooks receive at the + model/tool points. +- Crew-scoping works the same way: apply the decorator to a method inside a + `@CrewBase` class. +- They support the same `agents=` / `tools=` filters. + +You might still prefer them for existing codebases that already use +`return False` semantics, or when you want the point-specific typed signatures. +For the detailed guides — context attributes, patterns, and management APIs +(`register_*` / `unregister_*` / `clear_*`) — see: + +- [LLM Call Hooks →](/edge/en/learn/llm-hooks) +- [Tool Call Hooks →](/edge/en/learn/tool-hooks) + +## Related documentation + +- [Before and After Kickoff Hooks →](/edge/en/learn/before-and-after-kickoff-hooks) +- [Human-in-the-Loop →](/edge/en/learn/human-in-the-loop) diff --git a/docs/v1.15.13/en/learn/force-tool-output-as-result.mdx b/docs/v1.15.13/en/learn/force-tool-output-as-result.mdx new file mode 100644 index 0000000000..4ed351d223 --- /dev/null +++ b/docs/v1.15.13/en/learn/force-tool-output-as-result.mdx @@ -0,0 +1,51 @@ +--- +title: Force Tool Output as Result +description: Learn how to force tool output as the result in an Agent's task in CrewAI. +icon: wrench-simple +mode: "wide" +--- + +## Introduction + +In CrewAI, you can force the output of a tool as the result of an agent's task. +This feature is useful when you want to ensure that the tool output is captured and returned as the task result, avoiding any agent modification during the task execution. + +## Forcing Tool Output as Result + +To force the tool output as the result of an agent's task, you need to set the `result_as_answer` parameter to `True` when adding a tool to the agent. +This parameter ensures that the tool output is captured and returned as the task result, without any modifications by the agent. + +Here's an example of how to force the tool output as the result of an agent's task: + +```python Code +from crewai.agent import Agent +from my_tool import MyCustomTool + +# Create a coding agent with the custom tool +coding_agent = Agent( + role="Data Scientist", + goal="Produce amazing reports on AI", + backstory="You work with data and AI", + tools=[MyCustomTool(result_as_answer=True)], + ) + +# Assuming the tool's execution and result population occurs within the system +task_result = coding_agent.execute_task(task) +``` + +## Workflow in Action + + + + The agent executes the task using the tool provided. + + + The tool generates the output, which is captured as the task result. + + + The agent may reflect and take learnings from the tool but the output is not modified. + + + The tool output is returned as the task result without any modifications. + + \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/hierarchical-process.mdx b/docs/v1.15.13/en/learn/hierarchical-process.mdx new file mode 100644 index 0000000000..d048c2f1d5 --- /dev/null +++ b/docs/v1.15.13/en/learn/hierarchical-process.mdx @@ -0,0 +1,113 @@ +--- +title: Hierarchical Process +description: A comprehensive guide to understanding and applying the hierarchical process within your CrewAI projects, updated to reflect the latest coding practices and functionalities. +icon: sitemap +mode: "wide" +--- + +## Introduction + +The hierarchical process in CrewAI introduces a structured approach to task management, simulating traditional organizational hierarchies for efficient task delegation and execution. +This systematic workflow enhances project outcomes by ensuring tasks are handled with optimal efficiency and accuracy. + + + The hierarchical process is designed to leverage advanced models like GPT-4, optimizing token usage while handling complex tasks with greater efficiency. + + +## Hierarchical Process Overview + +By default, tasks in CrewAI are managed through a sequential process. However, adopting a hierarchical approach allows for a clear hierarchy in task management, +where a 'manager' agent coordinates the workflow, delegates tasks, and validates outcomes for streamlined and effective execution. This manager agent can now be either +automatically created by CrewAI or explicitly set by the user. + +### Key Features + +- **Task Delegation**: A manager agent allocates tasks among crew members based on their roles and capabilities. +- **Result Validation**: The manager evaluates outcomes to ensure they meet the required standards. +- **Efficient Workflow**: Emulates corporate structures, providing an organized approach to task management. +- **System Prompt Handling**: Optionally specify whether the system should use predefined prompts. +- **Stop Words Control**: Optionally specify whether stop words should be used, supporting various models including the o1 models. +- **Context Window Respect**: Prioritize important context by enabling respect of the context window, which is now the default behavior. +- **Delegation Control**: Delegation is now disabled by default to give users explicit control. +- **Max Requests Per Minute**: Configurable option to set the maximum number of requests per minute. +- **Max Iterations**: Limit the maximum number of iterations for obtaining a final answer. + + +## Implementing the Hierarchical Process + +To utilize the hierarchical process, it's essential to explicitly set the process attribute to `Process.hierarchical`, as the default behavior is `Process.sequential`. +Define a crew with a designated manager and establish a clear chain of command. + + + Assign tools at the agent level to facilitate task delegation and execution by the designated agents under the manager's guidance. + Tools can also be specified at the task level for precise control over tool availability during task execution. + + + + Configuring the `manager_llm` parameter is crucial for the hierarchical process. + The system requires a manager LLM to be set up for proper function, ensuring tailored decision-making. + + +```python Code +from crewai import Crew, Process, Agent + +# Agents are defined with attributes for backstory, cache, and verbose mode +researcher = Agent( + role='Researcher', + goal='Conduct in-depth analysis', + backstory='Experienced data analyst with a knack for uncovering hidden trends.', +) +writer = Agent( + role='Writer', + goal='Create engaging content', + backstory='Creative writer passionate about storytelling in technical domains.', +) + +# Establishing the crew with a hierarchical process and additional configurations +project_crew = Crew( + tasks=[...], # Tasks to be delegated and executed under the manager's supervision + agents=[researcher, writer], + manager_llm="gpt-4o", # Specify which LLM the manager should use + process=Process.hierarchical, + planning=True, +) +``` + +### Using a Custom Manager Agent + +Alternatively, you can create a custom manager agent with specific attributes tailored to your project's management needs. This gives you more control over the manager's behavior and capabilities. + +```python +# Define a custom manager agent +manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success.", + allow_delegation=True, +) + +# Use the custom manager in your crew +project_crew = Crew( + tasks=[...], + agents=[researcher, writer], + manager_agent=manager, # Use your custom manager agent + process=Process.hierarchical, + planning=True, +) +``` + + + For more details on creating and customizing a manager agent, check out the [Custom Manager Agent documentation](/en/learn/custom-manager-agent). + + + +### Workflow in Action + +1. **Task Assignment**: The manager assigns tasks strategically, considering each agent's capabilities and available tools. +2. **Execution and Review**: Agents complete their tasks with the option for asynchronous execution and callback functions for streamlined workflows. +3. **Sequential Task Progression**: Despite being a hierarchical process, tasks follow a logical order for smooth progression, facilitated by the manager's oversight. + +## Conclusion + +Adopting the hierarchical process in CrewAI, with the correct configurations and understanding of the system's capabilities, facilitates an organized and efficient approach to project management. +Utilize the advanced features and customizations to tailor the workflow to your specific needs, ensuring optimal task execution and project success. diff --git a/docs/v1.15.13/en/learn/human-feedback-in-flows.mdx b/docs/v1.15.13/en/learn/human-feedback-in-flows.mdx new file mode 100644 index 0000000000..0c3792bca5 --- /dev/null +++ b/docs/v1.15.13/en/learn/human-feedback-in-flows.mdx @@ -0,0 +1,707 @@ +--- +title: Human Feedback in Flows +description: Learn how to integrate human feedback directly into your CrewAI Flows using the @human_feedback decorator +icon: user-check +mode: "wide" +--- + +## Overview + + +The `@human_feedback` decorator requires **CrewAI version 1.8.0 or higher**. Make sure to update your installation before using this feature. + + +The `@human_feedback` decorator enables human-in-the-loop (HITL) workflows directly within CrewAI Flows. It allows you to pause flow execution, present output to a human for review, collect their feedback, and optionally route to different listeners based on the feedback outcome. + +This is particularly valuable for: + +- **Quality assurance**: Review AI-generated content before it's used downstream +- **Decision gates**: Let humans make critical decisions in automated workflows +- **Approval workflows**: Implement approve/reject/revise patterns +- **Interactive refinement**: Collect feedback to improve outputs iteratively + +```mermaid +flowchart LR + A[Flow Method] --> B[Output Generated] + B --> C[Human Reviews] + C --> D{Feedback} + D -->|emit specified| E[LLM Collapses to Outcome] + D -->|no emit| F[HumanFeedbackResult] + E --> G["@listen('approved')"] + E --> H["@listen('rejected')"] + F --> I[Next Listener] +``` + +## Quick Start + +Here's the simplest way to add human feedback to a flow: + +```python Code +from crewai.flow.flow import Flow, start, listen +from crewai.flow.human_feedback import human_feedback + +class SimpleReviewFlow(Flow): + @start() + @human_feedback(message="Please review this content:") + def generate_content(self): + return "This is AI-generated content that needs review." + + @listen(generate_content) + def process_feedback(self, result): + print(f"Content: {result.output}") + print(f"Human said: {result.feedback}") + +flow = SimpleReviewFlow() +flow.kickoff() +``` + +When this flow runs, it will: +1. Execute `generate_content` and return the string +2. Display the output to the user with the request message +3. Wait for the user to type feedback (or press Enter to skip) +4. Pass a `HumanFeedbackResult` object to `process_feedback` + +## The @human_feedback Decorator + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `message` | `str` | Yes | The message shown to the human alongside the method output | +| `emit` | `Sequence[str]` | No | List of possible outcomes. Feedback is collapsed to one of these, which triggers `@listen` decorators | +| `llm` | `str \| BaseLLM` | When `emit` specified | LLM used to interpret feedback and map to an outcome | +| `default_outcome` | `str` | No | Outcome to use if no feedback provided. Must be in `emit` | +| `metadata` | `dict` | No | Additional data for enterprise integrations | +| `provider` | `HumanFeedbackProvider` | No | Custom provider for async/non-blocking feedback. See [Async Human Feedback](#async-human-feedback-non-blocking) | +| `learn` | `bool` | No | Enable HITL learning: distill lessons from feedback and pre-review future output. Default `False`. See [Learning from Feedback](#learning-from-feedback) | +| `learn_limit` | `int` | No | Max past lessons to recall for pre-review. Default `5` | + +### Basic Usage (No Routing) + +When you don't specify `emit`, the decorator simply collects feedback and passes a `HumanFeedbackResult` to the next listener: + +```python Code +@start() +@human_feedback(message="What do you think of this analysis?") +def analyze_data(self): + return "Analysis results: Revenue up 15%, costs down 8%" + +@listen(analyze_data) +def handle_feedback(self, result): + # result is a HumanFeedbackResult + print(f"Analysis: {result.output}") + print(f"Feedback: {result.feedback}") +``` + +### Routing with emit + +When you specify `emit`, the decorator becomes a router. The human's free-form feedback is interpreted by an LLM and collapsed into one of the specified outcomes: + +```python Code +from crewai.flow.flow import Flow, start, listen, or_ +from crewai.flow.human_feedback import human_feedback + +class ReviewFlow(Flow): + @start() + def generate_content(self): + return "Draft blog post content here..." + + @human_feedback( + message="Do you approve this content for publication?", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + @listen(or_("generate_content", "needs_revision")) + def review_content(self): + return "Draft blog post content here..." + + @listen("approved") + def publish(self, result): + print(f"Publishing! User said: {result.feedback}") + + @listen("rejected") + def discard(self, result): + print(f"Discarding. Reason: {result.feedback}") +``` + +When the human says something like "needs more detail", the LLM collapses that to `"needs_revision"`, which triggers `review_content` again via `or_()` — creating a revision loop. The loop continues until the outcome is `"approved"` or `"rejected"`. + + +The LLM uses structured outputs (function calling) when available to guarantee the response is one of your specified outcomes. This makes routing reliable and predictable. + + + +A `@start()` method only runs once at the beginning of the flow. If you need a revision loop, separate the start method from the review method and use `@listen(or_("trigger", "revision_outcome"))` on the review method to enable the self-loop. + + +## HumanFeedbackResult + +The `HumanFeedbackResult` dataclass contains all information about a human feedback interaction: + +```python Code +from crewai.flow.human_feedback import HumanFeedbackResult + +@dataclass +class HumanFeedbackResult: + output: Any # The original method output shown to the human + feedback: str # The raw feedback text from the human + outcome: str | None # The collapsed outcome (if emit was specified) + timestamp: datetime # When the feedback was received + method_name: str # Name of the decorated method + metadata: dict # Any metadata passed to the decorator +``` + +### Accessing in Listeners + +When a listener is triggered by a `@human_feedback` method with `emit`, it receives the `HumanFeedbackResult`: + +```python Code +@listen("approved") +def on_approval(self, result: HumanFeedbackResult): + print(f"Original output: {result.output}") + print(f"User feedback: {result.feedback}") + print(f"Outcome: {result.outcome}") # "approved" + print(f"Received at: {result.timestamp}") +``` + +## Accessing Feedback History + +The `Flow` class provides two attributes for accessing human feedback: + +### last_human_feedback + +Returns the most recent `HumanFeedbackResult`: + +```python Code +@listen(some_method) +def check_feedback(self): + if self.last_human_feedback: + print(f"Last feedback: {self.last_human_feedback.feedback}") +``` + +### human_feedback_history + +A list of all `HumanFeedbackResult` objects collected during the flow: + +```python Code +@listen(final_step) +def summarize(self): + print(f"Total feedback collected: {len(self.human_feedback_history)}") + for i, fb in enumerate(self.human_feedback_history): + print(f"{i+1}. {fb.method_name}: {fb.outcome or 'no routing'}") +``` + + +Each `HumanFeedbackResult` is appended to `human_feedback_history`, so multiple feedback steps won't overwrite each other. Use this list to access all feedback collected during the flow. + + +## Complete Example: Content Approval Workflow + +Here's a full example implementing a content review and approval workflow with a revision loop: + + + +```python Code +from crewai.flow.flow import Flow, start, listen, or_ +from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult +from pydantic import BaseModel + + +class ContentState(BaseModel): + draft: str = "" + revision_count: int = 0 + status: str = "pending" + + +class ContentApprovalFlow(Flow[ContentState]): + """A flow that generates content and loops until the human approves.""" + + @start() + def generate_draft(self): + self.state.draft = "# AI Safety\n\nThis is a draft about AI Safety..." + return self.state.draft + + @human_feedback( + message="Please review this draft. Approve, reject, or describe what needs changing:", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + @listen(or_("generate_draft", "needs_revision")) + def review_draft(self): + self.state.revision_count += 1 + return f"{self.state.draft} (v{self.state.revision_count})" + + @listen("approved") + def publish_content(self, result: HumanFeedbackResult): + self.state.status = "published" + print(f"Content approved and published! Reviewer said: {result.feedback}") + return "published" + + @listen("rejected") + def handle_rejection(self, result: HumanFeedbackResult): + self.state.status = "rejected" + print(f"Content rejected. Reason: {result.feedback}") + return "rejected" + + +flow = ContentApprovalFlow() +result = flow.kickoff() +print(f"\nFlow completed. Status: {flow.state.status}, Reviews: {flow.state.revision_count}") +``` + +```text Output +================================================== +OUTPUT FOR REVIEW: +================================================== +# AI Safety + +This is a draft about AI Safety... (v1) +================================================== + +Please review this draft. Approve, reject, or describe what needs changing: +(Press Enter to skip, or type your feedback) + +Your feedback: Needs more detail on alignment research + +================================================== +OUTPUT FOR REVIEW: +================================================== +# AI Safety + +This is a draft about AI Safety... (v2) +================================================== + +Please review this draft. Approve, reject, or describe what needs changing: +(Press Enter to skip, or type your feedback) + +Your feedback: Looks good, approved! + +Content approved and published! Reviewer said: Looks good, approved! + +Flow completed. Status: published, Reviews: 2 +``` + + + +The key pattern is `@listen(or_("generate_draft", "needs_revision"))` — the review method listens to both the initial trigger and its own revision outcome, creating a self-loop that repeats until the human approves or rejects. + +## Combining with Other Decorators + +The `@human_feedback` decorator works with `@start()`, `@listen()`, and `or_()`. Both decorator orderings work — the framework propagates attributes in both directions — but the recommended patterns are: + +```python Code +# One-shot review at the start of a flow (no self-loop) +@start() +@human_feedback(message="Review this:", emit=["approved", "rejected"], llm="gpt-4o-mini") +def my_start_method(self): + return "content" + +# Linear review on a listener (no self-loop) +@listen(other_method) +@human_feedback(message="Review this too:", emit=["good", "bad"], llm="gpt-4o-mini") +def my_listener(self, data): + return f"processed: {data}" + +# Self-loop: review that can loop back for revisions +@human_feedback(message="Approve or revise?", emit=["approved", "revise"], llm="gpt-4o-mini") +@listen(or_("upstream_method", "revise")) +def review_with_loop(self): + return "content for review" +``` + +### Self-loop pattern + +To create a revision loop, the review method must listen to **both** an upstream trigger and its own revision outcome using `or_()`: + +```python Code +@start() +def generate(self): + return "initial draft" + +@human_feedback( + message="Approve or request changes?", + emit=["revise", "approved"], + llm="gpt-4o-mini", + default_outcome="approved", +) +@listen(or_("generate", "revise")) +def review(self): + return "content" + +@listen("approved") +def publish(self): + return "published" +``` + +When the outcome is `"revise"`, the flow routes back to `review` (because it listens to `"revise"` via `or_()`). When the outcome is `"approved"`, the flow continues to `publish`. This works because the flow engine exempts routers from the "fire once" rule, allowing them to re-execute on each loop iteration. + +### Chained routers + +A listener triggered by one router's outcome can itself be a router: + +```python Code +@start() +def generate(self): + return "draft content" + +@human_feedback(message="First review:", emit=["approved", "rejected"], llm="gpt-4o-mini") +@listen("generate") +def first_review(self): + return "draft content" + +@human_feedback(message="Final review:", emit=["publish", "hold"], llm="gpt-4o-mini") +@listen("approved") +def final_review(self, prev): + return "final content" + +@listen("publish") +def on_publish(self, prev): + return "published" + +@listen("hold") +def on_hold(self, prev): + return "held for later" +``` + +### Limitations + +- **`@start()` methods run once**: A `@start()` method cannot self-loop. If you need a revision cycle, use a separate `@start()` method as the entry point and put the `@human_feedback` on a `@listen()` method. +- **No `@start()` + `@listen()` on the same method**: This is a Flow framework constraint. A method is either a start point or a listener, not both. + +## Best Practices + +### 1. Write Clear Request Messages + +The `message` parameter is what the human sees. Make it actionable: + +```python Code +# ✅ Good - clear and actionable +@human_feedback(message="Does this summary accurately capture the key points? Reply 'yes' or explain what's missing:") + +# ❌ Bad - vague +@human_feedback(message="Review this:") +``` + +### 2. Choose Meaningful Outcomes + +When using `emit`, pick outcomes that map naturally to human responses: + +```python Code +# ✅ Good - natural language outcomes +emit=["approved", "rejected", "needs_more_detail"] + +# ❌ Bad - technical or unclear +emit=["state_1", "state_2", "state_3"] +``` + +### 3. Always Provide a Default Outcome + +Use `default_outcome` to handle cases where users press Enter without typing: + +```python Code +@human_feedback( + message="Approve? (press Enter to request revision)", + emit=["approved", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", # Safe default +) +``` + +### 4. Use Feedback History for Audit Trails + +Access `human_feedback_history` to create audit logs: + +```python Code +@listen(final_step) +def create_audit_log(self): + log = [] + for fb in self.human_feedback_history: + log.append({ + "step": fb.method_name, + "outcome": fb.outcome, + "feedback": fb.feedback, + "timestamp": fb.timestamp.isoformat(), + }) + return log +``` + +### 5. Handle Both Routed and Non-Routed Feedback + +When designing flows, consider whether you need routing: + +| Scenario | Use | +|----------|-----| +| Simple review, just need the feedback text | No `emit` | +| Need to branch to different paths based on response | Use `emit` | +| Approval gates with approve/reject/revise | Use `emit` | +| Collecting comments for logging only | No `emit` | + +## Async Human Feedback (Non-Blocking) + +By default, `@human_feedback` blocks execution waiting for console input. For production applications, you may need **async/non-blocking** feedback that integrates with external systems like Slack, email, webhooks, or APIs. + +### The Provider Abstraction + +Use the `provider` parameter to specify a custom feedback collection strategy: + +```python Code +from crewai.flow import Flow, start, human_feedback, HumanFeedbackProvider, HumanFeedbackPending, PendingFeedbackContext + +class WebhookProvider(HumanFeedbackProvider): + """Provider that pauses flow and waits for webhook callback.""" + + def __init__(self, webhook_url: str): + self.webhook_url = webhook_url + + def request_feedback(self, context: PendingFeedbackContext, flow: Flow) -> str: + # Notify external system (e.g., send Slack message, create ticket) + self.send_notification(context) + + # Pause execution - framework handles persistence automatically + raise HumanFeedbackPending( + context=context, + callback_info={"webhook_url": f"{self.webhook_url}/{context.flow_id}"} + ) + +class ReviewFlow(Flow): + @start() + @human_feedback( + message="Review this content:", + emit=["approved", "rejected"], + llm="gpt-4o-mini", + provider=WebhookProvider("https://myapp.com/api"), + ) + def generate_content(self): + return "AI-generated content..." + + @listen("approved") + def publish(self, result): + return "Published!" +``` + + +The flow framework **automatically persists state** when `HumanFeedbackPending` is raised. Your provider only needs to notify the external system and raise the exception—no manual persistence calls required. + + +### Handling Paused Flows + +When using an async provider, `kickoff()` returns a `HumanFeedbackPending` object instead of raising an exception: + +```python Code +flow = ReviewFlow() +result = flow.kickoff() + +if isinstance(result, HumanFeedbackPending): + # Flow is paused, state is automatically persisted + print(f"Waiting for feedback at: {result.callback_info['webhook_url']}") + print(f"Flow ID: {result.context.flow_id}") +else: + # Normal completion + print(f"Flow completed: {result}") +``` + +### Resuming a Paused Flow + +When feedback arrives (e.g., via webhook), resume the flow: + +```python Code +# Sync handler: +def handle_feedback_webhook(flow_id: str, feedback: str): + flow = ReviewFlow.from_pending(flow_id) + result = flow.resume(feedback) + return result + +# Async handler (FastAPI, aiohttp, etc.): +async def handle_feedback_webhook(flow_id: str, feedback: str): + flow = ReviewFlow.from_pending(flow_id) + result = await flow.resume_async(feedback) + return result +``` + +### Key Types + +| Type | Description | +|------|-------------| +| `HumanFeedbackProvider` | Protocol for custom feedback providers | +| `PendingFeedbackContext` | Contains all info needed to resume a paused flow | +| `HumanFeedbackPending` | Returned by `kickoff()` when flow is paused for feedback | +| `ConsoleProvider` | Default blocking console input provider | + +### PendingFeedbackContext + +The context contains everything needed to resume: + +```python Code +@dataclass +class PendingFeedbackContext: + flow_id: str # Unique identifier for this flow execution + flow_class: str # Fully qualified class name + method_name: str # Method that triggered feedback + method_output: Any # Output shown to the human + message: str # The request message + emit: list[str] | None # Possible outcomes for routing + default_outcome: str | None + metadata: dict # Custom metadata + llm: str | None # LLM for outcome collapsing + requested_at: datetime +``` + +### Complete Async Flow Example + +```python Code +from crewai.flow import ( + Flow, start, listen, human_feedback, + HumanFeedbackProvider, HumanFeedbackPending, PendingFeedbackContext +) + +class SlackNotificationProvider(HumanFeedbackProvider): + """Provider that sends Slack notifications and pauses for async feedback.""" + + def __init__(self, channel: str): + self.channel = channel + + def request_feedback(self, context: PendingFeedbackContext, flow: Flow) -> str: + # Send Slack notification (implement your own) + slack_thread_id = self.post_to_slack( + channel=self.channel, + message=f"Review needed:\n\n{context.method_output}\n\n{context.message}", + ) + + # Pause execution - framework handles persistence automatically + raise HumanFeedbackPending( + context=context, + callback_info={ + "slack_channel": self.channel, + "thread_id": slack_thread_id, + } + ) + +class ContentPipeline(Flow): + @start() + @human_feedback( + message="Approve this content for publication?", + emit=["approved", "rejected"], + llm="gpt-4o-mini", + default_outcome="rejected", + provider=SlackNotificationProvider("#content-reviews"), + ) + def generate_content(self): + return "AI-generated blog post content..." + + @listen("approved") + def publish(self, result): + print(f"Publishing! Reviewer said: {result.feedback}") + return {"status": "published"} + + @listen("rejected") + def archive(self, result): + print(f"Archived. Reason: {result.feedback}") + return {"status": "archived"} + + +# Starting the flow (will pause and wait for Slack response) +def start_content_pipeline(): + flow = ContentPipeline() + result = flow.kickoff() + + if isinstance(result, HumanFeedbackPending): + return {"status": "pending", "flow_id": result.context.flow_id} + + return result + + +# Resuming when Slack webhook fires (sync handler) +def on_slack_feedback(flow_id: str, slack_message: str): + flow = ContentPipeline.from_pending(flow_id) + result = flow.resume(slack_message) + return result + + +# If your handler is async (FastAPI, aiohttp, Slack Bolt async, etc.) +async def on_slack_feedback_async(flow_id: str, slack_message: str): + flow = ContentPipeline.from_pending(flow_id) + result = await flow.resume_async(slack_message) + return result +``` + + +If you're using an async web framework (FastAPI, aiohttp, Slack Bolt async mode), use `await flow.resume_async()` instead of `flow.resume()`. Calling `resume()` from within a running event loop will raise a `RuntimeError`. + + +### Best Practices for Async Feedback + +1. **Check the return type**: `kickoff()` returns `HumanFeedbackPending` when paused—no try/except needed +2. **Use the right resume method**: Use `resume()` in sync code, `await resume_async()` in async code +3. **Store callback info**: Use `callback_info` to store webhook URLs, ticket IDs, etc. +4. **Implement idempotency**: Your resume handler should be idempotent for safety +5. **Automatic persistence**: State is automatically saved when `HumanFeedbackPending` is raised and uses `SQLiteFlowPersistence` by default +6. **Custom persistence**: Pass a custom persistence instance to `from_pending()` if needed + +## Learning from Feedback + +The `learn=True` parameter enables a feedback loop between human reviewers and the memory system. When enabled, the system progressively improves its outputs by learning from past human corrections. + +### How It Works + +1. **After feedback**: The LLM extracts generalizable lessons from the output + feedback and stores them in memory with `source="hitl"`. If the feedback is just approval (e.g. "looks good"), nothing is stored. +2. **Before next review**: Past HITL lessons are recalled from memory and applied by the LLM to improve the output before the human sees it. + +Over time, the human sees progressively better pre-reviewed output because each correction informs future reviews. + +### Example + +```python Code +class ArticleReviewFlow(Flow): + @start() + def generate_article(self): + return self.crew.kickoff(inputs={"topic": "AI Safety"}).raw + + @human_feedback( + message="Review this article draft:", + emit=["approved", "needs_revision"], + llm="gpt-4o-mini", + learn=True, # enable HITL learning + ) + @listen(or_("generate_article", "needs_revision")) + def review_article(self): + return self.last_human_feedback.output if self.last_human_feedback else "article draft" + + @listen("approved") + def publish(self): + print(f"Publishing: {self.last_human_feedback.output}") +``` + +**First run**: The human sees the raw output and says "Always include citations for factual claims." The lesson is distilled and stored in memory. + +**Second run**: The system recalls the citation lesson, pre-reviews the output to add citations, then shows the improved version. The human's job shifts from "fix everything" to "catch what the system missed." + +### Configuration + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `learn` | `False` | Enable HITL learning | +| `learn_limit` | `5` | Max past lessons to recall for pre-review | + +### Key Design Decisions + +- **Same LLM for everything**: The `llm` parameter on the decorator is shared by outcome collapsing, lesson distillation, and pre-review. No need to configure multiple models. +- **Structured output**: Both distillation and pre-review use function calling with Pydantic models when the LLM supports it, falling back to text parsing otherwise. +- **Non-blocking storage**: Lessons are stored via `remember_many()` which runs in a background thread -- the flow continues immediately. +- **Graceful degradation**: If the LLM fails during distillation, nothing is stored. If it fails during pre-review, the raw output is shown. Neither failure blocks the flow. +- **No scope/categories needed**: When storing lessons, only `source` is passed. The encoding pipeline infers scope, categories, and importance automatically. + + +`learn=True` requires the Flow to have memory available. Flows get memory automatically by default, but if you've disabled it with `_skip_auto_memory`, HITL learning will be silently skipped. + + + +## Related Documentation + +- [Flows Overview](/en/concepts/flows) - Learn about CrewAI Flows +- [Flow State Management](/en/guides/flows/mastering-flow-state) - Managing state in flows +- [Flow Persistence](/en/concepts/flows#persistence) - Persisting flow state +- [Routing with @router](/en/concepts/flows#router) - More about conditional routing +- [Human Input on Execution](/en/learn/human-input-on-execution) - Task-level human input +- [Memory](/en/concepts/memory) - The unified memory system used by HITL learning diff --git a/docs/v1.15.13/en/learn/human-in-the-loop.mdx b/docs/v1.15.13/en/learn/human-in-the-loop.mdx new file mode 100644 index 0000000000..516726bd19 --- /dev/null +++ b/docs/v1.15.13/en/learn/human-in-the-loop.mdx @@ -0,0 +1,159 @@ +--- +title: "Human-in-the-Loop (HITL) Workflows" +description: "Learn how to implement Human-in-the-Loop workflows in CrewAI for enhanced decision-making" +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. CrewAI provides multiple ways to implement HITL depending on your needs. + +## Choosing Your HITL Approach + +CrewAI offers two main approaches for implementing human-in-the-loop workflows: + +| Approach | Best For | Integration | Version | +|----------|----------|-------------|---------| +| **Flow-based** (`@human_feedback` decorator) | Local development, console-based review, synchronous workflows | [Human Feedback in Flows](/en/learn/human-feedback-in-flows) | **1.8.0+** | +| **Webhook-based** (Enterprise) | Production deployments, async workflows, external integrations (Slack, Teams, etc.) | This guide | - | + + +If you're building flows and want to add human review steps with routing based on feedback, check out the [Human Feedback in Flows](/en/learn/human-feedback-in-flows) guide for the `@human_feedback` decorator. + + +## Setting Up Webhook-Based HITL Workflows + + + + Set up your task with human input enabled: + + Crew Human Input + + + + + When kicking off your crew, include a webhook URL for human input: + + Crew Webhook URL + + + Example with Bearer authentication: + ```bash + curl -X POST {BASE_URL}/kickoff \ + -H "Authorization: Bearer YOUR_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "inputs": { + "topic": "AI Research" + }, + "humanInputWebhook": { + "url": "https://your-webhook.com/hitl", + "authentication": { + "strategy": "bearer", + "token": "your-webhook-secret-token" + } + } + }' + ``` + + Or with Basic authentication: + ```bash + curl -X POST {BASE_URL}/kickoff \ + -H "Authorization: Bearer YOUR_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "inputs": { + "topic": "AI Research" + }, + "humanInputWebhook": { + "url": "https://your-webhook.com/hitl", + "authentication": { + "strategy": "basic", + "username": "your-username", + "password": "your-password" + } + } + }' + ``` + + + + Once the crew completes the task requiring human input, you'll receive a webhook notification containing: + - Execution ID + - Task ID + - Task output + + + + The system will pause in the `Pending Human Input` state. Review the task output carefully. + + + + Call the resume endpoint of your crew with the following information: + + Crew Resume Endpoint + + + + **Critical: Webhook URLs Must Be Provided Again**: + You **must** provide the same webhook URLs (`taskWebhookUrl`, `stepWebhookUrl`, `crewWebhookUrl`) in the resume call that you used in the kickoff call. Webhook configurations are **NOT** automatically carried over from kickoff - they must be explicitly included in the resume request to continue receiving notifications for task completion, agent steps, and crew completion. + + + Example resume call with webhooks: + ```bash + curl -X POST {BASE_URL}/resume \ + -H "Authorization: Bearer YOUR_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "execution_id": "abcd1234-5678-90ef-ghij-klmnopqrstuv", + "task_id": "research_task", + "human_feedback": "Great work! Please add more details.", + "is_approve": true, + "taskWebhookUrl": "https://your-server.com/webhooks/task", + "stepWebhookUrl": "https://your-server.com/webhooks/step", + "crewWebhookUrl": "https://your-server.com/webhooks/crew" + }' + ``` + + + **Feedback Impact on Task Execution**: + It's crucial to exercise care when providing feedback, as the entire feedback content will be incorporated as additional context for further task executions. + + This means: + - All information in your feedback becomes part of the task's context. + - Irrelevant details may negatively influence it. + - Concise, relevant feedback helps maintain task focus and efficiency. + - Always review your feedback carefully before submission to ensure it contains only pertinent information that will positively guide the task's execution. + + + If you provide negative feedback: + - The crew will retry the task with added context from your feedback. + - You'll receive another webhook notification for further review. + - Repeat steps 4-6 until satisfied. + + + + When you submit positive feedback, the execution will proceed to the next steps. + + + +## Best Practices + +- **Be Specific**: Provide clear, actionable feedback that directly addresses the task at hand +- **Stay Relevant**: Only include information that will help improve the task execution +- **Be Timely**: Respond to HITL prompts promptly to avoid workflow delays +- **Review Carefully**: Double-check your feedback before submitting to ensure accuracy + +## Common Use Cases + +HITL workflows are particularly valuable for: +- Quality assurance and validation +- Complex decision-making scenarios +- Sensitive or high-stakes operations +- Creative tasks requiring human judgment +- Compliance and regulatory reviews + +## Enterprise Features + + + 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 →](https://docs-platform.crewai.com/platform/en/features/flow-hitl-management) + diff --git a/docs/v1.15.13/en/learn/human-input-on-execution.mdx b/docs/v1.15.13/en/learn/human-input-on-execution.mdx new file mode 100644 index 0000000000..c4414bff02 --- /dev/null +++ b/docs/v1.15.13/en/learn/human-input-on-execution.mdx @@ -0,0 +1,99 @@ +--- +title: Human Input on Execution +description: Integrating CrewAI with human input during execution in complex decision-making processes and leveraging the full capabilities of the agent's attributes and tools. +icon: user-plus +mode: "wide" +--- + +## Human input in agent execution + +Human input is critical in several agent execution scenarios, allowing agents to request additional information or clarification when necessary. +This feature is especially useful in complex decision-making processes or when agents require more details to complete a task effectively. + +## Using human input with CrewAI + +To integrate human input into agent execution, set the `human_input` flag in the task definition. When enabled, the agent prompts the user for input before delivering its final answer. +This input can provide extra context, clarify ambiguities, or validate the agent's output. + +### Example: + +```shell +pip install crewai +``` + +```python Code +import os +from crewai import Agent, Task, Crew +from crewai_tools import SerperDevTool + +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key +os.environ["OPENAI_API_KEY"] = "Your Key" + +# Loading Tools +search_tool = SerperDevTool() + +# Define your agents with roles, goals, tools, and additional attributes +researcher = Agent( + role='Senior Research Analyst', + goal='Uncover cutting-edge developments in AI and data science', + backstory=( + "You are a Senior Research Analyst at a leading tech think tank. " + "Your expertise lies in identifying emerging trends and technologies in AI and data science. " + "You have a knack for dissecting complex data and presenting actionable insights." + ), + verbose=True, + allow_delegation=False, + tools=[search_tool] +) +writer = Agent( + role='Tech Content Strategist', + goal='Craft compelling content on tech advancements', + backstory=( + "You are a renowned Tech Content Strategist, known for your insightful and engaging articles on technology and innovation. " + "With a deep understanding of the tech industry, you transform complex concepts into compelling narratives." + ), + verbose=True, + allow_delegation=True, + tools=[search_tool], + cache=False, # Disable cache for this agent +) + +# Create tasks for your agents +task1 = Task( + description=( + "Conduct a comprehensive analysis of the latest advancements in AI in 2025. " + "Identify key trends, breakthrough technologies, and potential industry impacts. " + "Compile your findings in a detailed report. " + "Make sure to check with a human if the draft is good before finalizing your answer." + ), + expected_output='A comprehensive full report on the latest AI advancements in 2025, leave nothing out', + agent=researcher, + human_input=True +) + +task2 = Task( + description=( + "Using the insights from the researcher\'s report, develop an engaging blog post that highlights the most significant AI advancements. " + "Your post should be informative yet accessible, catering to a tech-savvy audience. " + "Aim for a narrative that captures the essence of these breakthroughs and their implications for the future." + ), + expected_output='A compelling 3 paragraphs blog post formatted as markdown about the latest AI advancements in 2025', + agent=writer, + human_input=True +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[researcher, writer], + tasks=[task1, task2], + verbose=True, + memory=True, + planning=True # Enable planning feature for the crew +) + +# Get your crew to work! +result = crew.kickoff() + +print("######################") +print(result) +``` diff --git a/docs/v1.15.13/en/learn/kickoff-async.mdx b/docs/v1.15.13/en/learn/kickoff-async.mdx new file mode 100644 index 0000000000..dc5c7c08bd --- /dev/null +++ b/docs/v1.15.13/en/learn/kickoff-async.mdx @@ -0,0 +1,306 @@ +--- +title: Kickoff Crew Asynchronously +description: Kickoff a Crew Asynchronously +icon: rocket-launch +mode: "wide" +--- + +## Introduction + +CrewAI provides the ability to kickoff a crew asynchronously, allowing you to start the crew execution in a non-blocking manner. +This feature is particularly useful when you want to run multiple crews concurrently or when you need to perform other tasks while the crew is executing. + +CrewAI offers two approaches for async execution: + +| Method | Type | Description | +|--------|------|-------------| +| `akickoff()` | Native async | True async/await throughout the entire execution chain | +| `kickoff_async()` | Thread-based | Wraps synchronous execution in `asyncio.to_thread` | + + +For high-concurrency workloads, `akickoff()` is recommended as it uses native async for task execution, memory operations, and knowledge retrieval. + + +## Native Async Execution with `akickoff()` + +The `akickoff()` method provides true native async execution, using async/await throughout the entire execution chain including task execution, memory operations, and knowledge queries. + +### Method Signature + +```python Code +async def akickoff(self, inputs: dict) -> CrewOutput: +``` + +### Parameters + +- `inputs` (dict): A dictionary containing the input data required for the tasks. + +### Returns + +- `CrewOutput`: An object representing the result of the crew execution. + +### Example: Native Async Crew Execution + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +# Create an agent +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +# Create a crew +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +# Native async execution +async def main(): + result = await analysis_crew.akickoff(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + +asyncio.run(main()) +``` + +### Example: Multiple Native Async Crews + +Run multiple crews concurrently using `asyncio.gather()` with native async: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +task_1 = Task( + description="Analyze the first dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +task_2 = Task( + description="Analyze the second dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +crew_1 = Crew(agents=[coding_agent], tasks=[task_1]) +crew_2 = Crew(agents=[coding_agent], tasks=[task_2]) + +async def main(): + results = await asyncio.gather( + crew_1.akickoff(inputs={"ages": [25, 30, 35, 40, 45]}), + crew_2.akickoff(inputs={"ages": [20, 22, 24, 28, 30]}) + ) + + for i, result in enumerate(results, 1): + print(f"Crew {i} Result:", result) + +asyncio.run(main()) +``` + +### Example: Native Async for Multiple Inputs + +Use `akickoff_for_each()` to execute your crew against multiple inputs concurrently with native async: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +async def main(): + datasets = [ + {"ages": [25, 30, 35, 40, 45]}, + {"ages": [20, 22, 24, 28, 30]}, + {"ages": [30, 35, 40, 45, 50]} + ] + + results = await analysis_crew.akickoff_for_each(datasets) + + for i, result in enumerate(results, 1): + print(f"Dataset {i} Result:", result) + +asyncio.run(main()) +``` + +## Thread-Based Async with `kickoff_async()` + +The `kickoff_async()` method provides async execution by wrapping the synchronous `kickoff()` in a thread. This is useful for simpler async integration or backward compatibility. + +### Method Signature + +```python Code +async def kickoff_async(self, inputs: dict) -> CrewOutput: +``` + +### Parameters + +- `inputs` (dict): A dictionary containing the input data required for the tasks. + +### Returns + +- `CrewOutput`: An object representing the result of the crew execution. + +### Example: Thread-Based Async Execution + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +async def async_crew_execution(): + result = await analysis_crew.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + +asyncio.run(async_crew_execution()) +``` + +### Example: Multiple Thread-Based Async Crews + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +task_1 = Task( + description="Analyze the first dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +task_2 = Task( + description="Analyze the second dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +crew_1 = Crew(agents=[coding_agent], tasks=[task_1]) +crew_2 = Crew(agents=[coding_agent], tasks=[task_2]) + +async def async_multiple_crews(): + result_1 = crew_1.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + result_2 = crew_2.kickoff_async(inputs={"ages": [20, 22, 24, 28, 30]}) + + results = await asyncio.gather(result_1, result_2) + + for i, result in enumerate(results, 1): + print(f"Crew {i} Result:", result) + +asyncio.run(async_multiple_crews()) +``` + +## Async Streaming + +Both async methods support streaming when `stream=True` is set on the crew: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +agent = Agent( + role="Researcher", + goal="Research and summarize topics", + backstory="You are an expert researcher." +) + +task = Task( + description="Research the topic: {topic}", + agent=agent, + expected_output="A comprehensive summary of the topic." +) + +crew = Crew( + agents=[agent], + tasks=[task], + stream=True # Enable streaming +) + +async def main(): + streaming_output = await crew.akickoff(inputs={"topic": "AI trends in 2024"}) + + # Async iteration over streaming chunks + async for chunk in streaming_output: + print(f"Chunk: {chunk.content}") + + # Access final result after streaming completes + result = streaming_output.result + print(f"Final result: {result.raw}") + +asyncio.run(main()) +``` + +## Potential Use Cases + +- **Parallel Content Generation**: Kickoff multiple independent crews asynchronously, each responsible for generating content on different topics. For example, one crew might research and draft an article on AI trends, while another crew generates social media posts about a new product launch. + +- **Concurrent Market Research Tasks**: Launch multiple crews asynchronously to conduct market research in parallel. One crew might analyze industry trends, while another examines competitor strategies, and yet another evaluates consumer sentiment. + +- **Independent Travel Planning Modules**: Execute separate crews to independently plan different aspects of a trip. One crew might handle flight options, another handles accommodation, and a third plans activities. + +## Choosing Between `akickoff()` and `kickoff_async()` + +| Feature | `akickoff()` | `kickoff_async()` | +|---------|--------------|-------------------| +| Execution model | Native async/await | Thread-based wrapper | +| Task execution | Async with `aexecute_sync()` | Sync in thread pool | +| Memory operations | Async | Sync in thread pool | +| Knowledge retrieval | Async | Sync in thread pool | +| Best for | High-concurrency, I/O-bound workloads | Simple async integration | +| Streaming support | Yes | Yes | diff --git a/docs/v1.15.13/en/learn/kickoff-for-each.mdx b/docs/v1.15.13/en/learn/kickoff-for-each.mdx new file mode 100644 index 0000000000..bded1550b9 --- /dev/null +++ b/docs/v1.15.13/en/learn/kickoff-for-each.mdx @@ -0,0 +1,54 @@ +--- +title: Kickoff Crew for Each +description: Kickoff Crew for Each Item in a List +icon: at +mode: "wide" +--- + +## Introduction + +CrewAI provides the ability to kickoff a crew for each item in a list, allowing you to execute the crew for each item in the list. +This feature is particularly useful when you need to perform the same set of tasks for multiple items. + +## Kicking Off a Crew for Each Item + +To kickoff a crew for each item in a list, use the `kickoff_for_each()` method. +This method executes the crew for each item in the list, allowing you to process multiple items efficiently. + +Here's an example of how to kickoff a crew for each item in a list: + +```python Code +from crewai import Crew, Agent, Task + +# Create an agent with code execution enabled +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task that requires code execution +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age calculated from the dataset" +) + +# Create a crew and add the task +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task], + verbose=True, + memory=False +) + +datasets = [ + { "ages": [25, 30, 35, 40, 45] }, + { "ages": [20, 25, 30, 35, 40] }, + { "ages": [30, 35, 40, 45, 50] } +] + +# Execute the crew +result = analysis_crew.kickoff_for_each(inputs=datasets) +``` \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/litellm-removal-guide.mdx b/docs/v1.15.13/en/learn/litellm-removal-guide.mdx new file mode 100644 index 0000000000..a4fe1de1e8 --- /dev/null +++ b/docs/v1.15.13/en/learn/litellm-removal-guide.mdx @@ -0,0 +1,449 @@ +--- +title: Using CrewAI Without LiteLLM +description: How to use CrewAI with native provider integrations and remove the LiteLLM dependency from your project. +icon: shield-check +mode: "wide" +--- + +## Overview + +CrewAI supports two paths for connecting to LLM providers: + +1. **Native integrations** — direct SDK connections to OpenAI, Anthropic, Google Gemini, Azure OpenAI, and AWS Bedrock +2. **LiteLLM fallback** — a translation layer that supports 100+ additional providers + +This guide explains how to use CrewAI exclusively with native provider integrations, removing any dependency on LiteLLM. + + + The `litellm` package was quarantined on PyPI due to a security/reliability incident. If you rely on LiteLLM-dependent providers, you should migrate to native integrations. CrewAI's native integrations give you full functionality without LiteLLM. + + +## Why Remove LiteLLM? + +- **Reduced dependency surface** — fewer packages means fewer potential supply-chain risks +- **Better performance** — native SDKs communicate directly with provider APIs, eliminating a translation layer +- **Simpler debugging** — one less abstraction layer between your code and the provider +- **Smaller install footprint** — LiteLLM brings in many transitive dependencies + +## Native Providers (No LiteLLM Required) + +These providers use their own SDKs and work without LiteLLM installed: + + + + GPT-4o, GPT-4o-mini, o1, o3-mini, and more. + ```bash + uv add "crewai[openai]" + ``` + + + Claude Sonnet, Claude Haiku, and more. + ```bash + uv add "crewai[anthropic]" + ``` + + + Gemini 2.0 Flash, Gemini 2.0 Pro, and more. + ```bash + uv add "crewai[gemini]" + ``` + + + Azure-hosted OpenAI models. + ```bash + uv add "crewai[azure]" + ``` + + + Claude, Llama, Titan, and more via AWS. + ```bash + uv add "crewai[bedrock]" + ``` + + + + + If you only use native providers, you **never** need to install `crewai[litellm]`. The base `crewai` package plus your chosen provider extra is all you need. + + +## How to Check If You're Using LiteLLM + +### Check your model strings + +If your code uses model prefixes like these, you're routing through LiteLLM: + +| Prefix | Provider | Uses LiteLLM? | +|--------|----------|---------------| +| `ollama/` | Ollama | ✅ Yes | +| `groq/` | Groq | ✅ Yes | +| `together_ai/` | Together AI | ✅ Yes | +| `mistral/` | Mistral | ✅ Yes | +| `cohere/` | Cohere | ✅ Yes | +| `huggingface/` | Hugging Face | ✅ Yes | +| `openai/` | OpenAI | ❌ Native | +| `anthropic/` | Anthropic | ❌ Native | +| `gemini/` | Google Gemini | ❌ Native | +| `azure/` | Azure OpenAI | ❌ Native | +| `bedrock/` | AWS Bedrock | ❌ Native | + +### Check if LiteLLM is installed + +```bash +# Using pip +pip show litellm + +# Using uv +uv pip show litellm +``` + +If the command returns package information, LiteLLM is installed in your environment. + +### Check your dependencies + +Look at your `pyproject.toml` for `crewai[litellm]`: + +```toml +# If you see this, you have LiteLLM as a dependency +dependencies = [ + "crewai[litellm]>=0.100.0", # ← Uses LiteLLM +] + +# Change to a native provider extra instead +dependencies = [ + "crewai[openai]>=0.100.0", # ← Native, no LiteLLM +] +``` + +## Migration Guide + +### Step 1: Identify your current provider + +Find all `LLM()` calls and model strings in your code: + +```bash +# Search your codebase for LLM model strings +grep -r "LLM(" --include="*.py" . +grep -r "llm=" --include="*.yaml" . +grep -r "llm:" --include="*.yaml" . +``` + +### Step 2: Switch to a native provider + + + + ```python + from crewai import LLM + + # Before (LiteLLM): + # llm = LLM(model="groq/llama-3.1-70b") + + # After (Native): + llm = LLM(model="openai/gpt-4o") + ``` + + ```bash + # Install + uv add "crewai[openai]" + + # Set your API key + export OPENAI_API_KEY="sk-..." + ``` + + + ```python + from crewai import LLM + + # Before (LiteLLM): + # llm = LLM(model="together_ai/meta-llama/Meta-Llama-3.1-70B") + + # After (Native): + llm = LLM(model="anthropic/claude-sonnet-4-20250514") + ``` + + ```bash + # Install + uv add "crewai[anthropic]" + + # Set your API key + export ANTHROPIC_API_KEY="sk-ant-..." + ``` + + + ```python + from crewai import LLM + + # Before (LiteLLM): + # llm = LLM(model="mistral/mistral-large-latest") + + # After (Native): + llm = LLM(model="gemini/gemini-2.0-flash") + ``` + + ```bash + # Install + uv add "crewai[gemini]" + + # Set your API key + export GEMINI_API_KEY="..." + ``` + + + ```python + from crewai import LLM + + # After (Native): + llm = LLM( + model="azure/your-deployment-name", + api_key="your-azure-api-key", + base_url="https://your-resource.openai.azure.com", + api_version="2024-06-01" + ) + ``` + + ```bash + # Install + uv add "crewai[azure]" + ``` + + + ```python + from crewai import LLM + + # After (Native): + llm = LLM( + model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0", + aws_region_name="us-east-1" + ) + ``` + + ```bash + # Install + uv add "crewai[bedrock]" + + # Configure AWS credentials + export AWS_ACCESS_KEY_ID="..." + export AWS_SECRET_ACCESS_KEY="..." + export AWS_DEFAULT_REGION="us-east-1" + ``` + + + +### Step 3: Keep Ollama without LiteLLM + +If you're using Ollama and want to keep using it, you can connect via Ollama's OpenAI-compatible API: + +```python +from crewai import LLM + +# Before (LiteLLM): +# llm = LLM(model="ollama/llama3") + +# After (OpenAI-compatible mode, no LiteLLM needed): +llm = LLM( + model="llama3", + custom_openai=True, + base_url="http://localhost:11434/v1", + api_key="ollama" # Ollama doesn't require a real API key +) +``` + + + Many local inference servers (Ollama, vLLM, LM Studio, llama.cpp) expose an OpenAI-compatible API. You can use `custom_openai=True` with a custom `base_url` to connect to any of them natively while keeping the model ID your gateway expects. + + +### Step 4: Update your YAML configs + +```yaml +# Before (LiteLLM providers): +researcher: + role: Research Specialist + goal: Conduct research + backstory: A dedicated researcher + llm: groq/llama-3.1-70b # ← LiteLLM + +# After (Native provider): +researcher: + role: Research Specialist + goal: Conduct research + backstory: A dedicated researcher + llm: openai/gpt-4o # ← Native +``` + +### Step 5: Remove LiteLLM + +Once you've migrated all your model references: + +```bash +# Remove litellm from your project +uv remove litellm + +# Or if using pip +pip uninstall litellm + +# Update your pyproject.toml: change crewai[litellm] to your provider extra +# e.g., crewai[openai], crewai[anthropic], crewai[gemini] +``` + +### Step 6: Verify + +Run your project and confirm everything works: + +```bash +# Run your crew +crewai run + +# Or run your tests +uv run pytest +``` + +## Custom OpenAI-Compatible Endpoints + +Many providers and local servers (Ollama, vLLM, LM Studio, llama.cpp, LiteLLM proxies, and hosted gateways) expose an **OpenAI-compatible** API. Instead of routing these through LiteLLM, you can talk to them directly with CrewAI's native OpenAI integration by setting `custom_openai=True`. + +This is the recommended replacement for any LiteLLM provider that offers an OpenAI-compatible endpoint. + +### How it works + +- `custom_openai=True` forces CrewAI to use the native OpenAI SDK, regardless of the model name. +- The model ID is passed to the endpoint without validation against OpenAI's known-model list. This lets you use arbitrary model IDs your gateway expects (for example, `anthropic/claude-sonnet-4-6` served behind an OpenAI-compatible proxy). An optional leading `openai/` routing prefix is stripped. +- A base URL is **required**. CrewAI resolves it, in order, from: + 1. `base_url=...` + 2. `api_base=...` + 3. `OPENAI_BASE_URL` environment variable + 4. `OPENAI_API_BASE` environment variable (legacy) + + If none are set, CrewAI raises a `ValueError` so misconfiguration fails fast instead of silently hitting `api.openai.com`. + +```python +from crewai import LLM + +llm = LLM( + model="anthropic/claude-sonnet-4-6", # passed through as-is + custom_openai=True, + base_url="https://your-gateway.example/v1", + api_key="your-key", +) +``` + +### Connect to common servers + + + + ```python + from crewai import LLM + + llm = LLM( + model="llama3.2:latest", + custom_openai=True, + base_url="http://localhost:11434/v1", + api_key="ollama", # Ollama ignores it, but the client requires a value + ) + ``` + + + ```python + from crewai import LLM + + llm = LLM( + model="meta-llama/Meta-Llama-3.1-8B-Instruct", + custom_openai=True, + base_url="http://localhost:8000/v1", + api_key="not-needed", + ) + ``` + + + ```python + from crewai import LLM + + llm = LLM( + model="your-loaded-model", + custom_openai=True, + base_url="http://localhost:1234/v1", + api_key="lm-studio", + ) + ``` + + + ```bash + export OPENAI_BASE_URL="https://your-gateway.example/v1" + export OPENAI_API_KEY="your-key" + ``` + ```python + from crewai import LLM + + # base_url is picked up from OPENAI_BASE_URL / OPENAI_API_BASE + llm = LLM(model="anthropic/claude-sonnet-4-6", custom_openai=True) + ``` + + + + + If you use the `openai/` prefix with a model that isn't a known OpenAI model and pass `base_url` or `api_base` directly, CrewAI automatically treats it as a custom OpenAI-compatible endpoint. Environment variables alone do not enable automatic routing for unknown models; set `custom_openai=True` when configuring the endpoint through `OPENAI_BASE_URL` or `OPENAI_API_BASE`. + + +## Quick Reference: Model String Mapping + +Here are common migration paths from LiteLLM-dependent providers to native ones: + +```python +from crewai import LLM + +# ─── LiteLLM providers → Native alternatives ──────────────────── + +# Groq → OpenAI or Anthropic +# llm = LLM(model="groq/llama-3.1-70b") +llm = LLM(model="openai/gpt-4o-mini") # Fast & affordable +llm = LLM(model="anthropic/claude-haiku-3-5") # Fast & affordable + +# Together AI → OpenAI or Gemini +# llm = LLM(model="together_ai/meta-llama/Meta-Llama-3.1-70B") +llm = LLM(model="openai/gpt-4o") # High quality +llm = LLM(model="gemini/gemini-2.0-flash") # Fast & capable + +# Mistral → Anthropic or OpenAI +# llm = LLM(model="mistral/mistral-large-latest") +llm = LLM(model="anthropic/claude-sonnet-4-20250514") # High quality + +# Ollama → OpenAI-compatible (keep using local models) +# llm = LLM(model="ollama/llama3") +llm = LLM( + model="llama3", + custom_openai=True, + base_url="http://localhost:11434/v1", + api_key="ollama" +) +``` + +## FAQ + + + + No, if you use one of the five natively supported providers (OpenAI, Anthropic, Gemini, Azure, Bedrock). These native integrations support all CrewAI features including streaming, tool calling, structured output, and more. You only lose access to providers that are exclusively available through LiteLLM (like Groq, Together AI, Mistral as first-class providers). + + + Yes. Install multiple extras and use different providers for different agents: + ```bash + uv add "crewai[openai,anthropic,gemini]" + ``` + ```python + researcher = Agent(llm="openai/gpt-4o", ...) + writer = Agent(llm="anthropic/claude-sonnet-4-20250514", ...) + ``` + + + Regardless of quarantine status, reducing your dependency surface is good security practice. If you only need providers that CrewAI supports natively, there's no reason to keep LiteLLM installed. + + + Native providers use the same environment variables you're already familiar with. No changes needed for `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, etc. + + + Most of these providers expose an OpenAI-compatible API. Use `custom_openai=True` with their base URL and API key — see [Custom OpenAI-Compatible Endpoints](#custom-openai-compatible-endpoints). For example, Groq: `LLM(model="llama-3.1-70b-versatile", custom_openai=True, base_url="https://api.groq.com/openai/v1", api_key="...")`. The model ID is passed through untouched, so use whatever ID the provider expects. + + + +## Related Resources + +- [LLM Connections](/en/learn/llm-connections) — Full guide to connecting CrewAI with any LLM +- [LLM Concepts](/en/concepts/llms) — Understanding LLMs in CrewAI +- [LLM Selection Guide](/en/learn/llm-selection-guide) — Choosing the right model for your use case diff --git a/docs/v1.15.13/en/learn/llm-connections.mdx b/docs/v1.15.13/en/learn/llm-connections.mdx new file mode 100644 index 0000000000..2b7a5d278b --- /dev/null +++ b/docs/v1.15.13/en/learn/llm-connections.mdx @@ -0,0 +1,214 @@ +--- +title: Connect to any LLM +description: Comprehensive guide on integrating CrewAI with various Large Language Models (LLMs) using LiteLLM, including supported providers and configuration options. +icon: brain-circuit +mode: "wide" +--- + +## Connect CrewAI to LLMs + +CrewAI connects to LLMs through native SDK integrations for the most popular providers (OpenAI, Anthropic, Google Gemini, Azure, and AWS Bedrock), and uses LiteLLM as a flexible fallback for all other providers. + + + By default, CrewAI uses the `gpt-4o-mini` model. This is determined by the `OPENAI_MODEL_NAME` environment variable, which defaults to "gpt-4o-mini" if not set. + You can easily configure your agents to use a different model or provider as described in this guide. + + +## Supported Providers + +LiteLLM supports a wide range of providers, including but not limited to: + +- OpenAI +- Anthropic +- Google (Vertex AI, Gemini) +- Azure OpenAI +- AWS (Bedrock, SageMaker) +- Cohere +- VoyageAI +- Hugging Face +- Ollama +- Mistral AI +- Replicate +- Together AI +- AI21 +- Cloudflare Workers AI +- DeepInfra +- Groq +- SambaNova +- Nebius AI Studio +- [NVIDIA NIMs](https://docs.api.nvidia.com/nim/reference/models-1) +- And many more! + +For a complete and up-to-date list of supported providers, please refer to the [LiteLLM Providers documentation](https://docs.litellm.ai/docs/providers). + + + To use any provider not covered by a native integration, add LiteLLM as a dependency to your project: + ```bash + uv add 'crewai[litellm]' + ``` + Native providers (OpenAI, Anthropic, Google Gemini, Azure, AWS Bedrock) use their own SDK extras — see the [Provider Configuration Examples](/en/concepts/llms#provider-configuration-examples). + + +## Changing the LLM + +To use a different LLM with your CrewAI agents, you have several options: + + + + Pass the model name as a string when initializing the agent: + + ```python Code + from crewai import Agent + + # Using OpenAI's GPT-4 + openai_agent = Agent( + role='OpenAI Expert', + goal='Provide insights using GPT-4', + backstory="An AI assistant powered by OpenAI's latest model.", + llm='gpt-4' + ) + + # Using Anthropic's Claude + claude_agent = Agent( + role='Anthropic Expert', + goal='Analyze data using Claude', + backstory="An AI assistant leveraging Anthropic's language model.", + llm='claude-2' + ) + ``` + + + + For more detailed configuration, use the LLM class: + + ```python Code + from crewai import Agent, LLM + + llm = LLM( + model="gpt-4", + temperature=0.7, + base_url="https://api.openai.com/v1", + api_key="your-api-key-here" + ) + + agent = Agent( + role='Customized LLM Expert', + goal='Provide tailored responses', + backstory="An AI assistant with custom LLM settings.", + llm=llm + ) + ``` + + + + +## Configuration Options + +When configuring an LLM for your agent, you have access to a wide range of parameters: + +| Parameter | Type | Description | +|:----------|:-----:|:-------------| +| **model** | `str` | The name of the model to use (e.g., "gpt-4", "claude-2") | +| **temperature** | `float` | Controls randomness in output (0.0 to 1.0) | +| **max_tokens** | `int` | Maximum number of tokens to generate | +| **top_p** | `float` | Controls diversity of output (0.0 to 1.0) | +| **frequency_penalty** | `float` | Penalizes new tokens based on their frequency in the text so far | +| **presence_penalty** | `float` | Penalizes new tokens based on their presence in the text so far | +| **stop** | `str`, `List[str]` | Sequence(s) to stop generation | +| **base_url** | `str` | The base URL for the API endpoint | +| **api_key** | `str` | Your API key for authentication | + +For a complete list of parameters and their descriptions, refer to the LLM class documentation. + +## Connecting to OpenAI-Compatible LLMs + +You can connect to OpenAI-compatible LLMs using either environment variables or by setting specific attributes on the LLM class: + + + + + ```python Generic + import os + + os.environ["OPENAI_API_KEY"] = "your-api-key" + os.environ["OPENAI_API_BASE"] = "https://api.your-provider.com/v1" + os.environ["OPENAI_MODEL_NAME"] = "your-model-name" + ``` + + ```python Google + import os + + # Example using Gemini's OpenAI-compatible API. + os.environ["OPENAI_API_KEY"] = "your-gemini-key" # Should start with AIza... + os.environ["OPENAI_API_BASE"] = "https://generativelanguage.googleapis.com/v1beta/openai/" + os.environ["OPENAI_MODEL_NAME"] = "openai/gemini-2.0-flash" # Add your Gemini model here, under openai/ + ``` + + + + + ```python Generic + llm = LLM( + model="custom-model-name", + api_key="your-api-key", + base_url="https://api.your-provider.com/v1" + ) + agent = Agent(llm=llm, ...) + ``` + + ```python Google + # Example using Gemini's OpenAI-compatible API + llm = LLM( + model="openai/gemini-2.0-flash", + base_url="https://generativelanguage.googleapis.com/v1beta/openai/", + api_key="your-gemini-key", # Should start with AIza... + ) + agent = Agent(llm=llm, ...) + ``` + + + + +## Using Local Models with Ollama + +For local models like those provided by Ollama: + + + + [Click here to download and install Ollama](https://ollama.com/download) + + + For example, run `ollama pull llama3.2` to download the model. + + + + ```python Code + agent = Agent( + role='Local AI Expert', + goal='Process information using a local model', + backstory="An AI assistant running on local hardware.", + llm=LLM(model="ollama/llama3.2", base_url="http://localhost:11434") + ) + ``` + + + + +## Changing the Base API URL + +You can change the base API URL for any LLM provider by setting the `base_url` parameter: + +```python Code +llm = LLM( + model="custom-model-name", + base_url="https://api.your-provider.com/v1", + api_key="your-api-key" +) +agent = Agent(llm=llm, ...) +``` + +This is particularly useful when working with OpenAI-compatible APIs or when you need to specify a different endpoint for your chosen provider. + +## Conclusion + +By leveraging LiteLLM, CrewAI offers seamless integration with a vast array of LLMs. This flexibility allows you to choose the most suitable model for your specific needs, whether you prioritize performance, cost-efficiency, or local deployment. Remember to consult the [LiteLLM documentation](https://docs.litellm.ai/docs/) for the most up-to-date information on supported models and configuration options. diff --git a/docs/v1.15.13/en/learn/llm-hooks.mdx b/docs/v1.15.13/en/learn/llm-hooks.mdx new file mode 100644 index 0000000000..7380973853 --- /dev/null +++ b/docs/v1.15.13/en/learn/llm-hooks.mdx @@ -0,0 +1,282 @@ +--- +title: LLM Call Hooks +description: Learn how to use LLM call hooks to intercept, modify, and control language model interactions in CrewAI +mode: "wide" +--- + +LLM Call Hooks provide fine-grained control over language model interactions +during agent execution. These hooks allow you to intercept LLM calls, modify +prompts, transform responses, implement approval gates, and add custom logging +or monitoring. + +## Overview + +LLM hooks are executed at two interception points: + +| Point | When | Hook receives | +|-------|------|---------------| +| `PRE_MODEL_CALL` | Before every LLM call | `LLMCallHookContext` | +| `POST_MODEL_CALL` | After every LLM call | `LLMCallHookContext` (with `response` set) | + +Write them with the [`@on` decorator](/edge/en/learn/execution-hooks). The +[legacy `@before_llm_call` / `@after_llm_call` decorators](#legacy-decorators) +keep working unchanged — both styles register on the same engine and run in one +ordered chain. + +## Hook Signature + +```python +from crewai.hooks import on, HookAborted, InterceptionPoint, LLMCallHookContext + +@on(InterceptionPoint.PRE_MODEL_CALL) +def before_hook(ctx: LLMCallHookContext) -> None: + # Mutate ctx.messages in place, or + # raise HookAborted(reason, source) to block the call + ... + +@on(InterceptionPoint.POST_MODEL_CALL) +def after_hook(ctx: LLMCallHookContext) -> str | None: + # Return a string to replace ctx.response + # Return None to keep the original response + ... +``` + +Unlike the boundary and step points, the model-call points pass the rich +`LLMCallHookContext` directly as the hook argument (there is no separate +`ctx.payload`): mutate `ctx.messages` in place before the call, and return a +string to replace the response after it. + +Blocking a call raises `ValueError("LLM call blocked by before_llm_call hook")` +inside the executor; the `HookAborted` reason and source are recorded in +[telemetry](/edge/en/learn/execution-hooks#telemetry). + +## LLM Hook Context + +The `LLMCallHookContext` object provides comprehensive access to execution state: + +```python +class LLMCallHookContext: + executor: CrewAgentExecutor | LiteAgent | None # Executor (None for direct LLM calls) + messages: list # Mutable message list + agent: Agent | None # Current agent (None for direct LLM calls) + task: Task | None # Current task (None for direct calls or LiteAgent) + crew: Crew | None # Crew instance (None for direct calls or LiteAgent) + llm: BaseLLM | None # LLM instance + iterations: int # Current iteration count (0 for direct calls) + response: str | None # LLM response (POST_MODEL_CALL only) +``` + +The context also exposes `request_human_input(prompt, default_message)`, which +pauses live console updates and collects input from the terminal — useful for +approval gates. + +### Modifying Messages + +**Important:** Always modify messages in-place: + +```python +# ✅ Correct - modify in-place +@on(InterceptionPoint.PRE_MODEL_CALL) +def add_context(ctx: LLMCallHookContext) -> None: + ctx.messages.append({"role": "system", "content": "Be concise"}) + +# ❌ Wrong - replaces list reference and breaks the executor +@on(InterceptionPoint.PRE_MODEL_CALL) +def wrong_approach(ctx: LLMCallHookContext) -> None: + ctx.messages = [{"role": "system", "content": "Be concise"}] +``` + +## Registration Methods + +### 1. Global Hooks + +Apply to all LLM calls across all crews. Use the `agents=` filter to scope a +hook to specific agent roles: + +```python +from crewai.hooks import on, InterceptionPoint + +@on(InterceptionPoint.PRE_MODEL_CALL) +def log_llm_call(ctx): + print(f"LLM call by {ctx.agent.role} at iteration {ctx.iterations}") + +@on(InterceptionPoint.POST_MODEL_CALL, agents=["Researcher"]) +def log_researcher_responses(ctx): + print(f"Response length: {len(ctx.response)}") +``` + +### 2. Crew-Scoped Hooks + +Apply the same decorator to a method inside a `@CrewBase` class to scope the +hook to that crew only: + +```python +from crewai.hooks import on, InterceptionPoint + +@CrewBase +class MyProjCrew: + @on(InterceptionPoint.PRE_MODEL_CALL) + def validate_inputs(self, ctx): + # Only applies to this crew + if ctx.iterations == 0: + print(f"Starting task: {ctx.task.description}") + + @crew + def crew(self) -> Crew: + return Crew(agents=self.agents, tasks=self.tasks, process=Process.sequential) +``` + +## Common Use Cases + +### 1. Iteration Limiting + +```python +@on(InterceptionPoint.PRE_MODEL_CALL) +def limit_iterations(ctx: LLMCallHookContext) -> None: + if ctx.iterations > 15: + raise HookAborted(reason="exceeded 15 iterations", source="loop-guard") +``` + +### 2. Human Approval Gate + +```python +@on(InterceptionPoint.PRE_MODEL_CALL) +def require_approval(ctx: LLMCallHookContext) -> None: + if ctx.iterations > 5: + response = ctx.request_human_input( + prompt=f"Iteration {ctx.iterations}: Approve LLM call?", + default_message="Press Enter to approve, or type 'no' to block:", + ) + if response.lower() == "no": + raise HookAborted(reason="blocked by user", source="approval-gate") +``` + +### 3. Adding System Context + +```python +@on(InterceptionPoint.PRE_MODEL_CALL) +def add_guardrails(ctx: LLMCallHookContext) -> None: + ctx.messages.append({ + "role": "system", + "content": "Ensure responses are factual and cite sources when possible." + }) +``` + +### 4. Response Sanitization + +```python +import re + +@on(InterceptionPoint.POST_MODEL_CALL) +def sanitize_sensitive_data(ctx: LLMCallHookContext) -> str | None: + if not ctx.response: + return None + sanitized = re.sub(r'\b\d{3}-\d{2}-\d{4}\b', '[SSN-REDACTED]', ctx.response) + return re.sub(r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', '[CARD-REDACTED]', sanitized) +``` + +### 5. Debug Logging + +```python +@on(InterceptionPoint.PRE_MODEL_CALL) +def debug_request(ctx: LLMCallHookContext) -> None: + print(f"Agent: {ctx.agent.role}, iteration {ctx.iterations}, " + f"{len(ctx.messages)} messages") + +@on(InterceptionPoint.POST_MODEL_CALL) +def debug_response(ctx: LLMCallHookContext) -> None: + if ctx.response: + print(f"Response preview: {ctx.response[:100]}...") +``` + +## Hook Management + +```python +from crewai.hooks import ( + InterceptionPoint, + clear_all_hooks, + clear_hooks, + get_hooks, + unregister_hook, +) + +# Unregister a specific hook +unregister_hook(InterceptionPoint.PRE_MODEL_CALL, my_hook) + +# Clear one point, or everything (e.g. between tests) +clear_hooks(InterceptionPoint.POST_MODEL_CALL) +clear_all_hooks() + +# Inspect what's registered +print(len(get_hooks(InterceptionPoint.PRE_MODEL_CALL))) +``` + +The legacy management API (`register_before_llm_call_hook`, +`unregister_before_llm_call_hook`, `clear_before_llm_call_hooks`, +`clear_all_llm_call_hooks`, `get_before_llm_call_hooks`, and their `after_` +counterparts) operates on the same underlying registries, so either API can +manage hooks registered by the other. + +## Legacy Decorators + +The original per-point decorators keep working unchanged and run in the same +registration-order chain as `@on` hooks: + +```python +from crewai.hooks import before_llm_call, after_llm_call + +@before_llm_call +def validate_iteration_count(context): + if context.iterations > 10: + return False # Block execution + return None + +@after_llm_call(agents=["Researcher"]) +def sanitize_response(context): + if context.response and "API_KEY" in context.response: + return context.response.replace("API_KEY", "[REDACTED]") + return None +``` + +Differences from `@on`: + +- **Blocking** is `return False` from a before hook — equivalent to raising + `HookAborted`, but without a custom reason or source for telemetry. +- **Signatures** are point-specific: before hooks return `bool | None`, after + hooks return `str | None`. The context object is the same + `LLMCallHookContext`. +- **Filters and crew-scoping** work the same way: `@before_llm_call(agents=[...])`, + and applying the decorator to a `@CrewBase` method scopes it to that crew. + +Prefer `@on` for new code; keep the legacy style where it is already in use — +there is no behavioral penalty. + +## Best Practices + +1. **Keep hooks focused and fast** — they run on every LLM call +2. **Modify in-place** — always mutate `ctx.messages`, never replace the list +3. **Use type hints** — annotate with `LLMCallHookContext` for IDE support +4. **Abort loudly** — raise `HookAborted` with a meaningful reason and source; + any other exception is swallowed (fail-open) +5. **Clear hooks in tests** — call `clear_all_hooks()` between test runs + +## Troubleshooting + +### Hook Not Executing +- Verify the hook is registered before crew execution +- Check whether an earlier hook aborted (subsequent hooks don't run) + +### Message Modifications Not Persisting +- Use in-place modifications: `ctx.messages.append(...)` +- Don't replace the list: `ctx.messages = []` + +### Response Modifications Not Working +- Return the modified string from a `POST_MODEL_CALL` hook +- Returning `None` keeps the original response + +## Related Documentation + +- [Execution Hooks Overview →](/edge/en/learn/execution-hooks) +- [Tool Call Hooks →](/edge/en/learn/tool-hooks) +- [Execution Boundary Hooks →](/edge/en/learn/execution-boundary-hooks) +- [Step Hooks →](/edge/en/learn/step-hooks) diff --git a/docs/v1.15.13/en/learn/llm-selection-guide.mdx b/docs/v1.15.13/en/learn/llm-selection-guide.mdx new file mode 100644 index 0000000000..30a85462b8 --- /dev/null +++ b/docs/v1.15.13/en/learn/llm-selection-guide.mdx @@ -0,0 +1,824 @@ +--- +title: "Strategic LLM Selection Guide" +description: "Strategic framework for choosing the right LLM for your CrewAI AI agents and writing effective task and agent definitions" +icon: "brain-circuit" +mode: "wide" +--- + +## The CrewAI Approach to LLM Selection + +Rather than prescriptive model recommendations, we advocate for a **thinking framework** that helps you make informed decisions based on your specific use case, constraints, and requirements. The LLM landscape evolves rapidly, with new models emerging regularly and existing ones being updated frequently. What matters most is developing a systematic approach to evaluation that remains relevant regardless of which specific models are available. + + + This guide focuses on strategic thinking rather than specific model + recommendations, as the LLM landscape evolves rapidly. + + +## Quick Decision Framework + + + + Begin by deeply understanding what your tasks actually require. Consider the + cognitive complexity involved, the depth of reasoning needed, the format of + expected outputs, and the amount of context the model will need to process. + This foundational analysis will guide every subsequent decision. + + + Once you understand your requirements, map them to model strengths. + Different model families excel at different types of work; some are + optimized for reasoning and analysis, others for creativity and content + generation, and others for speed and efficiency. + + + Factor in your real-world operational constraints including budget + limitations, latency requirements, data privacy needs, and infrastructure + capabilities. The theoretically best model may not be the practically best + choice for your situation. + + + Start with reliable, well-understood models and optimize based on actual + performance in your specific use case. Real-world results often differ from + theoretical benchmarks, so empirical testing is crucial. + + + +## Core Selection Framework + +### a. Task-First Thinking + +The most critical step in LLM selection is understanding what your task actually demands. Too often, teams select models based on general reputation or benchmark scores without carefully analyzing their specific requirements. This approach leads to either over-engineering simple tasks with expensive, complex models, or under-powering sophisticated work with models that lack the necessary capabilities. + + + + - **Simple Tasks** represent the majority of everyday AI work and include basic instruction following, straightforward data processing, and simple formatting operations. These tasks typically have clear inputs and outputs with minimal ambiguity. The cognitive load is low, and the model primarily needs to follow explicit instructions rather than engage in complex reasoning. + + - **Complex Tasks** require multi-step reasoning, strategic thinking, and the ability to handle ambiguous or incomplete information. These might involve analyzing multiple data sources, developing comprehensive strategies, or solving problems that require breaking down into smaller components. The model needs to maintain context across multiple reasoning steps and often must make inferences that aren't explicitly stated. + + - **Creative Tasks** demand a different type of cognitive capability focused on generating novel, engaging, and contextually appropriate content. This includes storytelling, marketing copy creation, and creative problem-solving. The model needs to understand nuance, tone, and audience while producing content that feels authentic and engaging rather than formulaic. + + + + + - **Structured Data** tasks require precision and consistency in format adherence. When working with JSON, XML, or database formats, the model must reliably produce syntactically correct output that can be programmatically processed. These tasks often have strict validation requirements and little tolerance for format errors, making reliability more important than creativity. + + - **Creative Content** outputs demand a balance of technical competence and creative flair. The model needs to understand audience, tone, and brand voice while producing content that engages readers and achieves specific communication goals. Quality here is often subjective and requires models that can adapt their writing style to different contexts and purposes. + + - **Technical Content** sits between structured data and creative content, requiring both precision and clarity. Documentation, code generation, and technical analysis need to be accurate and comprehensive while remaining accessible to the intended audience. The model must understand complex technical concepts and communicate them effectively. + + + + + - **Short Context** scenarios involve focused, immediate tasks where the model needs to process limited information quickly. These are often transactional interactions where speed and efficiency matter more than deep understanding. The model doesn't need to maintain extensive conversation history or process large documents. + + - **Long Context** requirements emerge when working with substantial documents, extended conversations, or complex multi-part tasks. The model needs to maintain coherence across thousands of tokens while referencing earlier information accurately. This capability becomes crucial for document analysis, comprehensive research, and sophisticated dialogue systems. + + - **Very Long Context** scenarios push the boundaries of what's currently possible, involving massive document processing, extensive research synthesis, or complex multi-session interactions. These use cases require models specifically designed for extended context handling and often involve trade-offs between context length and processing speed. + + + + +### b. Model Capability Mapping + +Understanding model capabilities requires looking beyond marketing claims and benchmark scores to understand the fundamental strengths and limitations of different model architectures and training approaches. + + + + Reasoning models represent a specialized category designed specifically for complex, multi-step thinking tasks. These models excel when problems require careful analysis, strategic planning, or systematic problem decomposition. They typically employ techniques like chain-of-thought reasoning or tree-of-thought processing to work through complex problems step by step. + + The strength of reasoning models lies in their ability to maintain logical consistency across extended reasoning chains and to break down complex problems into manageable components. They're particularly valuable for strategic planning, complex analysis, and situations where the quality of reasoning matters more than speed of response. + + However, reasoning models often come with trade-offs in terms of speed and cost. They may also be less suitable for creative tasks or simple operations where their sophisticated reasoning capabilities aren't needed. Consider these models when your tasks involve genuine complexity that benefits from systematic, step-by-step analysis. + + + + + General purpose models offer the most balanced approach to LLM selection, providing solid performance across a wide range of tasks without extreme specialization in any particular area. These models are trained on diverse datasets and optimized for versatility rather than peak performance in specific domains. + + The primary advantage of general purpose models is their reliability and predictability across different types of work. They handle most standard business tasks competently, from research and analysis to content creation and data processing. This makes them excellent choices for teams that need consistent performance across varied workflows. + + While general purpose models may not achieve the peak performance of specialized alternatives in specific domains, they offer operational simplicity and reduced complexity in model management. They're often the best starting point for new projects, allowing teams to understand their specific needs before potentially optimizing with more specialized models. + + + + + Fast and efficient models prioritize speed, cost-effectiveness, and resource efficiency over sophisticated reasoning capabilities. These models are optimized for high-throughput scenarios where quick responses and low operational costs are more important than nuanced understanding or complex reasoning. + + These models excel in scenarios involving routine operations, simple data processing, function calling, and high-volume tasks where the cognitive requirements are relatively straightforward. They're particularly valuable for applications that need to process many requests quickly or operate within tight budget constraints. + + The key consideration with efficient models is ensuring that their capabilities align with your task requirements. While they can handle many routine operations effectively, they may struggle with tasks requiring nuanced understanding, complex reasoning, or sophisticated content generation. They're best used for well-defined, routine operations where speed and cost matter more than sophistication. + + + + + Creative models are specifically optimized for content generation, writing quality, and creative thinking tasks. These models typically excel at understanding nuance, tone, and style while producing engaging, contextually appropriate content that feels natural and authentic. + + The strength of creative models lies in their ability to adapt writing style to different audiences, maintain consistent voice and tone, and generate content that engages readers effectively. They often perform better on tasks involving storytelling, marketing copy, brand communications, and other content where creativity and engagement are primary goals. + + When selecting creative models, consider not just their ability to generate text, but their understanding of audience, context, and purpose. The best creative models can adapt their output to match specific brand voices, target different audience segments, and maintain consistency across extended content pieces. + + + + + Open source models offer unique advantages in terms of cost control, customization potential, data privacy, and deployment flexibility. These models can be run locally or on private infrastructure, providing complete control over data handling and model behavior. + + The primary benefits of open source models include elimination of per-token costs, ability to fine-tune for specific use cases, complete data privacy, and independence from external API providers. They're particularly valuable for organizations with strict data privacy requirements, budget constraints, or specific customization needs. + + However, open source models require more technical expertise to deploy and maintain effectively. Teams need to consider infrastructure costs, model management complexity, and the ongoing effort required to keep models updated and optimized. The total cost of ownership may be higher than cloud-based alternatives when factoring in technical overhead. + + + + +## Strategic Configuration Patterns + +### a. Multi-Model Approach + + + Use different models for different purposes within the same crew to optimize + both performance and cost. + + +The most sophisticated CrewAI implementations often employ multiple models strategically, assigning different models to different agents based on their specific roles and requirements. This approach allows teams to optimize for both performance and cost by using the most appropriate model for each type of work. + +Planning agents benefit from reasoning models that can handle complex strategic thinking and multi-step analysis. These agents often serve as the "brain" of the operation, developing strategies and coordinating other agents' work. Content agents, on the other hand, perform best with creative models that excel at writing quality and audience engagement. Processing agents handling routine operations can use efficient models that prioritize speed and cost-effectiveness. + +**Example: Research and Analysis Crew** + +```python +from crewai import Agent, Task, Crew, LLM + +# High-capability reasoning model for strategic planning +manager_llm = LLM(model="gemini-2.5-flash-preview-05-20", temperature=0.1) + +# Creative model for content generation +content_llm = LLM(model="claude-3-5-sonnet-20241022", temperature=0.7) + +# Efficient model for data processing +processing_llm = LLM(model="gpt-4o-mini", temperature=0) + +research_manager = Agent( + role="Research Strategy Manager", + goal="Develop comprehensive research strategies and coordinate team efforts", + backstory="Expert research strategist with deep analytical capabilities", + llm=manager_llm, # High-capability model for complex reasoning + verbose=True +) + +content_writer = Agent( + role="Research Content Writer", + goal="Transform research findings into compelling, well-structured reports", + backstory="Skilled writer who excels at making complex topics accessible", + llm=content_llm, # Creative model for engaging content + verbose=True +) + +data_processor = Agent( + role="Data Analysis Specialist", + goal="Extract and organize key data points from research sources", + backstory="Detail-oriented analyst focused on accuracy and efficiency", + llm=processing_llm, # Fast, cost-effective model for routine tasks + verbose=True +) + +crew = Crew( + agents=[research_manager, content_writer, data_processor], + tasks=[...], # Your specific tasks + manager_llm=manager_llm, # Manager uses the reasoning model + verbose=True +) +``` + +The key to successful multi-model implementation is understanding how different agents interact and ensuring that model capabilities align with agent responsibilities. This requires careful planning but can result in significant improvements in both output quality and operational efficiency. + +### b. Component-Specific Selection + + + + The manager LLM plays a crucial role in hierarchical CrewAI processes, serving as the coordination point for multiple agents and tasks. This model needs to excel at delegation, task prioritization, and maintaining context across multiple concurrent operations. + + Effective manager LLMs require strong reasoning capabilities to make good delegation decisions, consistent performance to ensure predictable coordination, and excellent context management to track the state of multiple agents simultaneously. The model needs to understand the capabilities and limitations of different agents while optimizing task allocation for efficiency and quality. + + Cost considerations are particularly important for manager LLMs since they're involved in every operation. The model needs to provide sufficient capability for effective coordination while remaining cost-effective for frequent use. This often means finding models that offer good reasoning capabilities without the premium pricing of the most sophisticated options. + + + + + Function calling LLMs handle tool usage across all agents, making them critical for crews that rely heavily on external tools and APIs. These models need to excel at understanding tool capabilities, extracting parameters accurately, and handling tool responses effectively. + + The most important characteristics for function calling LLMs are precision and reliability rather than creativity or sophisticated reasoning. The model needs to consistently extract the correct parameters from natural language requests and handle tool responses appropriately. Speed is also important since tool usage often involves multiple round trips that can impact overall performance. + + Many teams find that specialized function calling models or general purpose models with strong tool support work better than creative or reasoning-focused models for this role. The key is ensuring that the model can reliably bridge the gap between natural language instructions and structured tool calls. + + + + + Individual agents can override crew-level LLM settings when their specific needs differ significantly from the general crew requirements. This capability allows for fine-tuned optimization while maintaining operational simplicity for most agents. + + Consider agent-specific overrides when an agent's role requires capabilities that differ substantially from other crew members. For example, a creative writing agent might benefit from a model optimized for content generation, while a data analysis agent might perform better with a reasoning-focused model. + + The challenge with agent-specific overrides is balancing optimization with operational complexity. Each additional model adds complexity to deployment, monitoring, and cost management. Teams should focus overrides on agents where the performance improvement justifies the additional complexity. + + + + +## Task Definition Framework + +### a. Focus on Clarity Over Complexity + +Effective task definition is often more important than model selection in determining the quality of CrewAI outputs. Well-defined tasks provide clear direction and context that enable even modest models to perform well, while poorly defined tasks can cause even sophisticated models to produce unsatisfactory results. + + + + The best task descriptions strike a balance between providing sufficient detail and maintaining clarity. They should define the specific objective clearly enough that there's no ambiguity about what success looks like, while explaining the approach or methodology in enough detail that the agent understands how to proceed. + + Effective task descriptions include relevant context and constraints that help the agent understand the broader purpose and any limitations they need to work within. They break complex work into focused steps that can be executed systematically, rather than presenting overwhelming, multi-faceted objectives that are difficult to approach systematically. + + Common mistakes include being too vague about objectives, failing to provide necessary context, setting unclear success criteria, or combining multiple unrelated tasks into a single description. The goal is to provide enough information for the agent to succeed while maintaining focus on a single, clear objective. + + + + + Expected output guidelines serve as a contract between the task definition and the agent, clearly specifying what the deliverable should look like and how it will be evaluated. These guidelines should describe both the format and structure needed, as well as the key elements that must be included for the output to be considered complete. + + The best output guidelines provide concrete examples of quality indicators and define completion criteria clearly enough that both the agent and human reviewers can assess whether the task has been completed successfully. This reduces ambiguity and helps ensure consistent results across multiple task executions. + + Avoid generic output descriptions that could apply to any task, missing format specifications that leave agents guessing about structure, unclear quality standards that make evaluation difficult, or failing to provide examples or templates that help agents understand expectations. + + + + +### b. Task Sequencing Strategy + + + + Sequential task dependencies are essential when tasks build upon previous outputs, information flows from one task to another, or quality depends on the completion of prerequisite work. This approach ensures that each task has access to the information and context it needs to succeed. + + Implementing sequential dependencies effectively requires using the context parameter to chain related tasks, building complexity gradually through task progression, and ensuring that each task produces outputs that serve as meaningful inputs for subsequent tasks. The goal is to maintain logical flow between dependent tasks while avoiding unnecessary bottlenecks. + + Sequential dependencies work best when there's a clear logical progression from one task to another and when the output of one task genuinely improves the quality or feasibility of subsequent tasks. However, they can create bottlenecks if not managed carefully, so it's important to identify which dependencies are truly necessary versus those that are merely convenient. + + + + + Parallel execution becomes valuable when tasks are independent of each other, time efficiency is important, or different expertise areas are involved that don't require coordination. This approach can significantly reduce overall execution time while allowing specialized agents to work on their areas of strength simultaneously. + + Successful parallel execution requires identifying tasks that can truly run independently, grouping related but separate work streams effectively, and planning for result integration when parallel tasks need to be combined into a final deliverable. The key is ensuring that parallel tasks don't create conflicts or redundancies that reduce overall quality. + + Consider parallel execution when you have multiple independent research streams, different types of analysis that don't depend on each other, or content creation tasks that can be developed simultaneously. However, be mindful of resource allocation and ensure that parallel execution doesn't overwhelm your available model capacity or budget. + + + + +## Optimizing Agent Configuration for LLM Performance + +### a. Role-Driven LLM Selection + + + Generic agent roles make it impossible to select the right LLM. Specific roles + enable targeted model optimization. + + +The specificity of your agent roles directly determines which LLM capabilities matter most for optimal performance. This creates a strategic opportunity to match precise model strengths with agent responsibilities. + +**Generic vs. Specific Role Impact on LLM Choice:** + +When defining roles, think about the specific domain knowledge, working style, and decision-making frameworks that would be most valuable for the tasks the agent will handle. The more specific and contextual the role definition, the better the model can embody that role effectively. + +```python +# ✅ Specific role - clear LLM requirements +specific_agent = Agent( + role="SaaS Revenue Operations Analyst", # Clear domain expertise needed + goal="Analyze recurring revenue metrics and identify growth opportunities", + backstory="Specialist in SaaS business models with deep understanding of ARR, churn, and expansion revenue", + llm=LLM(model="gpt-4o") # Reasoning model justified for complex analysis +) +``` + +**Role-to-Model Mapping Strategy:** + +- **"Research Analyst"** → Reasoning model (GPT-4o, Claude Sonnet) for complex analysis +- **"Content Editor"** → Creative model (Claude, GPT-4o) for writing quality +- **"Data Processor"** → Efficient model (GPT-4o-mini, Gemini Flash) for structured tasks +- **"API Coordinator"** → Function-calling optimized model (GPT-4o, Claude) for tool usage + +### b. Backstory as Model Context Amplifier + + + Strategic backstories multiply your chosen LLM's effectiveness by providing + domain-specific context that generic prompting cannot achieve. + + +A well-crafted backstory transforms your LLM choice from generic capability to specialized expertise. This is especially crucial for cost optimization - a well-contextualized efficient model can outperform a premium model without proper context. + +**Context-Driven Performance Example:** + +```python +# Context amplifies model effectiveness +domain_expert = Agent( + role="B2B SaaS Marketing Strategist", + goal="Develop comprehensive go-to-market strategies for enterprise software", + backstory=""" + You have 10+ years of experience scaling B2B SaaS companies from Series A to IPO. + You understand the nuances of enterprise sales cycles, the importance of product-market + fit in different verticals, and how to balance growth metrics with unit economics. + You've worked with companies like Salesforce, HubSpot, and emerging unicorns, giving + you perspective on both established and disruptive go-to-market strategies. + """, + llm=LLM(model="claude-3-5-sonnet", temperature=0.3) # Balanced creativity with domain knowledge +) + +# This context enables Claude to perform like a domain expert +# Without it, even it would produce generic marketing advice +``` + +**Backstory Elements That Enhance LLM Performance:** + +- **Domain Experience**: "10+ years in enterprise SaaS sales" +- **Specific Expertise**: "Specializes in technical due diligence for Series B+ rounds" +- **Working Style**: "Prefers data-driven decisions with clear documentation" +- **Quality Standards**: "Insists on citing sources and showing analytical work" + +### c. Holistic Agent-LLM Optimization + +The most effective agent configurations create synergy between role specificity, backstory depth, and LLM selection. Each element reinforces the others to maximize model performance. + +**Optimization Framework:** + +```python +# Example: Technical Documentation Agent +tech_writer = Agent( + role="API Documentation Specialist", # Specific role for clear LLM requirements + goal="Create comprehensive, developer-friendly API documentation", + backstory=""" + You're a technical writer with 8+ years documenting REST APIs, GraphQL endpoints, + and SDK integration guides. You've worked with developer tools companies and + understand what developers need: clear examples, comprehensive error handling, + and practical use cases. You prioritize accuracy and usability over marketing fluff. + """, + llm=LLM( + model="claude-3-5-sonnet", # Excellent for technical writing + temperature=0.1 # Low temperature for accuracy + ), + tools=[code_analyzer_tool, api_scanner_tool], + verbose=True +) +``` + +**Alignment Checklist:** + +- ✅ **Role Specificity**: Clear domain and responsibilities +- ✅ **LLM Match**: Model strengths align with role requirements +- ✅ **Backstory Depth**: Provides domain context the LLM can leverage +- ✅ **Tool Integration**: Tools support the agent's specialized function +- ✅ **Parameter Tuning**: Temperature and settings optimize for role needs + +The key is creating agents where every configuration choice reinforces your LLM selection strategy, maximizing performance while optimizing costs. + +## Practical Implementation Checklist + +Rather than repeating the strategic framework, here's a tactical checklist for implementing your LLM selection decisions in CrewAI: + + + + **What to Review:** + - Are all agents using the same LLM by default? + - Which agents handle the most complex reasoning tasks? + - Which agents primarily do data processing or formatting? + - Are any agents heavily tool-dependent? + + **Action**: Document current agent roles and identify optimization opportunities. + + + + + **Set Your Baseline:** + ```python + # Start with a reliable default for the crew + default_crew_llm = LLM(model="gpt-4o-mini") # Cost-effective baseline + + crew = Crew( + agents=[...], + tasks=[...], + memory=True + ) + ``` + + **Action**: Establish your crew's default LLM before optimizing individual agents. + + + + + **Identify and Upgrade Key Agents:** + ```python + # Manager or coordination agents + manager_agent = Agent( + role="Project Manager", + llm=LLM(model="gemini-2.5-flash-preview-05-20"), # Premium for coordination + # ... rest of config + ) + + # Creative or customer-facing agents + content_agent = Agent( + role="Content Creator", + llm=LLM(model="claude-3-5-sonnet"), # Best for writing + # ... rest of config + ) + ``` + + **Action**: Upgrade 20% of your agents that handle 80% of the complexity. + + + + + **Once you deploy your agents to production:** + - Use [CrewAI AMP platform](https://app.crewai.com) to A/B test your model selections + - Run multiple iterations with real inputs to measure consistency and performance + - Compare cost vs. performance across your optimized setup + - Share results with your team for collaborative decision-making + + **Action**: Replace guesswork with data-driven validation using the testing platform. + + + + +### When to Use Different Model Types + + + + Reasoning models become essential when tasks require genuine multi-step logical thinking, strategic planning, or high-level decision making that benefits from systematic analysis. These models excel when problems need to be broken down into components and analyzed systematically rather than handled through pattern matching or simple instruction following. + + Consider reasoning models for business strategy development, complex data analysis that requires drawing insights from multiple sources, multi-step problem solving where each step depends on previous analysis, and strategic planning tasks that require considering multiple variables and their interactions. + + However, reasoning models often come with higher costs and slower response times, so they're best reserved for tasks where their sophisticated capabilities provide genuine value rather than being used for simple operations that don't require complex reasoning. + + + + + Creative models become valuable when content generation is the primary output and the quality, style, and engagement level of that content directly impact success. These models excel when writing quality and style matter significantly, creative ideation or brainstorming is needed, or brand voice and tone are important considerations. + + Use creative models for blog post writing and article creation, marketing copy that needs to engage and persuade, creative storytelling and narrative development, and brand communications where voice and tone are crucial. These models often understand nuance and context better than general purpose alternatives. + + Creative models may be less suitable for technical or analytical tasks where precision and factual accuracy are more important than engagement and style. They're best used when the creative and communicative aspects of the output are primary success factors. + + + + + Efficient models are ideal for high-frequency, routine operations where speed and cost optimization are priorities. These models work best when tasks have clear, well-defined parameters and don't require sophisticated reasoning or creative capabilities. + + Consider efficient models for data processing and transformation tasks, simple formatting and organization operations, function calling and tool usage where precision matters more than sophistication, and high-volume operations where cost per operation is a significant factor. + + The key with efficient models is ensuring that their capabilities align with task requirements. They can handle many routine operations effectively but may struggle with tasks requiring nuanced understanding, complex reasoning, or sophisticated content generation. + + + + + Open source models become attractive when budget constraints are significant, data privacy requirements exist, customization needs are important, or local deployment is required for operational or compliance reasons. + + Consider open source models for internal company tools where data privacy is paramount, privacy-sensitive applications that can't use external APIs, cost-optimized deployments where per-token pricing is prohibitive, and situations requiring custom model modifications or fine-tuning. + + However, open source models require more technical expertise to deploy and maintain effectively. Consider the total cost of ownership including infrastructure, technical overhead, and ongoing maintenance when evaluating open source options. + + + + +## Common CrewAI Model Selection Pitfalls + + + + **The Problem**: Using the same LLM for all agents in a crew, regardless of their specific roles and responsibilities. This is often the default approach but rarely optimal. + + **Real Example**: Using GPT-4o for both a strategic planning manager and a data extraction agent. The manager needs reasoning capabilities worth the premium cost, but the data extractor could perform just as well with GPT-4o-mini at a fraction of the price. + + **CrewAI Solution**: Leverage agent-specific LLM configuration to match model capabilities with agent roles: + ```python + # Strategic agent gets premium model + manager = Agent(role="Strategy Manager", llm=LLM(model="gpt-4o")) + + # Processing agent gets efficient model + processor = Agent(role="Data Processor", llm=LLM(model="gpt-4o-mini")) + ``` + + + + + **The Problem**: Not understanding how CrewAI's LLM hierarchy works - crew LLM, manager LLM, and agent LLM settings can conflict or be poorly coordinated. + + **Real Example**: Setting a crew to use Claude, but having agents configured with GPT models, creating inconsistent behavior and unnecessary model switching overhead. + + **CrewAI Solution**: Plan your LLM hierarchy strategically: + ```python + crew = Crew( + agents=[agent1, agent2], + tasks=[task1, task2], + manager_llm=LLM(model="gpt-4o"), # For crew coordination + process=Process.hierarchical # When using manager_llm + ) + + # Agents inherit crew LLM unless specifically overridden + agent1 = Agent(llm=LLM(model="claude-3-5-sonnet")) # Override for specific needs + ``` + + + + + **The Problem**: Choosing models based on general capabilities while ignoring function calling performance for tool-heavy CrewAI workflows. + + **Real Example**: Selecting a creative-focused model for an agent that primarily needs to call APIs, search tools, or process structured data. The agent struggles with tool parameter extraction and reliable function calls. + + **CrewAI Solution**: Prioritize function calling capabilities for tool-heavy agents: + ```python + # For agents that use many tools + tool_agent = Agent( + role="API Integration Specialist", + tools=[search_tool, api_tool, data_tool], + llm=LLM(model="gpt-4o"), # Excellent function calling + # OR + llm=LLM(model="claude-3-5-sonnet") # Also strong with tools + ) + ``` + + + + + **The Problem**: Making complex model selection decisions based on theoretical performance without validating with actual CrewAI workflows and tasks. + + **Real Example**: Implementing elaborate model switching logic based on task types without testing if the performance gains justify the operational complexity. + + **CrewAI Solution**: Start simple, then optimize based on real performance data: + ```python + # Start with this + crew = Crew(agents=[...], tasks=[...], llm=LLM(model="gpt-4o-mini")) + + # Test performance, then optimize specific agents as needed + # Use Enterprise platform testing to validate improvements + ``` + + + + + **The Problem**: Not considering how model context windows interact with CrewAI's memory and context sharing between agents. + + **Real Example**: Using a short-context model for agents that need to maintain conversation history across multiple task iterations, or in crews with extensive agent-to-agent communication. + + **CrewAI Solution**: Match context capabilities to crew communication patterns. + + + + +## Testing and Iteration Strategy + + + + Begin with reliable, general-purpose models that are well-understood and + widely supported. This provides a stable foundation for understanding your + specific requirements and performance expectations before optimizing for + specialized needs. + + + Develop metrics that align with your specific use case and business + requirements rather than relying solely on general benchmarks. Focus on + measuring outcomes that directly impact your success rather than theoretical + performance indicators. + + + Make model changes based on observed performance in your specific context + rather than theoretical considerations or general recommendations. + Real-world performance often differs significantly from benchmark results or + general reputation. + + + Evaluate the complete cost of ownership including model costs, development + time, maintenance overhead, and operational complexity. The cheapest model + per token may not be the most cost-effective choice when considering all + factors. + + + + + Focus on understanding your requirements first, then select models that best + match those needs. The best LLM choice is the one that consistently delivers + the results you need within your operational constraints. + + +### Enterprise-Grade Model Validation + +For teams serious about optimizing their LLM selection, the **CrewAI AMP platform** provides sophisticated testing capabilities that go far beyond basic CLI testing. The platform enables comprehensive model evaluation that helps you make data-driven decisions about your LLM strategy. + + + ![Enterprise Testing Interface](/images/enterprise/enterprise-testing.png) + + +**Advanced Testing Features:** + +- **Multi-Model Comparison**: Test multiple LLMs simultaneously across the same tasks and inputs. Compare performance between GPT-4o, Claude, Llama, Groq, Cerebras, and other leading models in parallel to identify the best fit for your specific use case. + +- **Statistical Rigor**: Configure multiple iterations with consistent inputs to measure reliability and performance variance. This helps identify models that not only perform well but do so consistently across runs. + +- **Real-World Validation**: Use your actual crew inputs and scenarios rather than synthetic benchmarks. The platform allows you to test with your specific industry context, company information, and real use cases for more accurate evaluation. + +- **Comprehensive Analytics**: Access detailed performance metrics, execution times, and cost analysis across all tested models. This enables data-driven decision making rather than relying on general model reputation or theoretical capabilities. + +- **Team Collaboration**: Share testing results and model performance data across your team, enabling collaborative decision-making and consistent model selection strategies across projects. + +Go to [app.crewai.com](https://app.crewai.com) to get started! + + + The Enterprise platform transforms model selection from guesswork into a + data-driven process, enabling you to validate the principles in this guide + with your actual use cases and requirements. + + +## Key Principles Summary + + + + Choose models based on what the task actually requires, not theoretical capabilities or general reputation. + + +{" "} + + Align model strengths with agent roles and responsibilities for optimal + performance. + + +{" "} + + Maintain coherent model selection strategy across related components and + workflows. + + +{" "} + + Validate choices through real-world usage rather than benchmarks alone. + + +{" "} + + Start simple and optimize based on actual performance and needs. + + + + Balance performance requirements with cost and complexity constraints. + + + + + Remember: The best LLM choice is the one that consistently delivers the + results you need within your operational constraints. Focus on understanding + your requirements first, then select models that best match those needs. + + +## Current Model Landscape (June 2025) + + + **Snapshot in Time**: The following model rankings represent current + leaderboard standings as of June 2025, compiled from [LMSys + Arena](https://arena.lmsys.org/), [Artificial + Analysis](https://artificialanalysis.ai/), and other leading benchmarks. LLM + performance, availability, and pricing change rapidly. Always conduct your own + evaluations with your specific use cases and data. + + +### Leading Models by Category + +The tables below show a representative sample of current top-performing models across different categories, with guidance on their suitability for CrewAI agents: + + + These tables/metrics showcase selected leading models in each category and are + not exhaustive. Many excellent models exist beyond those listed here. The goal + is to illustrate the types of capabilities to look for rather than provide a + complete catalog. + + + + + **Best for Manager LLMs and Complex Analysis** + + | Model | Intelligence Score | Cost ($/M tokens) | Speed | Best Use in CrewAI | + |:------|:------------------|:------------------|:------|:------------------| + | **o3** | 70 | $17.50 | Fast | Manager LLM for complex multi-agent coordination | + | **Gemini 2.5 Pro** | 69 | $3.44 | Fast | Strategic planning agents, research coordination | + | **DeepSeek R1** | 68 | $0.96 | Moderate | Cost-effective reasoning for budget-conscious crews | + | **Claude 4 Sonnet** | 53 | $6.00 | Fast | Analysis agents requiring nuanced understanding | + | **Qwen3 235B (Reasoning)** | 62 | $2.63 | Moderate | Open-source alternative for reasoning tasks | + + These models excel at multi-step reasoning and are ideal for agents that need to develop strategies, coordinate other agents, or analyze complex information. + + + + + **Best for Development and Tool-Heavy Workflows** + + | Model | Coding Performance | Tool Use Score | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:------------------|:---------------|:------------------|:------------------| + | **Claude 4 Sonnet** | Excellent | 72.7% | $6.00 | Primary coding agent, technical documentation | + | **Claude 4 Opus** | Excellent | 72.5% | $30.00 | Complex software architecture, code review | + | **DeepSeek V3** | Very Good | High | $0.48 | Cost-effective coding for routine development | + | **Qwen2.5 Coder 32B** | Very Good | Medium | $0.15 | Budget-friendly coding agent | + | **Llama 3.1 405B** | Good | 81.1% | $3.50 | Function calling LLM for tool-heavy workflows | + + These models are optimized for code generation, debugging, and technical problem-solving, making them ideal for development-focused crews. + + + + + **Best for High-Throughput and Real-Time Applications** + + | Model | Speed (tokens/s) | Latency (TTFT) | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:-----------------|:---------------|:------------------|:------------------| + | **Llama 4 Scout** | 2,600 | 0.33s | $0.27 | High-volume processing agents | + | **Gemini 2.5 Flash** | 376 | 0.30s | $0.26 | Real-time response agents | + | **DeepSeek R1 Distill** | 383 | Variable | $0.04 | Cost-optimized high-speed processing | + | **Llama 3.3 70B** | 2,500 | 0.52s | $0.60 | Balanced speed and capability | + | **Nova Micro** | High | 0.30s | $0.04 | Simple, fast task execution | + + These models prioritize speed and efficiency, perfect for agents handling routine operations or requiring quick responses. **Pro tip**: Pairing these models with fast inference providers like Groq can achieve even better performance, especially for open-source models like Llama. + + + + + **Best All-Around Models for General Crews** + + | Model | Overall Score | Versatility | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:--------------|:------------|:------------------|:------------------| + | **GPT-4.1** | 53 | Excellent | $3.50 | General-purpose crew LLM | + | **Claude 3.7 Sonnet** | 48 | Very Good | $6.00 | Balanced reasoning and creativity | + | **Gemini 2.0 Flash** | 48 | Good | $0.17 | Cost-effective general use | + | **Llama 4 Maverick** | 51 | Good | $0.37 | Open-source general purpose | + | **Qwen3 32B** | 44 | Good | $1.23 | Budget-friendly versatility | + + These models offer good performance across multiple dimensions, suitable for crews with diverse task requirements. + + + + +### Selection Framework for Current Models + + + + **When performance is the priority**: Use top-tier models like **o3**, **Gemini 2.5 Pro**, or **Claude 4 Sonnet** for manager LLMs and critical agents. These models excel at complex reasoning and coordination but come with higher costs. + + **Strategy**: Implement a multi-model approach where premium models handle strategic thinking while efficient models handle routine operations. + + + + + **When budget is a primary constraint**: Focus on models like **DeepSeek R1**, **Llama 4 Scout**, or **Gemini 2.0 Flash**. These provide strong performance at significantly lower costs. + + **Strategy**: Use cost-effective models for most agents, reserving premium models only for the most critical decision-making roles. + + + + + **For specific domain expertise**: Choose models optimized for your primary use case. **Claude 4** series for coding, **Gemini 2.5 Pro** for research, **Llama 405B** for function calling. + + **Strategy**: Select models based on your crew's primary function, ensuring the core capability aligns with model strengths. + + + + + **For data-sensitive operations**: Consider open-source models like **Llama 4** series, **DeepSeek V3**, or **Qwen3** that can be deployed locally while maintaining competitive performance. + + **Strategy**: Deploy open-source models on private infrastructure, accepting potential performance trade-offs for data control. + + + + +### Key Considerations for Model Selection + +- **Performance Trends**: The current landscape shows strong competition between reasoning-focused models (o3, Gemini 2.5 Pro) and balanced models (Claude 4, GPT-4.1). Specialized models like DeepSeek R1 offer excellent cost-performance ratios. + +- **Speed vs. Intelligence Trade-offs**: Models like Llama 4 Scout prioritize speed (2,600 tokens/s) while maintaining reasonable intelligence, whereas models like o3 maximize reasoning capability at the cost of speed and price. + +- **Open Source Viability**: The gap between open-source and proprietary models continues to narrow, with models like Llama 4 Maverick and DeepSeek V3 offering competitive performance at attractive price points. Fast inference providers particularly shine with open-source models, often delivering better speed-to-cost ratios than proprietary alternatives. + + + **Testing is Essential**: Leaderboard rankings provide general guidance, but + your specific use case, prompting style, and evaluation criteria may produce + different results. Always test candidate models with your actual tasks and + data before making final decisions. + + +### Practical Implementation Strategy + + + + Begin with well-established models like **GPT-4.1**, **Claude 3.7 Sonnet**, or **Gemini 2.0 Flash** that offer good performance across multiple dimensions and have extensive real-world validation. + + + + Determine if your crew has specific requirements (coding, reasoning, speed) + that would benefit from specialized models like **Claude 4 Sonnet** for + development or **o3** for complex analysis. For speed-critical applications, + consider fast inference providers like **Groq** alongside model selection. + + + + Use different models for different agents based on their roles. + High-capability models for managers and complex tasks, efficient models for + routine operations. + + + + Track performance metrics relevant to your use case and be prepared to adjust model selections as new models are released or pricing changes. + + diff --git a/docs/v1.15.13/en/learn/multimodal-agents.mdx b/docs/v1.15.13/en/learn/multimodal-agents.mdx new file mode 100644 index 0000000000..1b414cac93 --- /dev/null +++ b/docs/v1.15.13/en/learn/multimodal-agents.mdx @@ -0,0 +1,141 @@ +--- +title: Using Multimodal Agents +description: Learn how to enable and use multimodal capabilities in your agents for processing images and other non-text content within the CrewAI framework. +icon: video +mode: "wide" +--- + +## Using Multimodal Agents + +CrewAI supports multimodal agents that can process both text and non-text content like images. This guide will show you how to enable and use multimodal capabilities in your agents. + +### Enabling Multimodal Capabilities + +To create a multimodal agent, simply set the `multimodal` parameter to `True` when initializing your agent: + +```python +from crewai import Agent + +agent = Agent( + role="Image Analyst", + goal="Analyze and extract insights from images", + backstory="An expert in visual content interpretation with years of experience in image analysis", + multimodal=True # This enables multimodal capabilities +) +``` + +When you set `multimodal=True`, the agent is automatically configured with the necessary tools for handling non-text content, including the `AddImageTool`. + +### Working with Images + +The multimodal agent comes pre-configured with the `AddImageTool`, which allows it to process images. You don't need to manually add this tool - it's automatically included when you enable multimodal capabilities. + +Here's a complete example showing how to use a multimodal agent to analyze an image: + +```python +from crewai import Agent, Task, Crew + +# Create a multimodal agent +image_analyst = Agent( + role="Product Analyst", + goal="Analyze product images and provide detailed descriptions", + backstory="Expert in visual product analysis with deep knowledge of design and features", + multimodal=True +) + +# Create a task for image analysis +task = Task( + description="Analyze the product image at https://example.com/product.jpg and provide a detailed description", + expected_output="A detailed description of the product image", + agent=image_analyst +) + +# Create and run the crew +crew = Crew( + agents=[image_analyst], + tasks=[task] +) + +result = crew.kickoff() +``` + +### Advanced Usage with Context + +You can provide additional context or specific questions about the image when creating tasks for multimodal agents. The task description can include specific aspects you want the agent to focus on: + +```python +from crewai import Agent, Task, Crew + +# Create a multimodal agent for detailed analysis +expert_analyst = Agent( + role="Visual Quality Inspector", + goal="Perform detailed quality analysis of product images", + backstory="Senior quality control expert with expertise in visual inspection", + multimodal=True # AddImageTool is automatically included +) + +# Create a task with specific analysis requirements +inspection_task = Task( + description=""" + Analyze the product image at https://example.com/product.jpg with focus on: + 1. Quality of materials + 2. Manufacturing defects + 3. Compliance with standards + Provide a detailed report highlighting any issues found. + """, + expected_output="A detailed report highlighting any issues found", + agent=expert_analyst +) + +# Create and run the crew +crew = Crew( + agents=[expert_analyst], + tasks=[inspection_task] +) + +result = crew.kickoff() +``` + +### Tool Details + +When working with multimodal agents, the `AddImageTool` is automatically configured with the following schema: + +```python +class AddImageToolSchema: + image_url: str # Required: The URL or path of the image to process + action: Optional[str] = None # Optional: Additional context or specific questions about the image +``` + +The multimodal agent will automatically handle the image processing through its built-in tools, allowing it to: +- Access images via URLs or local file paths +- Process image content with optional context or specific questions +- Provide analysis and insights based on the visual information and task requirements + +### Best Practices + +When working with multimodal agents, keep these best practices in mind: + +1. **Image Access** + - Ensure your images are accessible via URLs that the agent can reach + - For local images, consider hosting them temporarily or using absolute file paths + - Verify that image URLs are valid and accessible before running tasks + +2. **Task Description** + - Be specific about what aspects of the image you want the agent to analyze + - Include clear questions or requirements in the task description + - Consider using the optional `action` parameter for focused analysis + +3. **Resource Management** + - Image processing may require more computational resources than text-only tasks + - Some language models may require base64 encoding for image data + - Consider batch processing for multiple images to optimize performance + +4. **Environment Setup** + - Verify that your environment has the necessary dependencies for image processing + - Ensure your language model supports multimodal capabilities + - Test with small images first to validate your setup + +5. **Error Handling** + - Implement proper error handling for image loading failures + - Have fallback strategies for when image processing fails + - Monitor and log image processing operations for debugging diff --git a/docs/v1.15.13/en/learn/overview.mdx b/docs/v1.15.13/en/learn/overview.mdx new file mode 100644 index 0000000000..7b82aef3a6 --- /dev/null +++ b/docs/v1.15.13/en/learn/overview.mdx @@ -0,0 +1,159 @@ +--- +title: "Overview" +description: "Learn how to build, customize, and optimize your CrewAI applications with comprehensive guides and tutorials" +icon: "face-smile" +mode: "wide" +--- + +## Learn CrewAI + +This section provides comprehensive guides and tutorials to help you master CrewAI, from basic concepts to advanced techniques. Whether you're just getting started or looking to optimize your existing implementations, these resources will guide you through every aspect of building powerful AI agent workflows. + +## Getting Started Guides + +### Core Concepts + + + Learn how to execute tasks in a sequential order for structured workflows. + + + + Implement hierarchical task execution with manager agents overseeing workflows. + + + + Create dynamic workflows with conditional task execution based on outcomes. + + + + Execute crews asynchronously for improved performance and concurrency. + + + +### Agent Development + + + Learn how to customize agent behavior, roles, and capabilities. + + + + Build agents that can write, execute, and debug code automatically. + + + + Create agents that can process text, images, and other media types. + + + + Implement custom manager agents for complex hierarchical workflows. + + + +## Advanced Features + +### Workflow Control + + + Integrate human oversight and intervention into agent workflows. + + + + Allow human input during task execution for dynamic decision making. + + + + Replay and resume tasks from previous crew executions. + + + + Execute crews multiple times with different inputs efficiently. + + + +### Customization & Integration + + + Integrate custom language models and providers with CrewAI. + + + + Configure and manage connections to various LLM providers. + + + + Build custom tools to extend agent capabilities. + + + + Use Python annotations for cleaner, more maintainable code. + + + +## Specialized Applications + +### Content & Media + + + Generate images using DALL-E integration with your agents. + + + + Integrate existing agents and models into CrewAI workflows. + + + +### Tool Management + + + Configure tools to return their output directly as task results. + + + +## Learning Path Recommendations + +### For Beginners +1. Start with **Sequential Process** to understand basic workflow execution +2. Learn **Customizing Agents** to create effective agent configurations +3. Explore **Create Custom Tools** to extend functionality +4. Try **Human in the Loop** for interactive workflows + +### For Intermediate Users +1. Master **Hierarchical Process** for complex multi-agent systems +2. Implement **Conditional Tasks** for dynamic workflows +3. Use **Async Kickoff** for performance optimization +4. Integrate **Custom LLM** for specialized models + +### For Advanced Users +1. Build **Multimodal Agents** for complex media processing +2. Create **Custom Manager Agents** for sophisticated orchestration +3. Implement **Bring Your Own Agent** for hybrid systems +4. Use **Replay Tasks** for robust error recovery + +## Best Practices + +### Development +- **Start Simple**: Begin with basic sequential workflows before adding complexity +- **Test Incrementally**: Test each component before integrating into larger systems +- **Use Annotations**: Leverage Python annotations for cleaner, more maintainable code +- **Custom Tools**: Build reusable tools that can be shared across different agents + +### Production +- **Error Handling**: Implement robust error handling and recovery mechanisms +- **Performance**: Use async execution and optimize LLM calls for better performance +- **Monitoring**: Integrate observability tools to track agent performance +- **Human Oversight**: Include human checkpoints for critical decisions + +### Optimization +- **Resource Management**: Monitor and optimize token usage and API costs +- **Workflow Design**: Design workflows that minimize unnecessary LLM calls +- **Tool Efficiency**: Create efficient tools that provide maximum value with minimal overhead +- **Iterative Improvement**: Use feedback and metrics to continuously improve agent performance + +## Getting Help + +- **Documentation**: Each guide includes detailed examples and explanations +- **Community**: Join the [CrewAI Forum](https://community.crewai.com) for discussions and support +- **Examples**: Check the Examples section for complete working implementations +- **Support**: Contact [support@crewai.com](mailto:support@crewai.com) for technical assistance + +Start with the guides that match your current needs and gradually explore more advanced topics as you become comfortable with the fundamentals. diff --git a/docs/v1.15.13/en/learn/replay-tasks-from-latest-crew-kickoff.mdx b/docs/v1.15.13/en/learn/replay-tasks-from-latest-crew-kickoff.mdx new file mode 100644 index 0000000000..07b452b5f1 --- /dev/null +++ b/docs/v1.15.13/en/learn/replay-tasks-from-latest-crew-kickoff.mdx @@ -0,0 +1,79 @@ +--- +title: Replay Tasks from Latest Crew Kickoff +description: Replay tasks from the latest crew.kickoff(...) +icon: arrow-right +mode: "wide" +--- + +## Introduction + +CrewAI provides the ability to replay from a task specified from the latest crew kickoff. This feature is particularly useful when you've finished a kickoff and may want to retry certain tasks or don't need to refetch data over and your agents already have the context saved from the kickoff execution so you just need to replay the tasks you want to. + + + You must run `crew.kickoff()` before you can replay a task. + Currently, only the latest kickoff is supported, so if you use `kickoff_for_each`, it will only allow you to replay from the most recent crew run. + + +Here's an example of how to replay from a task: + +### Replaying from Specific Task Using the CLI + +To use the replay feature, follow these steps: + + + + + + To view the latest kickoff task_ids use: + + ```shell + crewai log-tasks-outputs + ``` + + Once you have your `task_id` to replay, use: + + ```shell + crewai replay -t + ``` + + + + + Ensure `crewai` is installed and configured correctly in your development environment. + + +### Replaying from a Task Programmatically + +To replay from a task programmatically, use the following steps: + + + + Specify the `task_id` and input parameters for the replay process. + + + Execute the replay command within a try-except block to handle potential errors. + + ```python Code + def replay(): + """ + Replay the crew execution from a specific task. + """ + task_id = '' + inputs = {"topic": "CrewAI Training"} # This is optional; you can pass in the inputs you want to replay; otherwise, it uses the previous kickoff's inputs. + try: + YourCrewName_Crew().crew().replay(task_id=task_id, inputs=inputs) + + except subprocess.CalledProcessError as e: + raise Exception(f"An error occurred while replaying the crew: {e}") + + except Exception as e: + raise Exception(f"An unexpected error occurred: {e}") + ``` + + + + +## Conclusion + +With the above enhancements and detailed functionality, replaying specific tasks in CrewAI has been made more efficient and robust. +Ensure you follow the commands and steps precisely to make the most of these features. \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/sequential-process.mdx b/docs/v1.15.13/en/learn/sequential-process.mdx new file mode 100644 index 0000000000..940ff5bc01 --- /dev/null +++ b/docs/v1.15.13/en/learn/sequential-process.mdx @@ -0,0 +1,128 @@ +--- +title: Sequential Processes +description: A comprehensive guide to utilizing the sequential processes for task execution in CrewAI projects. +icon: forward +mode: "wide" +--- + +## Introduction + +CrewAI offers a flexible framework for executing tasks in a structured manner, supporting both sequential and hierarchical processes. +This guide outlines how to effectively implement these processes to ensure efficient task execution and project completion. + +## Sequential Process Overview + +The sequential process ensures tasks are executed one after the other, following a linear progression. +This approach is ideal for projects requiring tasks to be completed in a specific order. + +### Key Features + +- **Linear Task Flow**: Ensures orderly progression by handling tasks in a predetermined sequence. +- **Simplicity**: Best suited for projects with clear, step-by-step tasks. +- **Easy Monitoring**: Facilitates easy tracking of task completion and project progress. + +## Implementing the Sequential Process + +To use the sequential process, assemble your crew and define tasks in the order they need to be executed. + +```python Code +from crewai import Crew, Process, Agent, Task, TaskOutput, CrewOutput + +# Define your agents +researcher = Agent( + role='Researcher', + goal='Conduct foundational research', + backstory='An experienced researcher with a passion for uncovering insights' +) +analyst = Agent( + role='Data Analyst', + goal='Analyze research findings', + backstory='A meticulous analyst with a knack for uncovering patterns' +) +writer = Agent( + role='Writer', + goal='Draft the final report', + backstory='A skilled writer with a talent for crafting compelling narratives' +) + +# Define your tasks +research_task = Task( + description='Gather relevant data...', + agent=researcher, + expected_output='Raw Data' +) +analysis_task = Task( + description='Analyze the data...', + agent=analyst, + expected_output='Data Insights' +) +writing_task = Task( + description='Compose the report...', + agent=writer, + expected_output='Final Report' +) + +# Form the crew with a sequential process +report_crew = Crew( + agents=[researcher, analyst, writer], + tasks=[research_task, analysis_task, writing_task], + process=Process.sequential +) + +# Execute the crew +result = report_crew.kickoff() + +# Accessing the type-safe output +task_output: TaskOutput = result.tasks[0].output +crew_output: CrewOutput = result.output +``` + +### Note: + +Each task in a sequential process **must** have an agent assigned. Ensure that every `Task` includes an `agent` parameter. + +### Workflow in Action + +1. **Initial Task**: In a sequential process, the first agent completes their task and signals completion. +2. **Subsequent Tasks**: Agents pick up their tasks based on the process type, with outcomes of preceding tasks or directives guiding their execution. +3. **Completion**: The process concludes once the final task is executed, leading to project completion. + +## Advanced Features + +### Task Delegation + +In sequential processes, if an agent has `allow_delegation` set to `True`, they can delegate tasks to other agents in the crew. +This feature is automatically set up when there are multiple agents in the crew. + +### Asynchronous Execution + +Tasks can be executed asynchronously, allowing for parallel processing when appropriate. +To create an asynchronous task, set `async_execution=True` when defining the task. + +### Memory and Caching + +CrewAI supports both memory and caching features: + +- **Memory**: Enable by setting `memory=True` when creating the Crew. This allows agents to retain information across tasks. +- **Caching**: By default, caching is enabled. Set `cache=False` to disable it. + +### Callbacks + +You can set callbacks at both the task and step level: + +- `task_callback`: Executed after each task completion. +- `step_callback`: Executed after each step in an agent's execution. + +### Usage Metrics + +CrewAI tracks token usage across all tasks and agents. You can access these metrics after execution. + +## Best Practices for Sequential Processes + +1. **Order Matters**: Arrange tasks in a logical sequence where each task builds upon the previous one. +2. **Clear Task Descriptions**: Provide detailed descriptions for each task to guide the agents effectively. +3. **Appropriate Agent Selection**: Match agents' skills and roles to the requirements of each task. +4. **Use Context**: Leverage the context from previous tasks to inform subsequent ones. + +This updated documentation ensures that details accurately reflect the latest changes in the codebase and clearly describes how to leverage new features and configurations. +The content is kept simple and direct to ensure easy understanding. \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/step-hooks.mdx b/docs/v1.15.13/en/learn/step-hooks.mdx new file mode 100644 index 0000000000..7aa104e4b7 --- /dev/null +++ b/docs/v1.15.13/en/learn/step-hooks.mdx @@ -0,0 +1,142 @@ +--- +title: Step Hooks +description: Intercept task and flow-method steps with PRE_STEP and POST_STEP hooks in CrewAI +mode: "wide" +--- + +Step hooks intercept each unit of work inside an execution: every crew **task** +and every **flow method**. Use them to inspect or rewrite what goes into a +step, transform what comes out, or trace step-by-step progress — without +touching the level of individual LLM or tool calls. + +## Overview + +Two interception points cover steps: + +| Point | When | `ctx.payload` | +|-------|------|---------------| +| `PRE_STEP` | Before a task or flow method runs | step input (see below) | +| `POST_STEP` | After a task or flow method runs | step output (see below) | + +What the payload holds depends on `ctx.kind`: + +| `ctx.kind` | `PRE_STEP` payload | `POST_STEP` payload | +|------------|--------------------|---------------------| +| `"task"` | The context string passed to the agent | The `TaskOutput` object | +| `"flow_method"` | The method's parameters as a `dict` | The method's return value | + +For flow methods, positional arguments appear in the params dict under `_0`, +`_1`, ... keys and keyword arguments under their own names; edits and +replacements are mapped back onto the actual call. + +## Hook Signature + +```python +from crewai.hooks import on, HookAborted, InterceptionPoint + +@on(InterceptionPoint.PRE_STEP) +def step_hook(ctx) -> Any | None: + # Mutate ctx.payload in place, or + # return a non-None value to replace it, or + # raise HookAborted(reason, source) to stop the step + return None +``` + +## Context Schema + +Both points receive a `StepContext`: + +```python +class StepContext(InterceptionContext): + payload: Any # Step input (pre) or step output (post) + kind: str | None # "task" or "flow_method" + step_name: str | None # Task name/description, or flow method name + output: Any # POST_STEP only: same object as payload + agent: Any # Task steps: the executing agent (else None) + agent_role: str | None # Task steps: the agent's role (else None) + task: Any # Task steps: the Task instance (else None) + crew: Any # None for step points + flow: Any # Flow-method steps: the Flow instance (else None) +``` + +For task steps, `step_name` is the task's `name` (falling back to its +description). For flow-method steps, it is the method name. + +## Common Use Cases + +### Step Tracing + +```python +@on(InterceptionPoint.POST_STEP) +def trace_steps(ctx): + print(f"{ctx.kind} '{ctx.step_name}' finished") +``` + +### Rewriting Task Context + +```python +@on(InterceptionPoint.PRE_STEP) +def inject_disclaimer(ctx): + if ctx.kind != "task": + return None + return f"{ctx.payload}\n\nNote: treat all figures as estimates." +``` + +### Transforming Task Output + +```python +@on(InterceptionPoint.POST_STEP) +def normalize_output(ctx): + if ctx.kind != "task": + return None + ctx.payload.raw = ctx.payload.raw.strip() +``` + + +`POST_STEP` runs before the task's output is stored, so rewrites propagate +everywhere the output is used: downstream task context, callbacks, the final +crew output, and the task's `output_file` on disk. + + +### Guarding Flow Methods + +```python +@on(InterceptionPoint.PRE_STEP) +def guard_publish(ctx): + if ctx.kind == "flow_method" and ctx.step_name == "publish": + if not ctx.flow.state.get("reviewed"): + raise HookAborted(reason="publish requires review", source="review-gate") +``` + +### Filtering by Agent + +Step hooks support the same `agents=` filter as the other points (matched +against the executing agent's role on task steps): + +```python +@on(InterceptionPoint.POST_STEP, agents=["Researcher"]) +def log_research_steps(ctx): + print(f"research step done: {ctx.step_name}") +``` + +## Aborting a Step + +Raising `HookAborted` in `PRE_STEP` stops the step before any agent or method +work happens, and the abort propagates out of the execution with its reason — +it is not swallowed. Any other exception raised by a step hook is swallowed +(fail-open), like at every other point. + +## Managing Hooks in Tests + +```python +from crewai.hooks import clear_all_hooks + +clear_all_hooks() # Clears every point, including steps +``` + +## Related Documentation + +- [Execution Hooks Overview →](/edge/en/learn/execution-hooks) +- [Execution Boundary Hooks →](/edge/en/learn/execution-boundary-hooks) +- [LLM Call Hooks →](/edge/en/learn/llm-hooks) +- [Tool Call Hooks →](/edge/en/learn/tool-hooks) diff --git a/docs/v1.15.13/en/learn/streaming-crew-execution.mdx b/docs/v1.15.13/en/learn/streaming-crew-execution.mdx new file mode 100644 index 0000000000..ff0a3cd7f6 --- /dev/null +++ b/docs/v1.15.13/en/learn/streaming-crew-execution.mdx @@ -0,0 +1,384 @@ +--- +title: Streaming Crew Execution +description: Stream real-time output from your CrewAI crew execution +icon: wave-pulse +mode: "wide" +--- + +## Introduction + +CrewAI provides the ability to stream real-time output during crew execution, allowing you to display results as they're generated rather than waiting for the entire process to complete. This feature is particularly useful for building interactive applications, providing user feedback, and monitoring long-running processes. + +## How Streaming Works + +When streaming is enabled, CrewAI captures LLM responses and tool calls as they happen, packaging them into structured chunks that include context about which task and agent is executing. You can iterate over these chunks in real-time and access the final result once execution completes. + +## Enabling Streaming + +To enable streaming, set the `stream` parameter to `True` when creating your crew: + +```python Code +from crewai import Agent, Crew, Task + +# Create your agents and tasks +researcher = Agent( + role="Research Analyst", + goal="Gather comprehensive information on topics", + backstory="You are an experienced researcher with excellent analytical skills.", +) + +task = Task( + description="Research the latest developments in AI", + expected_output="A detailed report on recent AI advancements", + agent=researcher, +) + +# Enable streaming +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True # Enable streaming output +) +``` + +## Synchronous Streaming + +When you call `kickoff()` on a crew with streaming enabled, it returns a `CrewStreamingOutput` object that you can iterate over to receive chunks as they arrive: + +```python Code +# Start streaming execution +streaming = crew.kickoff(inputs={"topic": "artificial intelligence"}) + +# Iterate over chunks as they arrive +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# Access the final result after streaming completes +result = streaming.result +print(f"\n\nFinal output: {result.raw}") +``` + +### Stream Chunk Information + +Each chunk provides rich context about the execution: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +for chunk in streaming: + print(f"Task: {chunk.task_name} (index {chunk.task_index})") + print(f"Agent: {chunk.agent_role}") + print(f"Content: {chunk.content}") + print(f"Type: {chunk.chunk_type}") # TEXT or TOOL_CALL + if chunk.tool_call: + print(f"Tool: {chunk.tool_call.tool_name}") + print(f"Arguments: {chunk.tool_call.arguments}") +``` + +### Accessing Streaming Results + +The `CrewStreamingOutput` object provides several useful properties: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +# Iterate and collect chunks +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# After iteration completes +print(f"\nCompleted: {streaming.is_completed}") +print(f"Full text: {streaming.get_full_text()}") +print(f"All chunks: {len(streaming.chunks)}") +print(f"Final result: {streaming.result.raw}") +``` + +## Asynchronous Streaming + +For async applications, you can use either `akickoff()` (native async) or `kickoff_async()` (thread-based) with async iteration: + +### Native Async with `akickoff()` + +The `akickoff()` method provides true native async execution throughout the entire chain: + +```python Code +import asyncio + +async def stream_crew(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + # Start native async streaming + streaming = await crew.akickoff(inputs={"topic": "AI"}) + + # Async iteration over chunks + async for chunk in streaming: + print(chunk.content, end="", flush=True) + + # Access final result + result = streaming.result + print(f"\n\nFinal output: {result.raw}") + +asyncio.run(stream_crew()) +``` + +### Thread-Based Async with `kickoff_async()` + +For simpler async integration or backward compatibility: + +```python Code +import asyncio + +async def stream_crew(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + # Start thread-based async streaming + streaming = await crew.kickoff_async(inputs={"topic": "AI"}) + + # Async iteration over chunks + async for chunk in streaming: + print(chunk.content, end="", flush=True) + + # Access final result + result = streaming.result + print(f"\n\nFinal output: {result.raw}") + +asyncio.run(stream_crew()) +``` + + +For high-concurrency workloads, `akickoff()` is recommended as it uses native async for task execution, memory operations, and knowledge retrieval. See the [Kickoff Crew Asynchronously](/en/learn/kickoff-async) guide for more details. + + +## Streaming with kickoff_for_each + +When executing a crew for multiple inputs with `kickoff_for_each()`, streaming works differently depending on whether you use sync or async: + +### Synchronous kickoff_for_each + +With synchronous `kickoff_for_each()`, you get a list of `CrewStreamingOutput` objects, one for each input: + +```python Code +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True +) + +inputs_list = [ + {"topic": "AI in healthcare"}, + {"topic": "AI in finance"} +] + +# Returns list of streaming outputs +streaming_outputs = crew.kickoff_for_each(inputs=inputs_list) + +# Iterate over each streaming output +for i, streaming in enumerate(streaming_outputs): + print(f"\n=== Input {i + 1} ===") + for chunk in streaming: + print(chunk.content, end="", flush=True) + + result = streaming.result + print(f"\n\nResult {i + 1}: {result.raw}") +``` + +### Asynchronous kickoff_for_each_async + +With async `kickoff_for_each_async()`, you get a single `CrewStreamingOutput` that yields chunks from all crews as they arrive concurrently: + +```python Code +import asyncio + +async def stream_multiple_crews(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + inputs_list = [ + {"topic": "AI in healthcare"}, + {"topic": "AI in finance"} + ] + + # Returns single streaming output for all crews + streaming = await crew.kickoff_for_each_async(inputs=inputs_list) + + # Chunks from all crews arrive as they're generated + async for chunk in streaming: + print(f"[{chunk.task_name}] {chunk.content}", end="", flush=True) + + # Access all results + results = streaming.results # List of CrewOutput objects + for i, result in enumerate(results): + print(f"\n\nResult {i + 1}: {result.raw}") + +asyncio.run(stream_multiple_crews()) +``` + +## Stream Chunk Types + +Chunks can be of different types, indicated by the `chunk_type` field: + +### TEXT Chunks + +Standard text content from LLM responses: + +```python Code +for chunk in streaming: + if chunk.chunk_type == StreamChunkType.TEXT: + print(chunk.content, end="", flush=True) +``` + +### TOOL_CALL Chunks + +Information about tool calls being made: + +```python Code +for chunk in streaming: + if chunk.chunk_type == StreamChunkType.TOOL_CALL: + print(f"\nCalling tool: {chunk.tool_call.tool_name}") + print(f"Arguments: {chunk.tool_call.arguments}") +``` + +## Practical Example: Building a UI with Streaming + +Here's a complete example showing how to build an interactive application with streaming: + +```python Code +import asyncio +from crewai import Agent, Crew, Task +from crewai.types.streaming import StreamChunkType + +async def interactive_research(): + # Create crew with streaming enabled + researcher = Agent( + role="Research Analyst", + goal="Provide detailed analysis on any topic", + backstory="You are an expert researcher with broad knowledge.", + ) + + task = Task( + description="Research and analyze: {topic}", + expected_output="A comprehensive analysis with key insights", + agent=researcher, + ) + + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True, + verbose=False + ) + + # Get user input + topic = input("Enter a topic to research: ") + + print(f"\n{'='*60}") + print(f"Researching: {topic}") + print(f"{'='*60}\n") + + # Start streaming execution + streaming = await crew.kickoff_async(inputs={"topic": topic}) + + current_task = "" + async for chunk in streaming: + # Show task transitions + if chunk.task_name != current_task: + current_task = chunk.task_name + print(f"\n[{chunk.agent_role}] Working on: {chunk.task_name}") + print("-" * 60) + + # Display text chunks + if chunk.chunk_type == StreamChunkType.TEXT: + print(chunk.content, end="", flush=True) + + # Display tool calls + elif chunk.chunk_type == StreamChunkType.TOOL_CALL and chunk.tool_call: + print(f"\n🔧 Using tool: {chunk.tool_call.tool_name}") + + # Show final result + result = streaming.result + print(f"\n\n{'='*60}") + print("Analysis Complete!") + print(f"{'='*60}") + print(f"\nToken Usage: {result.token_usage}") + +asyncio.run(interactive_research()) +``` + +## Use Cases + +Streaming is particularly valuable for: + +- **Interactive Applications**: Provide real-time feedback to users as agents work +- **Long-Running Tasks**: Show progress for research, analysis, or content generation +- **Debugging and Monitoring**: Observe agent behavior and decision-making in real-time +- **User Experience**: Reduce perceived latency by showing incremental results +- **Live Dashboards**: Build monitoring interfaces that display crew execution status + +## Cancellation and Resource Cleanup + +`CrewStreamingOutput` supports graceful cancellation so that in-flight work stops promptly when the consumer disconnects. + +### Async Context Manager + +```python Code +streaming = await crew.akickoff(inputs={"topic": "AI"}) + +async with streaming: + async for chunk in streaming: + print(chunk.content, end="", flush=True) +``` + +### Explicit Cancellation + +```python Code +streaming = await crew.akickoff(inputs={"topic": "AI"}) +try: + async for chunk in streaming: + print(chunk.content, end="", flush=True) +finally: + await streaming.aclose() # async + # streaming.close() # sync equivalent +``` + +After cancellation, `streaming.is_cancelled` and `streaming.is_completed` are both `True`. Both `aclose()` and `close()` are idempotent. + +## Important Notes + +- Streaming automatically enables LLM streaming for all agents in the crew +- You must iterate through all chunks before accessing the `.result` property +- For `kickoff_for_each_async()` with streaming, use `.results` (plural) to get all outputs +- Streaming adds minimal overhead and can actually improve perceived performance +- Each chunk includes full context (task, agent, chunk type) for rich UIs + +## Error Handling + +Handle errors during streaming execution: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +try: + for chunk in streaming: + print(chunk.content, end="", flush=True) + + result = streaming.result + print(f"\nSuccess: {result.raw}") + +except Exception as e: + print(f"\nError during streaming: {e}") + if streaming.is_completed: + print("Streaming completed but an error occurred") +``` + +By leveraging streaming, you can build more responsive and interactive applications with CrewAI, providing users with real-time visibility into agent execution and results. \ No newline at end of file diff --git a/docs/v1.15.13/en/learn/streaming-flow-execution.mdx b/docs/v1.15.13/en/learn/streaming-flow-execution.mdx new file mode 100644 index 0000000000..e0c5ae2ccb --- /dev/null +++ b/docs/v1.15.13/en/learn/streaming-flow-execution.mdx @@ -0,0 +1,479 @@ +--- +title: Streaming Flow Execution +description: Stream real-time output from your CrewAI flow execution +icon: wave-pulse +mode: "wide" +--- + +## Introduction + +CrewAI Flows support streaming output, allowing you to receive real-time updates as your flow executes. This feature enables you to build responsive applications that display results incrementally, provide live progress updates, and create better user experiences for long-running workflows. + +## How Flow Streaming Works + +When streaming is enabled on a Flow, CrewAI captures and streams output from any crews, LLM calls, tools, and lifecycle events within the flow. The stream delivers ordered `StreamFrame` items with printable content plus structured event data as execution progresses. + +## Enabling Streaming + +To enable streaming, set the `stream` attribute to `True` on your Flow class: + +```python Code +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Task + +class ResearchFlow(Flow): + stream = True # Enable streaming for the entire flow + + @start() + def initialize(self): + return {"topic": "AI trends"} + + @listen(initialize) + def research_topic(self, data): + researcher = Agent( + role="Research Analyst", + goal="Research topics thoroughly", + backstory="Expert researcher with analytical skills", + ) + + task = Task( + description="Research {topic} and provide insights", + expected_output="Detailed research findings", + agent=researcher, + ) + + crew = Crew( + agents=[researcher], + tasks=[task], + ) + + return crew.kickoff(inputs=data) +``` + +## Synchronous Streaming + +When you call `kickoff()` on a flow with streaming enabled, it returns a stream session that yields ordered `StreamFrame` items: + +```python Code +flow = ResearchFlow() + +# Start streaming execution +streaming = flow.kickoff() + +# Iterate over stream items as they arrive +for item in streaming: + print(item.content, end="", flush=True) + +# Access the final result after streaming completes +result = streaming.result +print(f"\n\nFinal output: {result}") +``` + +### Stream Item Information + +Each item provides both printable content and structured event data: + +```python Code +streaming = flow.kickoff() + +for item in streaming: + print(f"Channel: {item.channel}") + print(f"Type: {item.type}") + print(f"Content: {item.content}") + print(f"Event payload: {item.event}") +``` + +### Accessing Streaming Properties + +The stream session provides useful properties and methods: + +```python Code +streaming = flow.kickoff() + +# Iterate and collect items +for item in streaming: + print(item.content, end="", flush=True) + +# After iteration completes +print(f"\nCompleted: {streaming.is_completed}") +print(f"Total frames: {len(streaming.frames)}") +print(f"Final result: {streaming.result}") +``` + +## Asynchronous Streaming + +For async applications, use `kickoff_async()` with async iteration: + +```python Code +import asyncio + +async def stream_flow(): + flow = ResearchFlow() + + # Start async streaming + streaming = await flow.kickoff_async() + + # Async iteration over stream items + async for item in streaming: + print(item.content, end="", flush=True) + + # Access final result + result = streaming.result + print(f"\n\nFinal output: {result}") + +asyncio.run(stream_flow()) +``` + +## Streaming with Multi-Step Flows + +Streaming works seamlessly across multiple flow steps, including flows that execute multiple crews: + +```python Code +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Task + +class MultiStepFlow(Flow): + stream = True + + @start() + def research_phase(self): + """First crew: Research the topic.""" + researcher = Agent( + role="Research Analyst", + goal="Gather comprehensive information", + backstory="Expert at finding relevant information", + ) + + task = Task( + description="Research AI developments in healthcare", + expected_output="Research findings on AI in healthcare", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[task]) + result = crew.kickoff() + + self.state["research"] = result.raw + return result.raw + + @listen(research_phase) + def analysis_phase(self, research_data): + """Second crew: Analyze the research.""" + analyst = Agent( + role="Data Analyst", + goal="Analyze information and extract insights", + backstory="Expert at identifying patterns and trends", + ) + + task = Task( + description="Analyze this research: {research}", + expected_output="Key insights and trends", + agent=analyst, + ) + + crew = Crew(agents=[analyst], tasks=[task]) + return crew.kickoff(inputs={"research": research_data}) + + +# Stream across both phases +flow = MultiStepFlow() +streaming = flow.kickoff() + +current_step = "" +for item in streaming: + # Track which flow step is executing + step_name = item.event.get("method_name") or item.event.get("task_name") + if step_name and step_name != current_step: + current_step = step_name + print(f"\n\n=== {step_name} ===\n") + + print(item.content, end="", flush=True) + +result = streaming.result +print(f"\n\nFinal analysis: {result}") +``` + +## Practical Example: Progress Dashboard + +Here's a complete example showing how to build a progress dashboard with streaming: + +```python Code +import asyncio +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Task + +class ResearchPipeline(Flow): + stream = True + + @start() + def gather_data(self): + researcher = Agent( + role="Data Gatherer", + goal="Collect relevant information", + backstory="Skilled at finding quality sources", + ) + + task = Task( + description="Gather data on renewable energy trends", + expected_output="Collection of relevant data points", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[task]) + result = crew.kickoff() + self.state["data"] = result.raw + return result.raw + + @listen(gather_data) + def analyze_data(self, data): + analyst = Agent( + role="Data Analyst", + goal="Extract meaningful insights", + backstory="Expert at data analysis", + ) + + task = Task( + description="Analyze: {data}", + expected_output="Key insights and trends", + agent=analyst, + ) + + crew = Crew(agents=[analyst], tasks=[task]) + return crew.kickoff(inputs={"data": data}) + + +async def run_with_dashboard(): + flow = ResearchPipeline() + + print("="*60) + print("RESEARCH PIPELINE DASHBOARD") + print("="*60) + + streaming = await flow.kickoff_async() + + current_agent = "" + current_task = "" + frame_count = 0 + + async for item in streaming: + frame_count += 1 + + # Display phase transitions + task_name = item.event.get("task_name", "") + agent_role = item.event.get("agent_role", "") + if task_name and task_name != current_task: + current_task = task_name + current_agent = agent_role + print(f"\n\n📋 Phase: {current_task}") + print(f"👤 Agent: {current_agent}") + print("-" * 60) + + # Display text output + if item.content: + print(item.content, end="", flush=True) + + # Display tool usage + elif item.channel == "tools": + print(f"\n🔧 Tool event: {item.type}") + + # Show completion summary + result = streaming.result + print(f"\n\n{'='*60}") + print("PIPELINE COMPLETE") + print(f"{'='*60}") + print(f"Total frames: {frame_count}") + print(f"Final output length: {len(str(result))} characters") + +asyncio.run(run_with_dashboard()) +``` + +## Streaming with State Management + +Streaming works naturally with Flow state management: + +```python Code +from pydantic import BaseModel + +class AnalysisState(BaseModel): + topic: str = "" + research: str = "" + insights: str = "" + +class StatefulStreamingFlow(Flow[AnalysisState]): + stream = True + + @start() + def research(self): + # State is available during streaming + topic = self.state.topic + print(f"Researching: {topic}") + + researcher = Agent( + role="Researcher", + goal="Research topics thoroughly", + backstory="Expert researcher", + ) + + task = Task( + description=f"Research {topic}", + expected_output="Research findings", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[task]) + result = crew.kickoff() + + self.state.research = result.raw + return result.raw + + @listen(research) + def analyze(self, research): + # Access updated state + print(f"Analyzing {len(self.state.research)} chars of research") + + analyst = Agent( + role="Analyst", + goal="Extract insights", + backstory="Expert analyst", + ) + + task = Task( + description="Analyze: {research}", + expected_output="Key insights", + agent=analyst, + ) + + crew = Crew(agents=[analyst], tasks=[task]) + result = crew.kickoff(inputs={"research": research}) + + self.state.insights = result.raw + return result.raw + + +# Run with streaming +flow = StatefulStreamingFlow() +streaming = flow.kickoff(inputs={"topic": "quantum computing"}) + +for item in streaming: + print(item.content, end="", flush=True) + +result = streaming.result +print(f"\n\nFinal state:") +print(f"Topic: {flow.state.topic}") +print(f"Research length: {len(flow.state.research)}") +print(f"Insights length: {len(flow.state.insights)}") +``` + +## Use Cases + +Flow streaming is particularly valuable for: + +- **Multi-Stage Workflows**: Show progress across research, analysis, and synthesis phases +- **Complex Pipelines**: Provide visibility into long-running data processing flows +- **Interactive Applications**: Build responsive UIs that display intermediate results +- **Monitoring and Debugging**: Observe flow execution and crew interactions in real-time +- **Progress Tracking**: Show users which stage of the workflow is currently executing +- **Live Dashboards**: Create monitoring interfaces for production flows + +## Stream Frame Channels + +Flow streaming yields `StreamFrame` items across several channels: + +### LLM Frames + +Standard text content from LLM responses: + +```python Code +for item in streaming: + if item.channel == "llm" and item.content: + print(item.content, end="", flush=True) +``` + +### Tool Frames + +Information about tool calls within the flow: + +```python Code +for item in streaming: + if item.channel == "tools": + print(f"\nTool event: {item.type}") + print(f"Payload: {item.event}") +``` + +## Error Handling + +Handle errors gracefully during streaming: + +```python Code +flow = ResearchFlow() +streaming = flow.kickoff() + +try: + for item in streaming: + print(item.content, end="", flush=True) + + result = streaming.result + print(f"\nSuccess! Result: {result}") + +except Exception as e: + print(f"\nError during flow execution: {e}") + if streaming.is_completed: + print("Streaming completed but flow encountered an error") +``` + +## Cancellation and Resource Cleanup + +The stream session supports graceful cancellation so that in-flight work stops promptly when the consumer disconnects. + +### Async Context Manager + +```python Code +streaming = await flow.kickoff_async() + +async with streaming: + async for item in streaming: + print(item.content, end="", flush=True) +``` + +### Explicit Cancellation + +```python Code +streaming = await flow.kickoff_async() +try: + async for item in streaming: + print(item.content, end="", flush=True) +finally: + await streaming.aclose() # async + # streaming.close() # sync equivalent +``` + +After cancellation, `streaming.is_cancelled` and `streaming.is_completed` are both `True`. Both `aclose()` and `close()` are idempotent. + +## Important Notes + +- Streaming automatically enables LLM streaming for any crews used within the flow +- You must iterate through all stream items before accessing the `.result` property +- Streaming works with both structured and unstructured flow state +- Flow streaming captures output from all crews and LLM calls in the flow +- Each frame includes structured event context such as channel, type, namespace, and payload +- Streaming adds minimal overhead to flow execution + +## Combining with Flow Visualization + +You can combine streaming with flow visualization to provide a complete picture: + +```python Code +# Generate flow visualization +flow = ResearchFlow() +flow.plot("research_flow") # Creates HTML visualization + +# Run with streaming +streaming = flow.kickoff() +for item in streaming: + print(item.content, end="", flush=True) + +result = streaming.result +print(f"\nFlow complete! View structure at: research_flow.html") +``` + +By leveraging flow streaming, you can build sophisticated, responsive applications that provide users with real-time visibility into complex multi-stage workflows, making your AI automations more transparent and engaging. diff --git a/docs/v1.15.13/en/learn/streaming-runtime-contract.mdx b/docs/v1.15.13/en/learn/streaming-runtime-contract.mdx new file mode 100644 index 0000000000..b7116d4706 --- /dev/null +++ b/docs/v1.15.13/en/learn/streaming-runtime-contract.mdx @@ -0,0 +1,194 @@ +--- +title: Streaming Runtime Contract +description: Stream ordered runtime frames from Flows, direct LLM calls, and conversational turns. +icon: tower-broadcast +mode: "wide" +--- + +## Overview + +CrewAI exposes a frame-based streaming contract for runtimes that need more than plain text chunks. The contract emits ordered `StreamFrame` objects for Flow lifecycle events, direct LLM tokens, tool activity, conversation messages, and custom events. + +Use this API when you are building a UI, service bridge, terminal app, or deployment runtime that needs a stable stream of structured events while a Flow, chat turn, or direct LLM call is running. + +## StreamFrame + +Every frame has the same envelope: + +```python +from crewai.types.streaming import StreamFrame + +frame.id # unique frame id +frame.seq # execution-local order, when available +frame.type # source event type, such as "flow_started" +frame.channel # "llm", "flow", "tools", "messages", "lifecycle", or "custom" +frame.namespace # source/runtime namespace +frame.timestamp # event timestamp +frame.parent_id # parent event id, when available +frame.previous_id # previous event id, when available +frame.data # event payload +frame.event # alias for frame.data +frame.content # printable text for token-like frames, otherwise "" +``` + +The `channel` field is the fastest way to route frames in consumers: + +| Channel | Contains | +|---------|----------| +| `llm` | Token and thinking chunks from LLM streaming events | +| `flow` | Flow lifecycle, method execution, routing, and pause/resume events | +| `tools` | Tool usage events | +| `messages` | Conversation transcript events | +| `lifecycle` | Runtime lifecycle events that are not specific to another channel | +| `custom` | Events that do not map to a built-in channel | + +`frame.type` preserves the source event type, so consumers can handle specific events inside a channel. + +## Stream a Flow + +Set `stream=True` on a Flow to make `kickoff()` return a stream session: + +```python +from crewai.flow import Flow, start + + +class ReportFlow(Flow): + @start() + def generate(self): + return "done" + + +flow = ReportFlow(stream=True) +stream = flow.kickoff() + +with stream: + for chunk in stream: + print(chunk.content, end="", flush=True) + if chunk.type == "tool_usage_started": + print(chunk.event["tool_name"]) + +result = stream.result +``` + +You must consume the stream before reading `stream.result`. Accessing the result early raises a `RuntimeError` so consumers do not accidentally treat a partial run as complete. + +You can also call `flow.stream_events(...)` directly when you want streaming for a single invocation without setting `stream=True` on the Flow instance. + +## Filter by Channel + +`StreamSession` exposes channel projections that preserve global frame order within the selected channel: + +```python +stream = flow.stream_events() + +with stream: + for frame in stream.llm: + print(frame.content, end="", flush=True) + +result = stream.result +``` + +Available projections are: + +| Projection | Frames | +|------------|--------| +| `stream.events` | All frames | +| `stream.llm` | LLM frames | +| `stream.messages` | Conversation message frames | +| `stream.flow` | Flow frames | +| `stream.tools` | Tool frames | +| `stream.interleave([...])` | A selected set of channels | + +Use `stream.interleave(["flow", "llm", "messages"])` when a consumer wants only some channels but still needs their relative order. + +## Async Streaming + +Use `astream()` for async consumers: + +```python +flow = ReportFlow() +stream = flow.astream() + +async with stream: + async for chunk in stream.events: + print(chunk.channel, chunk.type, chunk.content) + +result = stream.result +``` + +The async session has the same projections as the sync session. + +## Stream a Direct LLM Call + +`llm.call(...)` still returns the final assembled result. Use `llm.stream_events(...)` when you want to iterate over chunks as they arrive while keeping the structured event payload: + +```python +from crewai import LLM + + +llm = LLM(model="gpt-4o-mini") +stream = llm.stream_events( + messages=[ + { + "role": "user", + "content": "Explain CrewAI streaming in two short sentences.", + } + ] +) + +with stream: + for chunk in stream: + print(chunk.content, end="", flush=True) + +result = stream.result +``` + +`llm.stream_events(...)` temporarily enables streaming for the wrapped call and restores the LLM's previous `stream` setting afterward. Provider integrations continue to emit the underlying LLM stream events; this helper provides a common iterator API over those events for every LLM provider. + +## Conversational Turns + +Conversational Flows can stream one user turn with `stream_turn()`: + +```python +from crewai import Flow +from crewai.experimental.conversational import ConversationConfig, ConversationState + + +@ConversationConfig(llm="gpt-4o-mini", defer_trace_finalization=True) +class ChatFlow(Flow[ConversationState]): + conversational = True + + +flow = ChatFlow() +stream = flow.stream_turn("What can you help me with?", session_id="session-1") + +with stream: + for frame in stream.events: + if frame.channel == "llm" and frame.type == "llm_stream_chunk": + print(frame.content, end="", flush=True) + +reply = stream.result +``` + +During `stream_turn()`, the built-in conversational answer path enables LLM token streaming for that turn and restores the LLM's previous `stream` setting afterward. Custom route handlers that create their own agents or LLM instances should configure those LLMs for streaming if they need token-level output. + +## Cleanup + +Use the session as a context manager when possible. If a client disconnects before the stream is exhausted, close the session explicitly: + +```python +stream = flow.stream_events() + +try: + for frame in stream.events: + print(frame.type) +finally: + if not stream.is_exhausted: + stream.close() +``` + +For async streams, use `await stream.aclose()`. + +## Legacy Chunk Streaming + +Crew streaming with `stream=True` still returns the chunk-oriented `CrewStreamingOutput` API described in [Streaming Crew Execution](/en/learn/streaming-crew-execution). Direct `llm.call(...)` still returns the final LLM result. The frame contract is intended for runtimes that need a stable event envelope across Flows, direct LLM calls, conversational turns, tools, and messages. diff --git a/docs/v1.15.13/en/learn/tool-hooks.mdx b/docs/v1.15.13/en/learn/tool-hooks.mdx new file mode 100644 index 0000000000..793fd9e626 --- /dev/null +++ b/docs/v1.15.13/en/learn/tool-hooks.mdx @@ -0,0 +1,340 @@ +--- +title: Tool Call Hooks +description: Learn how to use tool call hooks to intercept, modify, and control tool execution in CrewAI +mode: "wide" +--- + +Tool Call Hooks provide fine-grained control over tool execution during agent +operations. These hooks allow you to intercept tool calls, modify inputs, +transform outputs, implement safety checks, and add comprehensive logging or +monitoring. + +## Overview + +Tool hooks are executed at two interception points: + +| Point | When | Hook receives | +|-------|------|---------------| +| `PRE_TOOL_CALL` | Before every tool execution | `ToolCallHookContext` | +| `POST_TOOL_CALL` | After every tool execution | `ToolCallHookContext` (with results set) | + +Write them with the [`@on` decorator](/edge/en/learn/execution-hooks). The +[legacy `@before_tool_call` / `@after_tool_call` decorators](#legacy-decorators) +keep working unchanged — both styles register on the same engine and run in one +ordered chain. + +## Hook Signature + +```python +from crewai.hooks import on, HookAborted, InterceptionPoint, ToolCallHookContext + +@on(InterceptionPoint.PRE_TOOL_CALL) +def before_hook(ctx: ToolCallHookContext) -> None: + # Mutate ctx.tool_input in place, or + # raise HookAborted(reason, source) to block the call + ... + +@on(InterceptionPoint.POST_TOOL_CALL) +def after_hook(ctx: ToolCallHookContext) -> str | None: + # Return a string to replace ctx.tool_result + # Return None to keep the original result + ... +``` + +Unlike the boundary and step points, the tool-call points pass the rich +`ToolCallHookContext` directly as the hook argument (there is no separate +`ctx.payload`): mutate `ctx.tool_input` in place before the call, and return a +string to replace the result after it. + +When a call is blocked, the tool does not run and the agent receives +`"Tool execution blocked by hook. Tool: "` as the result — the run +continues. `POST_TOOL_CALL` hooks still fire on blocked calls, so monitoring +hooks see every attempt. + +## Tool Hook Context + +The `ToolCallHookContext` object provides comprehensive access to tool +execution state: + +```python +class ToolCallHookContext: + tool_name: str # Name of the tool being called + tool_input: dict[str, Any] # Mutable tool input parameters + tool: CrewStructuredTool # Tool instance reference + agent: Agent | BaseAgent | None # Agent executing the tool + task: Task | None # Current task + crew: Crew | None # Crew instance + tool_result: str | None # Agent-facing result string (POST_TOOL_CALL only) + raw_tool_result: Any | None # Raw Python result (POST_TOOL_CALL only) +``` + +For typed tool outputs, `tool_result` is the string the agent sees. By default, +this is JSON. If the tool uses custom formatting, it can be Markdown or another +string. Use `raw_tool_result` when your hook needs the typed object or +dictionary; it is not affected by result replacement. + +The context also exposes `request_human_input(prompt, default_message)`, which +pauses live console updates and collects input from the terminal — useful for +approval gates. + +### Modifying Tool Inputs + +**Important:** Always modify tool inputs in-place: + +```python +# ✅ Correct - modify in-place +@on(InterceptionPoint.PRE_TOOL_CALL) +def sanitize_input(ctx: ToolCallHookContext) -> None: + ctx.tool_input['query'] = ctx.tool_input['query'].lower() + +# ❌ Wrong - replaces dict reference; the tool never sees it +@on(InterceptionPoint.PRE_TOOL_CALL) +def wrong_approach(ctx: ToolCallHookContext) -> None: + ctx.tool_input = {'query': 'new query'} +``` + +## Registration Methods + +### 1. Global Hooks + +Apply to all tool calls across all crews. Use `tools=` / `agents=` filters to +scope a hook: + +```python +from crewai.hooks import on, HookAborted, InterceptionPoint + +@on(InterceptionPoint.PRE_TOOL_CALL) +def log_tool_call(ctx): + print(f"Tool: {ctx.tool_name}, input: {ctx.tool_input}") + +@on(InterceptionPoint.PRE_TOOL_CALL, tools=["delete_file", "drop_table"]) +def block_destructive(ctx): + raise HookAborted(reason=f"{ctx.tool_name} is not allowed", source="safety-policy") + +@on(InterceptionPoint.POST_TOOL_CALL, tools=["web_search"], agents=["Researcher"]) +def log_search_results(ctx): + print(f"search returned {len(ctx.tool_result or '')} chars") +``` + +### 2. Crew-Scoped Hooks + +Apply the same decorator to a method inside a `@CrewBase` class to scope the +hook to that crew only: + +```python +from crewai.hooks import on, InterceptionPoint + +@CrewBase +class MyProjCrew: + @on(InterceptionPoint.PRE_TOOL_CALL) + def validate_tool_inputs(self, ctx): + # Only applies to this crew + if ctx.tool_name == "web_search" and not ctx.tool_input.get("query"): + raise HookAborted(reason="empty search query", source="input-validation") + + @crew + def crew(self) -> Crew: + return Crew(agents=self.agents, tasks=self.tasks, process=Process.sequential) +``` + +## Common Use Cases + +### 1. Safety Guardrails + +```python +@on(InterceptionPoint.PRE_TOOL_CALL) +def safety_check(ctx: ToolCallHookContext) -> None: + destructive = {'delete_file', 'drop_table', 'remove_user', 'system_shutdown'} + if ctx.tool_name in destructive: + raise HookAborted(reason=f"{ctx.tool_name} is destructive", source="safety-policy") +``` + +### 2. Human Approval Gate + +```python +@on(InterceptionPoint.PRE_TOOL_CALL, tools=["send_email", "make_purchase", "delete_file"]) +def require_approval(ctx: ToolCallHookContext) -> None: + response = ctx.request_human_input( + prompt=f"Approve {ctx.tool_name}?", + default_message=f"Input: {ctx.tool_input}\nType 'yes' to approve:", + ) + if response.lower() != 'yes': + raise HookAborted(reason="denied by operator", source="approval-gate") +``` + +### 3. Input Validation and Sanitization + +```python +@on(InterceptionPoint.PRE_TOOL_CALL, tools=["web_search"]) +def validate_query(ctx: ToolCallHookContext) -> None: + query = ctx.tool_input.get('query', '') + if len(query) < 3: + raise HookAborted(reason="search query too short", source="input-validation") + ctx.tool_input['query'] = query.strip().lower() + +@on(InterceptionPoint.PRE_TOOL_CALL, tools=["read_file"]) +def validate_path(ctx: ToolCallHookContext) -> None: + path = ctx.tool_input.get('path', '') + if '..' in path or path.startswith('/'): + raise HookAborted(reason="invalid file path", source="input-validation") +``` + +### 4. Result Sanitization + +```python +import re + +@on(InterceptionPoint.POST_TOOL_CALL) +def sanitize_sensitive_data(ctx: ToolCallHookContext) -> str | None: + if not ctx.tool_result: + return None + result = re.sub( + r'(api[_-]?key|token)["\']?\s*[:=]\s*["\']?[\w-]+', + r'\1: [REDACTED]', + ctx.tool_result, + flags=re.IGNORECASE, + ) + return re.sub( + r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', + '[EMAIL-REDACTED]', + result, + ) +``` + +### 5. Tool Usage Analytics + +```python +import time +from collections import defaultdict + +tool_stats = defaultdict(lambda: {'count': 0, 'total_time': 0}) + +@on(InterceptionPoint.PRE_TOOL_CALL) +def start_timer(ctx: ToolCallHookContext) -> None: + ctx.tool_input['_start_time'] = time.time() + +@on(InterceptionPoint.POST_TOOL_CALL) +def track_tool_usage(ctx: ToolCallHookContext) -> None: + start_time = ctx.tool_input.pop('_start_time', time.time()) + tool_stats[ctx.tool_name]['count'] += 1 + tool_stats[ctx.tool_name]['total_time'] += time.time() - start_time +``` + +### 6. Rate Limiting + +```python +from collections import defaultdict +from datetime import datetime, timedelta + +tool_call_history = defaultdict(list) + +@on(InterceptionPoint.PRE_TOOL_CALL) +def rate_limit_tools(ctx: ToolCallHookContext) -> None: + now = datetime.now() + history = tool_call_history[ctx.tool_name] + history[:] = [t for t in history if now - t < timedelta(minutes=1)] + if len(history) >= 10: + raise HookAborted(reason=f"rate limit exceeded for {ctx.tool_name}", + source="rate-limiter") + history.append(now) +``` + +## Hook Management + +```python +from crewai.hooks import ( + InterceptionPoint, + clear_all_hooks, + clear_hooks, + get_hooks, + unregister_hook, +) + +# Unregister a specific hook +unregister_hook(InterceptionPoint.PRE_TOOL_CALL, my_hook) + +# Clear one point, or everything (e.g. between tests) +clear_hooks(InterceptionPoint.POST_TOOL_CALL) +clear_all_hooks() + +# Inspect what's registered +print(len(get_hooks(InterceptionPoint.PRE_TOOL_CALL))) +``` + +The legacy management API (`register_before_tool_call_hook`, +`unregister_before_tool_call_hook`, `clear_before_tool_call_hooks`, +`clear_all_tool_call_hooks`, `get_before_tool_call_hooks`, and their `after_` +counterparts) operates on the same underlying registries, so either API can +manage hooks registered by the other. + +## Legacy Decorators + +The original per-point decorators keep working unchanged and run in the same +registration-order chain as `@on` hooks: + +```python +from crewai.hooks import before_tool_call, after_tool_call + +@before_tool_call +def block_dangerous_tools(context): + if context.tool_name in ('delete_database', 'drop_table'): + return False # Block execution + return None + +@after_tool_call(tools=["web_search"]) +def sanitize_results(context): + if context.tool_result and "password" in context.tool_result.lower(): + return context.tool_result.replace("password", "[REDACTED]") + return None +``` + +Differences from `@on`: + +- **Blocking** is `return False` from a before hook — equivalent to raising + `HookAborted`, but without a custom reason or source for telemetry. The agent + sees the same `"Tool execution blocked by hook"` message. +- **Signatures** are point-specific: before hooks return `bool | None`, after + hooks return `str | None`. The context object is the same + `ToolCallHookContext`. +- **Filters and crew-scoping** work the same way: + `@before_tool_call(tools=[...], agents=[...])`, and applying the decorator to + a `@CrewBase` method scopes it to that crew. + +Prefer `@on` for new code; keep the legacy style where it is already in use — +there is no behavioral penalty. + +## Best Practices + +1. **Keep hooks focused and fast** — they run on every tool call +2. **Modify in-place** — always mutate `ctx.tool_input`, never replace the dict +3. **Prefer filters over conditionals** — `tools=` / `agents=` keep hook bodies small +4. **Abort loudly** — raise `HookAborted` with a meaningful reason and source; + any other exception is swallowed (fail-open) +5. **Use type hints** — annotate with `ToolCallHookContext` for IDE support +6. **Clear hooks in tests** — call `clear_all_hooks()` between test runs + +## Troubleshooting + +### Hook Not Executing +- Verify the hook is registered before crew execution +- Check whether an earlier hook blocked the call (subsequent pre hooks don't run) +- Check `tools=` / `agents=` filters against the actual tool name and agent role + +### Input Modifications Not Working +- Use in-place modifications: `ctx.tool_input['key'] = value` +- Don't replace the dict: `ctx.tool_input = {}` + +### Result Modifications Not Working +- Return the modified string from a `POST_TOOL_CALL` hook +- Returning `None` keeps the original result + +### Tool Blocked Unexpectedly +- Check all pre hooks for `HookAborted` / `return False` conditions +- The abort reason and source appear on the `HookDispatchedEvent` telemetry + +## Related Documentation + +- [Execution Hooks Overview →](/edge/en/learn/execution-hooks) +- [LLM Call Hooks →](/edge/en/learn/llm-hooks) +- [Execution Boundary Hooks →](/edge/en/learn/execution-boundary-hooks) +- [Step Hooks →](/edge/en/learn/step-hooks) diff --git a/docs/v1.15.13/en/learn/using-annotations.mdx b/docs/v1.15.13/en/learn/using-annotations.mdx new file mode 100644 index 0000000000..a9a7fec1aa --- /dev/null +++ b/docs/v1.15.13/en/learn/using-annotations.mdx @@ -0,0 +1,155 @@ +--- +title: "Using Annotations in crew.py" +description: "Learn how to use classic Python annotations to structure agents, tasks, and components in CrewAI" +icon: "at" +mode: "wide" +--- + +This guide explains how to use annotations to properly reference **agents**, **tasks**, and other components in a classic `crew.py` file. + + +New crew projects created with `crewai create crew ` are JSON-first and use `crew.jsonc` plus `agents/*.jsonc`. Use this annotations guide when you are working in a classic project created with `crewai create crew --classic`, migrating an existing Python/YAML project, or need decorator-based Python control. + + +## Introduction + +Annotations in the CrewAI framework are used to decorate classes and methods, providing metadata and functionality to various components of your crew. In classic Python/YAML projects, these annotations help organize the code that loads `config/agents.yaml`, `config/tasks.yaml`, and returns the `Crew` object. + +## Available Annotations + +The CrewAI framework provides the following annotations: + +- `@CrewBase`: Used to decorate the main crew class. +- `@agent`: Decorates methods that define and return Agent objects. +- `@task`: Decorates methods that define and return Task objects. +- `@crew`: Decorates the method that creates and returns the Crew object. +- `@llm`: Decorates methods that initialize and return Language Model objects. +- `@tool`: Decorates methods that initialize and return Tool objects. +- `@callback`: Used for defining callback methods. +- `@output_json`: Used for methods that output JSON data. +- `@output_pydantic`: Used for methods that output Pydantic models. +- `@cache_handler`: Used for defining cache handling methods. + +## Usage Examples + +Let's go through examples of how to use these annotations: + +### 1. Crew Base Class + +```python +@CrewBase +class LinkedinProfileCrew(): + """LinkedinProfile crew""" + agents_config = 'config/agents.yaml' + tasks_config = 'config/tasks.yaml' +``` + +The `@CrewBase` annotation is used to decorate the main crew class. This class typically contains configurations and methods for creating agents, tasks, and the crew itself. + + +`@CrewBase` does more than register the class: + +- **Configuration bootstrapping:** looks for `agents_config` and `tasks_config` (defaulting to `config/agents.yaml` and `config/tasks.yaml`) beside the class file, loads them at instantiation, and safely falls back to empty dicts if files are missing. +- **Decorator orchestration:** keeps memoized references to every method marked with `@agent`, `@task`, `@before_kickoff`, or `@after_kickoff` so they are instantiated once per crew and executed in declaration order. +- **Hook wiring:** automatically attaches the preserved kickoff hooks to the `Crew` object returned by the `@crew` method, making them run before and after `.kickoff()`. +- **MCP integration:** when the class defines `mcp_server_params`, `get_mcp_tools()` lazily starts an MCP server adapter, hydrates the declared tools, and an internal after-kickoff hook stops the adapter. See [MCP overview](/en/mcp/overview) for adapter configuration details. + + +### 2. Tool Definition + +```python +@tool +def myLinkedInProfileTool(self): + return LinkedInProfileTool() +``` + +The `@tool` annotation is used to decorate methods that return tool objects. These tools can be used by agents to perform specific tasks. + +### 3. LLM Definition + +```python +@llm +def groq_llm(self): + api_key = os.getenv('api_key') + return ChatGroq(api_key=api_key, temperature=0, model_name="mixtral-8x7b-32768") +``` + +The `@llm` annotation is used to decorate methods that initialize and return Language Model objects. These LLMs are used by agents for natural language processing tasks. + +### 4. Agent Definition + +```python +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'] + ) +``` + +The `@agent` annotation is used to decorate methods that define and return Agent objects. + +### 5. Task Definition + +```python +@task +def research_task(self) -> Task: + return Task( + config=self.tasks_config['research_linkedin_task'], + agent=self.researcher() + ) +``` + +The `@task` annotation is used to decorate methods that define and return Task objects. These methods specify the task configuration and the agent responsible for the task. + +### 6. Crew Creation + +```python +@crew +def crew(self) -> Crew: + """Creates the LinkedinProfile crew""" + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +The `@crew` annotation is used to decorate the method that creates and returns the `Crew` object. This method assembles all the components (agents and tasks) into a functional crew. + +## Classic YAML Configuration + +In classic projects, agent configurations are typically stored in a YAML file. Here's an example of how the `agents.yaml` file might look for the researcher agent: + +```yaml +researcher: + role: > + LinkedIn Profile Senior Data Researcher + goal: > + Uncover detailed LinkedIn profiles based on provided name {name} and domain {domain} + Generate a Dall-E image based on domain {domain} + backstory: > + You're a seasoned researcher with a knack for uncovering the most relevant LinkedIn profiles. + Known for your ability to navigate LinkedIn efficiently, you excel at gathering and presenting + professional information clearly and concisely. + allow_delegation: False + verbose: True + llm: groq_llm + tools: + - myLinkedInProfileTool + - mySerperDevTool + - myDallETool +``` + +This YAML configuration corresponds to the researcher agent defined in the `LinkedinProfileCrew` class. The configuration specifies the agent's role, goal, backstory, and other properties such as the LLM and tools it uses. + +Note how the `llm` and `tools` in the YAML file correspond to the methods decorated with `@llm` and `@tool` in the Python class. + +## Best Practices + +- **Consistent Naming**: Use clear and consistent naming conventions for your methods. For example, agent methods could be named after their roles (e.g., researcher, reporting_analyst). +- **Environment Variables**: Use environment variables for sensitive information like API keys. +- **Flexibility**: Design your crew to be flexible by allowing easy addition or removal of agents and tasks. +- **YAML-Code Correspondence**: In classic projects, ensure that the names and structures in your YAML files correspond correctly to the decorated methods in your Python code. + +By following these guidelines and properly using annotations, you can maintain classic Python/YAML crews cleanly. For new crews, prefer the JSON-first structure covered in [Crews](/en/concepts/crews). diff --git a/docs/v1.15.13/en/mcp/dsl-integration.mdx b/docs/v1.15.13/en/mcp/dsl-integration.mdx new file mode 100644 index 0000000000..b2eb97c141 --- /dev/null +++ b/docs/v1.15.13/en/mcp/dsl-integration.mdx @@ -0,0 +1,349 @@ +--- +title: MCP DSL Integration +description: Learn how to use CrewAI's simple DSL syntax to integrate MCP servers directly with your agents using the mcps field. +icon: code +mode: "wide" +--- + +## Overview + +CrewAI's MCP DSL (Domain Specific Language) integration provides the **simplest way** to connect your agents to MCP (Model Context Protocol) servers. Just add an `mcps` field to your agent and CrewAI handles all the complexity automatically. + + + This is the **recommended approach** for most MCP use cases. For advanced + scenarios requiring manual connection management, see + [MCPServerAdapter](/en/mcp/overview#advanced-mcpserveradapter). + + +## Basic Usage + +Add MCP servers to your agent using the `mcps` field: + +```python +from crewai import Agent + +agent = Agent( + role="Research Assistant", + goal="Help with research and analysis tasks", + backstory="Expert assistant with access to advanced research tools", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=your_key&profile=research" + ] +) + +# MCP tools are now automatically available! +# No need for manual connection management or tool configuration +``` + +## Supported Reference Formats + +### External MCP Remote Servers + +```python +# Basic HTTPS server +"https://api.example.com/mcp" + +# Server with authentication +"https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile" + +# Server with custom path +"https://services.company.com/api/v1/mcp" +``` + +### Specific Tool Selection + +Use the `#` syntax to select specific tools from a server: + +```python +# Get only the forecast tool from weather server +"https://weather.api.com/mcp#get_forecast" + +# Get only the search tool from Exa +"https://mcp.exa.ai/mcp?api_key=your_key#web_search_exa" +``` + +### Connected MCP Integrations + +Connect MCP servers from the CrewAI catalog or bring your own. Once connected in your account, reference them by slug: + +```python +# Connected MCP with all tools +"snowflake" + +# Specific tool from a connected MCP +"stripe#list_invoices" + +# Multiple connected MCPs +mcps=[ + "snowflake", + "stripe", + "github" +] +``` + +## Complete Example + +Here's a complete example using multiple MCP servers: + +```python +from crewai import Agent, Task, Crew, Process + +# Create agent with multiple MCP sources +multi_source_agent = Agent( + role="Multi-Source Research Analyst", + goal="Conduct comprehensive research using multiple data sources", + backstory="""Expert researcher with access to web search, weather data, + financial information, and academic research tools""", + mcps=[ + # External MCP servers + "https://mcp.exa.ai/mcp?api_key=your_exa_key&profile=research", + "https://weather.api.com/mcp#get_current_conditions", + + # Connected MCPs from catalog + "snowflake", + "stripe#list_invoices", + "github#search_repositories" + ] +) + +# Create comprehensive research task +research_task = Task( + description="""Research the impact of AI agents on business productivity. + Include current weather impacts on remote work, financial market trends, + and recent academic publications on AI agent frameworks.""", + expected_output="""Comprehensive report covering: + 1. AI agent business impact analysis + 2. Weather considerations for remote work + 3. Financial market trends related to AI + 4. Academic research citations and insights + 5. Competitive landscape analysis""", + agent=multi_source_agent +) + +# Create and execute crew +research_crew = Crew( + agents=[multi_source_agent], + tasks=[research_task], + process=Process.sequential, + verbose=True +) + +result = research_crew.kickoff() +print(f"Research completed with {len(multi_source_agent.mcps)} MCP data sources") +``` + +## Tool Naming and Organization + +CrewAI automatically handles tool naming to prevent conflicts: + +```python +# Original MCP server has tools: "search", "analyze" +# CrewAI creates tools: "mcp_exa_ai_search", "mcp_exa_ai_analyze" + +agent = Agent( + role="Tool Organization Demo", + goal="Show how tool naming works", + backstory="Demonstrates automatic tool organization", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=key", # Tools: mcp_exa_ai_* + "https://weather.service.com/mcp", # Tools: weather_service_com_* + "snowflake" # Tools: snowflake_* + ] +) + +# Each server's tools get unique prefixes based on the server name +# This prevents naming conflicts between different MCP servers +``` + +## Error Handling and Resilience + +The MCP DSL is designed to be robust and user-friendly: + +### Graceful Server Failures + +```python +agent = Agent( + role="Resilient Researcher", + goal="Research despite server issues", + backstory="Experienced researcher who adapts to available tools", + mcps=[ + "https://primary-server.com/mcp", # Primary data source + "https://backup-server.com/mcp", # Backup if primary fails + "https://unreachable-server.com/mcp", # Will be skipped with warning + "snowflake" # Connected MCP from catalog + ] +) + +# Agent will: +# 1. Successfully connect to working servers +# 2. Log warnings for failing servers +# 3. Continue with available tools +# 4. Not crash or hang on server failures +``` + +### Timeout Protection + +All MCP operations have built-in timeouts: + +- **Connection timeout**: 10 seconds +- **Tool execution timeout**: 30 seconds +- **Discovery timeout**: 15 seconds + +```python +# These servers will timeout gracefully if unresponsive +mcps=[ + "https://slow-server.com/mcp", # Will timeout after 10s if unresponsive + "https://overloaded-api.com/mcp" # Will timeout if discovery takes > 15s +] +``` + +## Performance Features + +### Automatic Caching + +Tool schemas are cached for 5 minutes to improve performance: + +```python +# First agent creation - discovers tools from server +agent1 = Agent(role="First", goal="Test", backstory="Test", + mcps=["https://api.example.com/mcp"]) + +# Second agent creation (within 5 minutes) - uses cached tool schemas +agent2 = Agent(role="Second", goal="Test", backstory="Test", + mcps=["https://api.example.com/mcp"]) # Much faster! +``` + +### On-Demand Connections + +Tool connections are established only when tools are actually used: + +```python +# Agent creation is fast - no MCP connections made yet +agent = Agent( + role="On-Demand Agent", + goal="Use tools efficiently", + backstory="Efficient agent that connects only when needed", + mcps=["https://api.example.com/mcp"] +) + +# MCP connection is made only when a tool is actually executed +# This minimizes connection overhead and improves startup performance +``` + +## Integration with Existing Features + +MCP tools work seamlessly with other CrewAI features: + +```python +from crewai.tools import BaseTool + +class CustomTool(BaseTool): + name: str = "custom_analysis" + description: str = "Custom analysis tool" + + def _run(self, **kwargs): + return "Custom analysis result" + +agent = Agent( + role="Full-Featured Agent", + goal="Use all available tool types", + backstory="Agent with comprehensive tool access", + + # All tool types work together + tools=[CustomTool()], # Custom tools + apps=["gmail", "slack"], # Platform integrations + mcps=[ # MCP servers + "https://mcp.exa.ai/mcp?api_key=key", + "snowflake" + ], + + verbose=True, + max_iter=15 +) +``` + +## Best Practices + +### 1. Use Specific Tools When Possible + +```python +# Good - only get the tools you need +mcps=["https://weather.api.com/mcp#get_forecast"] + +# Less efficient - gets all tools from server +mcps=["https://weather.api.com/mcp"] +``` + +### 2. Handle Authentication Securely + +```python +import os + +# Store API keys in environment variables +exa_key = os.getenv("EXA_API_KEY") +exa_profile = os.getenv("EXA_PROFILE") + +agent = Agent( + role="Secure Agent", + goal="Use MCP tools securely", + backstory="Security-conscious agent", + mcps=[f"https://mcp.exa.ai/mcp?api_key={exa_key}&profile={exa_profile}"] +) +``` + +### 3. Plan for Server Failures + +```python +# Always include backup options +mcps=[ + "https://primary-api.com/mcp", # Primary choice + "https://backup-api.com/mcp", # Backup option + "snowflake" # Connected MCP fallback +] +``` + +### 4. Use Descriptive Agent Roles + +```python +agent = Agent( + role="Weather-Enhanced Market Analyst", + goal="Analyze markets considering weather impacts", + backstory="Financial analyst with access to weather data for agricultural market insights", + mcps=[ + "https://weather.service.com/mcp#get_forecast", + "stripe#list_invoices" + ] +) +``` + +## Troubleshooting + +### Common Issues + +**No tools discovered:** + +```python +# Check your MCP server URL and authentication +# Verify the server is running and accessible +mcps=["https://mcp.example.com/mcp?api_key=valid_key"] +``` + +**Connection timeouts:** + +```python +# Server may be slow or overloaded +# CrewAI will log warnings and continue with other servers +# Check server status or try backup servers +``` + +**Authentication failures:** + +```python +# Verify API keys and credentials +# Check server documentation for required parameters +# Ensure query parameters are properly URL encoded +``` + +## Advanced: MCPServerAdapter + +For complex scenarios requiring manual connection management, use the `MCPServerAdapter` class from `crewai-tools`. Using a Python context manager (`with` statement) is the recommended approach as it automatically handles starting and stopping the connection to the MCP server. diff --git a/docs/v1.15.13/en/mcp/multiple-servers.mdx b/docs/v1.15.13/en/mcp/multiple-servers.mdx new file mode 100644 index 0000000000..6ecd8cac70 --- /dev/null +++ b/docs/v1.15.13/en/mcp/multiple-servers.mdx @@ -0,0 +1,65 @@ +--- +title: Connecting to Multiple MCP Servers +description: Learn how to use MCPServerAdapter in CrewAI to connect to multiple MCP servers simultaneously and aggregate their tools. +icon: layer-group +mode: "wide" +--- + +## Overview + +`MCPServerAdapter` in `crewai-tools` allows you to connect to multiple MCP servers concurrently. This is useful when your agents need to access tools distributed across different services or environments. The adapter aggregates tools from all specified servers, making them available to your CrewAI agents. + +## Configuration + +To connect to multiple servers, you provide a list of server parameter dictionaries to `MCPServerAdapter`. Each dictionary in the list should define the parameters for one MCP server. + +Supported transport types for each server in the list include `stdio`, `sse`, and `streamable-http`. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters # Needed for Stdio example + +# Define parameters for multiple MCP servers +server_params_list = [ + # Streamable HTTP Server + { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" + }, + # SSE Server + { + "url": "http://localhost:8000/sse", + "transport": "sse" + }, + # StdIO Server + StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, + ) +] + +try: + with MCPServerAdapter(server_params_list) as aggregated_tools: + print(f"Available aggregated tools: {[tool.name for tool in aggregated_tools]}") + + multi_server_agent = Agent( + role="Versatile Assistant", + goal="Utilize tools from local Stdio, remote SSE, and remote HTTP MCP servers.", + backstory="An AI agent capable of leveraging a diverse set of tools from multiple sources.", + tools=aggregated_tools, # All tools are available here + verbose=True, + ) + + ... # Your other agent, tasks, and crew code here + +except Exception as e: + print(f"Error connecting to or using multiple MCP servers (Managed): {e}") + print("Ensure all MCP servers are running and accessible with correct configurations.") + +``` + +## Connection Management + +When using the context manager (`with` statement), `MCPServerAdapter` handles the lifecycle (start and stop) of all connections to the configured MCP servers. This simplifies resource management and ensures that all connections are properly closed when the context is exited. diff --git a/docs/v1.15.13/en/mcp/overview.mdx b/docs/v1.15.13/en/mcp/overview.mdx new file mode 100644 index 0000000000..5b0bfc3f29 --- /dev/null +++ b/docs/v1.15.13/en/mcp/overview.mdx @@ -0,0 +1,724 @@ +--- +title: "MCP Servers as Tools in CrewAI" +description: "Learn how to integrate MCP servers as tools in your CrewAI agents using the `crewai-tools` library." +icon: plug +mode: "wide" +--- + +## Overview + +The [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) provides a standardized way for AI agents to provide context to LLMs by communicating with external services, known as MCP Servers. + +CrewAI offers **two approaches** for MCP integration: + +### 🚀 **Simple DSL Integration** (Recommended) + +Use the `mcps` field directly on agents for seamless MCP tool integration. The DSL supports both **string references** (for quick setup) and **structured configurations** (for full control). + +#### String-Based References (Quick Setup) + +Perfect for remote HTTPS servers and connected MCP integrations from the CrewAI catalog: + +```python +from crewai import Agent + +agent = Agent( + role="Research Analyst", + goal="Research and analyze information", + backstory="Expert researcher with access to external tools", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=your_key", # External MCP server + "https://api.weather.com/mcp#get_forecast", # Specific tool from server + "snowflake", # Connected MCP from catalog + "stripe#list_invoices" # Specific tool from connected MCP + ] +) +# MCP tools are now automatically available to your agent! +``` + +#### Structured Configurations (Full Control) + +For complete control over connection settings, tool filtering, and all transport types: + +```python +from crewai import Agent +from crewai.mcp import MCPServerStdio, MCPServerHTTP, MCPServerSSE +from crewai.mcp.filters import create_static_tool_filter + +agent = Agent( + role="Advanced Research Analyst", + goal="Research with full control over MCP connections", + backstory="Expert researcher with advanced tool access", + mcps=[ + # Stdio transport for local servers + MCPServerStdio( + command="npx", + args=["-y", "@modelcontextprotocol/server-filesystem"], + env={"API_KEY": "your_key"}, + tool_filter=create_static_tool_filter( + allowed_tool_names=["read_file", "list_directory"] + ), + cache_tools_list=True, + ), + # HTTP/Streamable HTTP transport for remote servers + MCPServerHTTP( + url="https://api.example.com/mcp", + headers={"Authorization": "Bearer your_token"}, + streamable=True, + cache_tools_list=True, + ), + # SSE transport for real-time streaming + MCPServerSSE( + url="https://stream.example.com/mcp/sse", + headers={"Authorization": "Bearer your_token"}, + ), + ] +) +``` + +### 🔧 **Advanced: MCPServerAdapter** (For Complex Scenarios) + +For advanced use cases requiring manual connection management, the `crewai-tools` library provides the `MCPServerAdapter` class. + +We currently support the following transport mechanisms: + +- **Stdio**: for local servers (communication via standard input/output between processes on the same machine) +- **Server-Sent Events (SSE)**: for remote servers (unidirectional, real-time data streaming from server to client over HTTP) +- **Streamable HTTPS**: for remote servers (flexible, potentially bi-directional communication over HTTPS, often utilizing SSE for server-to-client streams) + +## Video Tutorial + +Watch this video tutorial for a comprehensive guide on MCP integration with CrewAI: + + + +## Installation + +CrewAI MCP integration requires the `mcp` library: + +```shell +# For Simple DSL Integration (Recommended) +uv add mcp + +# For Advanced MCPServerAdapter usage +uv pip install 'crewai-tools[mcp]' +``` + +## Quick Start: Simple DSL Integration + +The easiest way to integrate MCP servers is using the `mcps` field on your agents. You can use either string references or structured configurations. + +### Quick Start with String References + +```python +from crewai import Agent, Task, Crew + +# Create agent with MCP tools using string references +research_agent = Agent( + role="Research Analyst", + goal="Find and analyze information using advanced search tools", + backstory="Expert researcher with access to multiple data sources", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile", + "snowflake#run_query" + ] +) + +# Create task +research_task = Task( + description="Research the latest developments in AI agent frameworks", + expected_output="Comprehensive research report with citations", + agent=research_agent +) + +# Create and run crew +crew = Crew(agents=[research_agent], tasks=[research_task]) +result = crew.kickoff() +``` + +### Quick Start with Structured Configurations + +```python +from crewai import Agent, Task, Crew +from crewai.mcp import MCPServerStdio, MCPServerHTTP, MCPServerSSE + +# Create agent with structured MCP configurations +research_agent = Agent( + role="Research Analyst", + goal="Find and analyze information using advanced search tools", + backstory="Expert researcher with access to multiple data sources", + mcps=[ + # Local stdio server + MCPServerStdio( + command="python", + args=["local_server.py"], + env={"API_KEY": "your_key"}, + ), + # Remote HTTP server + MCPServerHTTP( + url="https://api.research.com/mcp", + headers={"Authorization": "Bearer your_token"}, + ), + ] +) + +# Create task +research_task = Task( + description="Research the latest developments in AI agent frameworks", + expected_output="Comprehensive research report with citations", + agent=research_agent +) + +# Create and run crew +crew = Crew(agents=[research_agent], tasks=[research_task]) +result = crew.kickoff() +``` + +That's it! The MCP tools are automatically discovered and available to your agent. + +## MCP Reference Formats + +The `mcps` field supports both **string references** (for quick setup) and **structured configurations** (for full control). You can mix both formats in the same list. + +### String-Based References + +#### External MCP Servers + +```python +mcps=[ + # Full server - get all available tools + "https://mcp.example.com/api", + + # Specific tool from server using # syntax + "https://api.weather.com/mcp#get_current_weather", + + # Server with authentication parameters + "https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile" +] +``` + +#### Connected MCP Integrations + +Connect MCP servers from the CrewAI catalog or bring your own. Once connected in your account, reference them by slug: + +```python +mcps=[ + # Connected MCP - get all available tools + "snowflake", + + # Specific tool from a connected MCP using # syntax + "stripe#list_invoices", + + # Multiple connected MCPs + "snowflake", + "stripe", + "github" +] +``` + +### Structured Configurations + +#### Stdio Transport (Local Servers) + +Perfect for local MCP servers that run as processes: + +```python +from crewai.mcp import MCPServerStdio +from crewai.mcp.filters import create_static_tool_filter + +mcps=[ + MCPServerStdio( + command="npx", + args=["-y", "@modelcontextprotocol/server-filesystem"], + env={"API_KEY": "your_key"}, + tool_filter=create_static_tool_filter( + allowed_tool_names=["read_file", "write_file"] + ), + cache_tools_list=True, + ), + # Python-based server + MCPServerStdio( + command="python", + args=["path/to/server.py"], + env={"UV_PYTHON": "3.12", "API_KEY": "your_key"}, + ), +] +``` + +#### HTTP/Streamable HTTP Transport (Remote Servers) + +For remote MCP servers over HTTP/HTTPS: + +```python +from crewai.mcp import MCPServerHTTP + +mcps=[ + # Streamable HTTP (default) + MCPServerHTTP( + url="https://api.example.com/mcp", + headers={"Authorization": "Bearer your_token"}, + streamable=True, + cache_tools_list=True, + ), + # Standard HTTP + MCPServerHTTP( + url="https://api.example.com/mcp", + headers={"Authorization": "Bearer your_token"}, + streamable=False, + ), +] +``` + +#### SSE Transport (Real-Time Streaming) + +For remote servers using Server-Sent Events: + +```python +from crewai.mcp import MCPServerSSE + +mcps=[ + MCPServerSSE( + url="https://stream.example.com/mcp/sse", + headers={"Authorization": "Bearer your_token"}, + cache_tools_list=True, + ), +] +``` + +### Mixed References + +You can combine string references and structured configurations: + +```python +from crewai.mcp import MCPServerStdio, MCPServerHTTP + +mcps=[ + # String references + "https://external-api.com/mcp", # External server + "snowflake", # Connected MCP from catalog + + # Structured configurations + MCPServerStdio( + command="npx", + args=["-y", "@modelcontextprotocol/server-filesystem"], + ), + MCPServerHTTP( + url="https://api.example.com/mcp", + headers={"Authorization": "Bearer token"}, + ), +] +``` + +### Tool Filtering + +Structured configurations support advanced tool filtering: + +```python +from crewai.mcp import MCPServerStdio +from crewai.mcp.filters import create_static_tool_filter, create_dynamic_tool_filter, ToolFilterContext + +# Static filtering (allow/block lists) +static_filter = create_static_tool_filter( + allowed_tool_names=["read_file", "write_file"], + blocked_tool_names=["delete_file"], +) + +# Dynamic filtering (context-aware) +def dynamic_filter(context: ToolFilterContext, tool: dict) -> bool: + # Block dangerous tools for certain agent roles + if context.agent.role == "Code Reviewer": + if "delete" in tool.get("name", "").lower(): + return False + return True + +mcps=[ + MCPServerStdio( + command="npx", + args=["-y", "@modelcontextprotocol/server-filesystem"], + tool_filter=static_filter, # or dynamic_filter + ), +] +``` + +## Configuration Parameters + +Each transport type supports specific configuration options: + +### MCPServerStdio Parameters + +- **`command`** (required): Command to execute (e.g., `"python"`, `"node"`, `"npx"`, `"uvx"`) +- **`args`** (optional): List of command arguments (e.g., `["server.py"]` or `["-y", "@mcp/server"]`) +- **`env`** (optional): Dictionary of environment variables to pass to the process +- **`tool_filter`** (optional): Tool filter function for filtering available tools +- **`cache_tools_list`** (optional): Whether to cache the tool list for faster subsequent access (default: `False`) + +### MCPServerHTTP Parameters + +- **`url`** (required): Server URL (e.g., `"https://api.example.com/mcp"`) +- **`headers`** (optional): Dictionary of HTTP headers for authentication or other purposes +- **`streamable`** (optional): Whether to use streamable HTTP transport (default: `True`) +- **`tool_filter`** (optional): Tool filter function for filtering available tools +- **`cache_tools_list`** (optional): Whether to cache the tool list for faster subsequent access (default: `False`) + +### MCPServerSSE Parameters + +- **`url`** (required): Server URL (e.g., `"https://api.example.com/mcp/sse"`) +- **`headers`** (optional): Dictionary of HTTP headers for authentication or other purposes +- **`tool_filter`** (optional): Tool filter function for filtering available tools +- **`cache_tools_list`** (optional): Whether to cache the tool list for faster subsequent access (default: `False`) + +### Common Parameters + +All transport types support: + +- **`tool_filter`**: Filter function to control which tools are available. Can be: + - `None` (default): All tools are available + - Static filter: Created with `create_static_tool_filter()` for allow/block lists + - Dynamic filter: Created with `create_dynamic_tool_filter()` for context-aware filtering +- **`cache_tools_list`**: When `True`, caches the tool list after first discovery to improve performance on subsequent connections + +## Key Features + +- 🔄 **Automatic Tool Discovery**: Tools are automatically discovered and integrated +- 🏷️ **Name Collision Prevention**: Server names are prefixed to tool names +- ⚡ **Performance Optimized**: On-demand connections with schema caching +- 🛡️ **Error Resilience**: Graceful handling of unavailable servers +- ⏱️ **Timeout Protection**: Built-in timeouts prevent hanging connections +- 📊 **Transparent Integration**: Works seamlessly with existing CrewAI features +- 🔧 **Full Transport Support**: Stdio, HTTP/Streamable HTTP, and SSE transports +- 🎯 **Advanced Filtering**: Static and dynamic tool filtering capabilities +- 🔐 **Flexible Authentication**: Support for headers, environment variables, and query parameters + +## Error Handling + +The MCP DSL integration is designed to be resilient and handles failures gracefully: + +```python +from crewai import Agent +from crewai.mcp import MCPServerStdio, MCPServerHTTP + +agent = Agent( + role="Resilient Agent", + goal="Continue working despite server issues", + backstory="Agent that handles failures gracefully", + mcps=[ + # String references + "https://reliable-server.com/mcp", # Will work + "https://unreachable-server.com/mcp", # Will be skipped gracefully + "snowflake", # Connected MCP from catalog + + # Structured configs + MCPServerStdio( + command="python", + args=["reliable_server.py"], # Will work + ), + MCPServerHTTP( + url="https://slow-server.com/mcp", # Will timeout gracefully + ), + ] +) +# Agent will use tools from working servers and log warnings for failing ones +``` + +All connection errors are handled gracefully: + +- **Connection failures**: Logged as warnings, agent continues with available tools +- **Timeout errors**: Connections timeout after 30 seconds (configurable) +- **Authentication errors**: Logged clearly for debugging +- **Invalid configurations**: Validation errors are raised at agent creation time + +## Advanced: MCPServerAdapter + +For complex scenarios requiring manual connection management, use the `MCPServerAdapter` class from `crewai-tools`. Using a Python context manager (`with` statement) is the recommended approach as it automatically handles starting and stopping the connection to the MCP server. + +## Connection Configuration + +The `MCPServerAdapter` supports several configuration options to customize the connection behavior: + +- **`connect_timeout`** (optional): Maximum time in seconds to wait for establishing a connection to the MCP server. Defaults to 30 seconds if not specified. This is particularly useful for remote servers that may have variable response times. + +```python +# Example with custom connection timeout +with MCPServerAdapter(server_params, connect_timeout=60) as tools: + # Connection will timeout after 60 seconds if not established + pass +``` + +```python +from crewai import Agent +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters # For Stdio Server + +# Example server_params (choose one based on your server type): +# 1. Stdio Server: +server_params=StdioServerParameters( + command="python3", + args=["servers/your_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +# 2. SSE Server: +server_params = { + "url": "http://localhost:8000/sse", + "transport": "sse" +} + +# 3. Streamable HTTP Server: +server_params = { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" +} + +# Example usage (uncomment and adapt once server_params is set): +with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="Utilize tools from an MCP server.", + backstory="I can connect to MCP servers and use their tools.", + tools=mcp_tools, # Pass the loaded tools to your agent + reasoning=True, + verbose=True + ) + # ... rest of your crew setup ... +``` + +This general pattern shows how to integrate tools. For specific examples tailored to each transport, refer to the detailed guides below. + +## Filtering Tools + +There are two ways to filter tools: + +1. Accessing a specific tool using dictionary-style indexing. +2. Pass a list of tool names to the `MCPServerAdapter` constructor. + +### Accessing a specific tool using dictionary-style indexing. + +```python +with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="Utilize tools from an MCP server.", + backstory="I can connect to MCP servers and use their tools.", + tools=[mcp_tools["tool_name"]], # Pass the loaded tools to your agent + reasoning=True, + verbose=True + ) + # ... rest of your crew setup ... +``` + +### Pass a list of tool names to the `MCPServerAdapter` constructor. + +```python +with MCPServerAdapter(server_params, "tool_name", connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="Utilize tools from an MCP server.", + backstory="I can connect to MCP servers and use their tools.", + tools=mcp_tools, # Pass the loaded tools to your agent + reasoning=True, + verbose=True + ) + # ... rest of your crew setup ... +``` + +## Using with CrewBase + +To use MCPServer tools within a CrewBase class, use the `get_mcp_tools` method. Server configurations should be provided via the `mcp_server_params` attribute. You can pass either a single configuration or a list of multiple server configurations. + +```python +@CrewBase +class CrewWithMCP: + # ... define your agents and tasks config file ... + + mcp_server_params = [ + # Streamable HTTP Server + { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" + }, + # SSE Server + { + "url": "http://localhost:8000/sse", + "transport": "sse" + }, + # StdIO Server + StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, + ) + ] + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) # get all available tools + + # ... rest of your crew setup ... +``` + + +When a crew class is decorated with `@CrewBase`, the adapter lifecycle is managed for you: + +- The first call to `get_mcp_tools()` lazily creates a shared `MCPServerAdapter` that is reused by every agent in the crew. +- The adapter automatically shuts down after `.kickoff()` completes thanks to an implicit after-kickoff hook injected by `@CrewBase`, so no manual cleanup is required. +- If `mcp_server_params` is not defined, `get_mcp_tools()` simply returns an empty list, allowing the same code paths to run with or without MCP configured. + +This makes it safe to call `get_mcp_tools()` from multiple agent methods or selectively enable MCP per environment. + + + +### Connection Timeout Configuration + +You can configure the connection timeout for MCP servers by setting the `mcp_connect_timeout` class attribute. If no timeout is specified, it defaults to 30 seconds. + +```python +@CrewBase +class CrewWithMCP: + mcp_server_params = [...] + mcp_connect_timeout = 60 # 60 seconds timeout for all MCP connections + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) +``` + +```python +@CrewBase +class CrewWithDefaultTimeout: + mcp_server_params = [...] + # No mcp_connect_timeout specified - uses default 30 seconds + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) +``` + +### Filtering Tools + +You can filter which tools are available to your agent by passing a list of tool names to the `get_mcp_tools` method. + +```python +@agent +def another_agent(self): + return Agent( + config=self.agents_config["your_agent"], + tools=self.get_mcp_tools("tool_1", "tool_2") # get specific tools + ) +``` + +The timeout configuration applies to all MCP tool calls within the crew: + +```python +@CrewBase +class CrewWithCustomTimeout: + mcp_server_params = [...] + mcp_connect_timeout = 90 # 90 seconds timeout for all MCP connections + + @agent + def filtered_agent(self): + return Agent( + config=self.agents_config["your_agent"], + tools=self.get_mcp_tools("tool_1", "tool_2") # specific tools with custom timeout + ) +``` + +## Explore MCP Integrations + + + + **Recommended**: Use the simple `mcps=[]` field syntax for effortless MCP + integration. + + + Connect to local MCP servers via standard input/output. Ideal for scripts + and local executables. + + + Integrate with remote MCP servers using Server-Sent Events for real-time + data streaming. + + + Utilize flexible Streamable HTTP for robust communication with remote MCP + servers. + + + Aggregate tools from several MCP servers simultaneously using a single + adapter. + + + Review important security best practices for MCP integration to keep your + agents safe. + + + +Checkout this repository for full demos and examples of MCP integration with CrewAI! 👇 + + + CrewAI MCP Demo + + +## Staying Safe with MCP + +Always ensure that you trust an MCP Server before using it. + +#### Security Warning: DNS Rebinding Attacks + +SSE transports can be vulnerable to DNS rebinding attacks if not properly secured. +To prevent this: + +1. **Always validate Origin headers** on incoming SSE connections to ensure they come from expected sources +2. **Avoid binding servers to all network interfaces** (0.0.0.0) when running locally - bind only to localhost (127.0.0.1) instead +3. **Implement proper authentication** for all SSE connections + +Without these protections, attackers could use DNS rebinding to interact with local MCP servers from remote websites. + +For more details, see the [Anthropic's MCP Transport Security docs](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations). + +### Limitations + +- **Supported Primitives**: Currently, `MCPServerAdapter` primarily supports adapting MCP `tools`. + Other MCP primitives like `prompts` or `resources` are not directly integrated as CrewAI components through this adapter at this time. +- **Output Handling**: The adapter typically processes the primary text output from an MCP tool (e.g., `.content[0].text`). Complex or multi-modal outputs might require custom handling if not fitting this pattern. diff --git a/docs/v1.15.13/en/mcp/security.mdx b/docs/v1.15.13/en/mcp/security.mdx new file mode 100644 index 0000000000..4fc84cdebf --- /dev/null +++ b/docs/v1.15.13/en/mcp/security.mdx @@ -0,0 +1,167 @@ +--- +title: MCP Security Considerations +description: Learn about important security best practices when integrating MCP servers with your CrewAI agents. +icon: lock +mode: "wide" +--- + +## Overview + + +The most critical aspect of MCP security is **trust**. You should **only** connect your CrewAI agents to MCP servers that you fully trust. + + +When integrating external services like MCP (Model Context Protocol) servers into your CrewAI agents, security is paramount. +MCP servers can execute code, access data, or interact with other systems based on the tools they expose. +It's crucial to understand the implications and follow best practices to protect your applications and data. + +### Risks + +- Execute arbitrary code on the machine where the agent is running (especially with `Stdio` transport if the server can control the command executed). +- Expose sensitive data from your agent or its environment. +- Manipulate your agent's behavior in unintended ways, including making unauthorized API calls on your behalf. +- Hijack your agent's reasoning process through sophisticated prompt injection techniques (see below). + +### 1. Trusting MCP Servers + + +**Only connect to MCP servers that you trust.** + + +Before configuring `MCPServerAdapter` to connect to an MCP server, ensure you know: +- **Who operates the server?** Is it a known, reputable service, or an internal server under your control? +- **What tools does it expose?** Understand the capabilities of the tools. Could they be misused if an attacker gained control or if the server itself is malicious? +- **What data does it access or process?** Be aware of any sensitive information that might be sent to or handled by the MCP server. + +Avoid connecting to unknown or unverified MCP servers, especially if your agents handle sensitive tasks or data. + +### 2. Secure Prompt Injection via Tool Metadata: The "Model Control Protocol" Risk + +A significant and subtle risk is the potential for prompt injection through tool metadata. Here's how it works: + +1. When your CrewAI agent connects to an MCP server, it typically requests a list of available tools. +2. The MCP server responds with metadata for each tool, including its name, description, and parameter descriptions. +3. Your agent's underlying Language Model (LLM) uses this metadata to understand how and when to use the tools. This metadata is often incorporated into the LLM's system prompt or context. +4. A malicious MCP server can craft its tool metadata (names, descriptions) to include hidden or overt instructions. These instructions can act as a prompt injection, effectively telling your LLM to behave in a certain way, reveal sensitive information, or perform malicious actions. + +**Crucially, this attack can occur simply by connecting to a malicious server and listing its tools, even if your agent never explicitly decides to *use* any of those tools.** The mere exposure to the malicious metadata can be enough to compromise the agent's behavior. + +**Mitigation:** + +* **Extreme Caution with Untrusted Servers:** Reiterate: *Do not connect to MCP servers you do not fully trust.* The risk of metadata injection makes this paramount. + +### Stdio Transport Security + +Stdio (Standard Input/Output) transport is typically used for local MCP servers running on the same machine as your CrewAI application. + +- **Process Isolation**: While generally safer as it doesn't involve network exposure by default, ensure the script or command run by `StdioServerParameters` is from a trusted source and has appropriate file system permissions. A malicious Stdio server script could still harm your local system. +- **Input Sanitization**: If your Stdio server script takes complex inputs derived from agent interactions, ensure the script itself sanitizes these inputs to prevent command injection or other vulnerabilities within the script's logic. +- **Resource Limits**: Be mindful that a local Stdio server process consumes local resources (CPU, memory). Ensure it's well-behaved and won't exhaust system resources. + +### Confused Deputy Attacks + +The [Confused Deputy Problem](https://en.wikipedia.org/wiki/Confused_deputy_problem) is a classic security vulnerability that can manifest in MCP integrations, especially when an MCP server acts as a proxy to other third-party services (e.g., Google Calendar, GitHub) that use OAuth 2.0 for authorization. + +**Scenario:** + +1. An MCP server (let's call it `MCP-Proxy`) allows your agent to interact with `ThirdPartyAPI`. +2. `MCP-Proxy` uses its own single, static `client_id` when talking to `ThirdPartyAPI`'s authorization server. +3. You, as the user, legitimately authorize `MCP-Proxy` to access `ThirdPartyAPI` on your behalf. During this, `ThirdPartyAPI`'s auth server might set a cookie in your browser indicating your consent for `MCP-Proxy`'s `client_id`. +4. An attacker crafts a malicious link. This link initiates an OAuth flow with `MCP-Proxy`, but is designed to trick `ThirdPartyAPI`'s auth server. +5. If you click this link, and `ThirdPartyAPI`'s auth server sees your existing consent cookie for `MCP-Proxy`'s `client_id`, it might *skip* asking for your consent again. +6. `MCP-Proxy` might then be tricked into forwarding an authorization code (for `ThirdPartyAPI`) to the attacker, or an MCP authorization code that the attacker can use to impersonate you to `MCP-Proxy`. + +**Mitigation (Primarily for MCP Server Developers):** + +* MCP proxy servers using static client IDs for downstream services **must** obtain explicit user consent for *each client application or agent* connecting to them *before* initiating an OAuth flow with the third-party service. This means `MCP-Proxy` itself should show a consent screen. + +**CrewAI User Implication:** + +* Be cautious if an MCP server redirects you for multiple OAuth authentications, especially if it seems unexpected or if the permissions requested are overly broad. +* Prefer MCP servers that clearly delineate their own identity versus the third-party services they might proxy. + +### Remote Transport Security (SSE & Streamable HTTP) + +When connecting to remote MCP servers via Server-Sent Events (SSE) or Streamable HTTP, standard web security practices are essential. + +### SSE Security Considerations + +### a. DNS Rebinding Attacks (Especially for SSE) + + +**Protect against DNS Rebinding Attacks.** + + +DNS rebinding allows an attacker-controlled website to bypass the same-origin policy and make requests to servers on the user's local network (e.g., `localhost`) or intranet. This is particularly risky if you run an MCP server locally (e.g., for development) and an agent in a browser-like environment (though less common for typical CrewAI backend setups) or if the MCP server is on an internal network. + +**Mitigation Strategies for MCP Server Implementers:** +- **Validate `Origin` and `Host` Headers**: MCP servers (especially SSE ones) should validate the `Origin` and/or `Host` HTTP headers to ensure requests are coming from expected domains/clients. +- **Bind to `localhost` (127.0.0.1)**: When running MCP servers locally for development, bind them to `127.0.0.1` instead of `0.0.0.0`. This prevents them from being accessible from other machines on the network. +- **Authentication**: Require authentication for all connections to your MCP server if it's not intended for public anonymous access. + +### b. Use HTTPS + +- **Encrypt Data in Transit**: Always use HTTPS (HTTP Secure) for the URLs of remote MCP servers. This encrypts the communication between your CrewAI application and the MCP server, protecting against eavesdropping and man-in-the-middle attacks. `MCPServerAdapter` will respect the scheme (`http` or `https`) provided in the URL. + +### c. Token Passthrough (Anti-Pattern) + +This is primarily a concern for MCP server developers but understanding it helps in choosing secure servers. + +"Token passthrough" is when an MCP server accepts an access token from your CrewAI agent (which might be a token for a *different* service, say `ServiceA`) and simply passes it through to another downstream API (`ServiceB`) without proper validation. Specifically, `ServiceB` (or the MCP server itself) should only accept tokens that were explicitly issued *for them* (i.e., the 'audience' claim in the token matches the server/service). + +**Risks:** + +* Bypasses security controls (like rate limiting or fine-grained permissions) on the MCP server or the downstream API. +* Breaks audit trails and accountability. +* Allows misuse of stolen tokens. + +**Mitigation (For MCP Server Developers):** + +* MCP servers **MUST NOT** accept tokens that were not explicitly issued for them. They must validate the token's audience claim. + +**CrewAI User Implication:** + +* While not directly controllable by the user, this highlights the importance of connecting to well-designed MCP servers that adhere to security best practices. + +#### Authentication and Authorization + +- **Verify Identity**: If the MCP server provides sensitive tools or access to private data, it MUST implement strong authentication mechanisms to verify the identity of the client (your CrewAI application). This could involve API keys, OAuth tokens, or other standard methods. +- **Principle of Least Privilege**: Ensure the credentials used by `MCPServerAdapter` (if any) have only the necessary permissions to access the required tools. + +### d. Input Validation and Sanitization + +- **Input Validation is Critical**: MCP servers **must** rigorously validate all inputs received from agents *before* processing them or passing them to tools. This is a primary defense against many common vulnerabilities: + - **Command Injection:** If a tool constructs shell commands, SQL queries, or other interpreted language statements based on input, the server must meticulously sanitize this input to prevent malicious commands from being injected and executed. + - **Path Traversal:** If a tool accesses files based on input parameters, the server must validate and sanitize these paths to prevent access to unauthorized files or directories (e.g., by blocking `../` sequences). + - **Data Type & Range Checks:** Servers must ensure that input data conforms to the expected data types (e.g., string, number, boolean) and falls within acceptable ranges or adheres to defined formats (e.g., regex for URLs). + - **JSON Schema Validation:** All tool parameters should be strictly validated against their defined JSON schema. This helps catch malformed requests early. +- **Client-Side Awareness**: While server-side validation is paramount, as a CrewAI user, be mindful of the data your agents are constructed to send to MCP tools, especially if interacting with less-trusted or new MCP servers. + +### e. Rate Limiting and Resource Management + +- **Prevent Abuse**: MCP servers should implement rate limiting to prevent abuse, whether intentional (Denial of Service attacks) or unintentional (e.g., a misconfigured agent making too many requests). +- **Client-Side Retries**: Implement sensible retry logic in your CrewAI tasks if transient network issues or server rate limits are expected, but avoid aggressive retries that could exacerbate server load. + +## 4. Secure MCP Server Implementation Advice (For Developers) + +If you are developing an MCP server that CrewAI agents might connect to, consider these best practices in addition to the points above: + +- **Follow Secure Coding Practices**: Adhere to standard secure coding principles for your chosen language and framework (e.g., OWASP Top 10). +- **Principle of Least Privilege**: Ensure the process running the MCP server (especially for `Stdio`) has only the minimum necessary permissions. Tools themselves should also operate with the least privilege required to perform their function. +- **Dependency Management**: Keep all server-side dependencies, including operating system packages, language runtimes, and third-party libraries, up-to-date to patch known vulnerabilities. Use tools to scan for vulnerable dependencies. +- **Secure Defaults**: Design your server and its tools to be secure by default. For example, features that could be risky should be off by default or require explicit opt-in with clear warnings. +- **Access Control for Tools**: Implement robust mechanisms to control which authenticated and authorized agents or users can access specific tools, especially those that are powerful, sensitive, or incur costs. +- **Secure Error Handling**: Servers should not expose detailed internal error messages, stack traces, or debugging information to the client, as these can reveal internal workings or potential vulnerabilities. Log errors comprehensively on the server-side for diagnostics. +- **Comprehensive Logging and Monitoring**: Implement detailed logging of security-relevant events (e.g., authentication attempts, tool invocations, errors, authorization changes). Monitor these logs for suspicious activity or abuse patterns. +- **Adherence to MCP Authorization Spec**: If implementing authentication and authorization, strictly follow the [MCP Authorization specification](https://modelcontextprotocol.io/specification/draft/basic/authorization) and relevant [OAuth 2.0 security best practices](https://datatracker.ietf.org/doc/html/rfc9700). +- **Regular Security Audits**: If your MCP server handles sensitive data, performs critical operations, or is publicly exposed, consider periodic security audits by qualified professionals. + +## 5. Further Reading + +For more detailed information on MCP security, refer to the official documentation: +- **[MCP Transport Security](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations)** + +By understanding these security considerations and implementing best practices, you can safely leverage the power of MCP servers in your CrewAI projects. +These are by no means exhaustive, but they cover the most common and critical security concerns. +The threats will continue to evolve, so it's important to stay informed and adapt your security measures accordingly. + diff --git a/docs/v1.15.13/en/mcp/sse.mdx b/docs/v1.15.13/en/mcp/sse.mdx new file mode 100644 index 0000000000..6c21c9aca8 --- /dev/null +++ b/docs/v1.15.13/en/mcp/sse.mdx @@ -0,0 +1,151 @@ +--- +title: SSE Transport +description: Learn how to connect CrewAI to remote MCP servers using Server-Sent Events (SSE) for real-time communication. +icon: wifi +mode: "wide" +--- + +## Overview + +Server-Sent Events (SSE) provide a standard way for a web server to send updates to a client over a single, long-lived HTTP connection. In the context of MCP, SSE is used for remote servers to stream data (like tool responses) to your CrewAI application in real-time. + +## Key Concepts + +- **Remote Servers**: SSE is suitable for MCP servers hosted remotely. +- **Unidirectional Stream**: Typically, SSE is a one-way communication channel from server to client. +- **`MCPServerAdapter` Configuration**: For SSE, you'll provide the server's URL and specify the transport type. + +## Connecting via SSE + +You can connect to an SSE-based MCP server using two main approaches for managing the connection lifecycle: + +### 1. Fully Managed Connection (Recommended) + +Using a Python context manager (`with` statement) is the recommended approach. It automatically handles establishing and closing the connection to the SSE MCP server. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL + "transport": "sse" +} + +# Using MCPServerAdapter with a context manager +try: + with MCPServerAdapter(server_params) as tools: + print(f"Available tools from SSE MCP server: {[tool.name for tool in tools]}") + + # Example: Using a tool from the SSE MCP server + sse_agent = Agent( + role="Remote Service User", + goal="Utilize a tool provided by a remote SSE MCP server.", + backstory="An AI agent that connects to external services via SSE.", + tools=tools, + reasoning=True, + verbose=True, + ) + + sse_task = Task( + description="Fetch real-time stock updates for 'AAPL' using an SSE tool.", + expected_output="The latest stock price for AAPL.", + agent=sse_agent, + markdown=True + ) + + sse_crew = Crew( + agents=[sse_agent], + tasks=[sse_task], + verbose=True, + process=Process.sequential + ) + + if tools: # Only kickoff if tools were loaded + result = sse_crew.kickoff() # Add inputs={'stock_symbol': 'AAPL'} if tool requires it + print("\nCrew Task Result (SSE - Managed):\n", result) + else: + print("Skipping crew kickoff as tools were not loaded (check server connection).") + +except Exception as e: + print(f"Error connecting to or using SSE MCP server (Managed): {e}") + print("Ensure the SSE MCP server is running and accessible at the specified URL.") + +``` + + +Replace `"http://localhost:8000/sse"` with the actual URL of your SSE MCP server. + + +### 2. Manual Connection Lifecycle + +If you need finer-grained control, you can manage the `MCPServerAdapter` connection lifecycle manually. + + +You **MUST** call `mcp_server_adapter.stop()` to ensure the connection is closed and resources are released. Using a `try...finally` block is highly recommended. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL + "transport": "sse" +} + +mcp_server_adapter = None +try: + mcp_server_adapter = MCPServerAdapter(server_params) + mcp_server_adapter.start() + tools = mcp_server_adapter.tools + print(f"Available tools (manual SSE): {[tool.name for tool in tools]}") + + manual_sse_agent = Agent( + role="Remote Data Analyst", + goal="Analyze data fetched from a remote SSE MCP server using manual connection management.", + backstory="An AI skilled in handling SSE connections explicitly.", + tools=tools, + verbose=True + ) + + analysis_task = Task( + description="Fetch and analyze the latest user activity trends from the SSE server.", + expected_output="A summary report of user activity trends.", + agent=manual_sse_agent + ) + + analysis_crew = Crew( + agents=[manual_sse_agent], + tasks=[analysis_task], + verbose=True, + process=Process.sequential + ) + + result = analysis_crew.kickoff() + print("\nCrew Task Result (SSE - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual SSE MCP integration: {e}") + print("Ensure the SSE MCP server is running and accessible.") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: + print("Stopping SSE MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: + print("SSE MCP server adapter was not connected. No stop needed or start failed.") + +``` + +## Security Considerations for SSE + + +**DNS Rebinding Attacks**: SSE transports can be vulnerable to DNS rebinding attacks if the MCP server is not properly secured. This could allow malicious websites to interact with local or intranet-based MCP servers. + + +To mitigate this risk: +- MCP server implementations should **validate `Origin` headers** on incoming SSE connections. +- When running local SSE MCP servers for development, **bind only to `localhost` (`127.0.0.1`)** rather than all network interfaces (`0.0.0.0`). +- Implement **proper authentication** for all SSE connections if they expose sensitive tools or data. + +For a comprehensive overview of security best practices, please refer to our [Security Considerations](./security.mdx) page and the official [MCP Transport Security documentation](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations). diff --git a/docs/v1.15.13/en/mcp/stdio.mdx b/docs/v1.15.13/en/mcp/stdio.mdx new file mode 100644 index 0000000000..c7c065d0c8 --- /dev/null +++ b/docs/v1.15.13/en/mcp/stdio.mdx @@ -0,0 +1,135 @@ +--- +title: Stdio Transport +description: Learn how to connect CrewAI to local MCP servers using the Stdio (Standard Input/Output) transport mechanism. +icon: server +mode: "wide" +--- + +## Overview + +The Stdio (Standard Input/Output) transport is designed for connecting `MCPServerAdapter` to local MCP servers that communicate over their standard input and output streams. This is typically used when the MCP server is a script or executable running on the same machine as your CrewAI application. + +## Key Concepts + +- **Local Execution**: Stdio transport manages a locally running process for the MCP server. +- **`StdioServerParameters`**: This class from the `mcp` library is used to configure the command, arguments, and environment variables for launching the Stdio server. + +## Connecting via Stdio + +You can connect to an Stdio-based MCP server using two main approaches for managing the connection lifecycle: + +### 1. Fully Managed Connection (Recommended) + +Using a Python context manager (`with` statement) is the recommended approach. It automatically handles starting the MCP server process and stopping it when the context is exited. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters +import os + +# Create a StdioServerParameters object +server_params=StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +with MCPServerAdapter(server_params) as tools: + print(f"Available tools from Stdio MCP server: {[tool.name for tool in tools]}") + + # Example: Using the tools from the Stdio MCP server in a CrewAI Agent + research_agent = Agent( + role="Local Data Processor", + goal="Process data using a local Stdio-based tool.", + backstory="An AI that leverages local scripts via MCP for specialized tasks.", + tools=tools, + reasoning=True, + verbose=True, + ) + + processing_task = Task( + description="Process the input data file 'data.txt' and summarize its contents.", + expected_output="A summary of the processed data.", + agent=research_agent, + markdown=True + ) + + data_crew = Crew( + agents=[research_agent], + tasks=[processing_task], + verbose=True, + process=Process.sequential + ) + + result = data_crew.kickoff() + print("\nCrew Task Result (Stdio - Managed):\n", result) + +``` + +### 2. Manual Connection Lifecycle + +If you need finer-grained control over when the Stdio MCP server process is started and stopped, you can manage the `MCPServerAdapter` lifecycle manually. + + +You **MUST** call `mcp_server_adapter.stop()` to ensure the server process is terminated and resources are released. Using a `try...finally` block is highly recommended. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters +import os + +# Create a StdioServerParameters object +stdio_params=StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +mcp_server_adapter = MCPServerAdapter(server_params=stdio_params) +try: + mcp_server_adapter.start() # Manually start the connection and server process + tools = mcp_server_adapter.tools + print(f"Available tools (manual Stdio): {[tool.name for tool in tools]}") + + # Example: Using the tools with your Agent, Task, Crew setup + manual_agent = Agent( + role="Local Task Executor", + goal="Execute a specific local task using a manually managed Stdio tool.", + backstory="An AI proficient in controlling local processes via MCP.", + tools=tools, + verbose=True + ) + + manual_task = Task( + description="Execute the 'perform_analysis' command via the Stdio tool.", + expected_output="Results of the analysis.", + agent=manual_agent + ) + + manual_crew = Crew( + agents=[manual_agent], + tasks=[manual_task], + verbose=True, + process=Process.sequential + ) + + + result = manual_crew.kickoff() # Actual inputs depend on your tool + print("\nCrew Task Result (Stdio - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual Stdio MCP integration: {e}") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: # Check if connected before stopping + print("Stopping Stdio MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: # If adapter exists but not connected (e.g. start failed) + print("Stdio MCP server adapter was not connected. No stop needed or start failed.") + +``` + +Remember to replace placeholder paths and commands with your actual Stdio server details. The `env` parameter in `StdioServerParameters` can +be used to set environment variables for the server process, which can be useful for configuring its behavior or providing necessary paths (like `PYTHONPATH`). diff --git a/docs/v1.15.13/en/mcp/streamable-http.mdx b/docs/v1.15.13/en/mcp/streamable-http.mdx new file mode 100644 index 0000000000..4084aa2447 --- /dev/null +++ b/docs/v1.15.13/en/mcp/streamable-http.mdx @@ -0,0 +1,136 @@ +--- +title: Streamable HTTP Transport +description: Learn how to connect CrewAI to remote MCP servers using the flexible Streamable HTTP transport. +icon: globe +mode: "wide" +--- + +## Overview + +Streamable HTTP transport provides a flexible way to connect to remote MCP servers. It's often built upon HTTP and can support various communication patterns, including request-response and streaming, sometimes utilizing Server-Sent Events (SSE) for server-to-client streams within a broader HTTP interaction. + +## Key Concepts + +- **Remote Servers**: Designed for MCP servers hosted remotely. +- **Flexibility**: Can support more complex interaction patterns than plain SSE, potentially including bi-directional communication if the server implements it. +- **`MCPServerAdapter` Configuration**: You'll need to provide the server's base URL for MCP communication and specify `"streamable-http"` as the transport type. + +## Connecting via Streamable HTTP + +You have two primary methods for managing the connection lifecycle with a Streamable HTTP MCP server: + +### 1. Fully Managed Connection (Recommended) + +The recommended approach is to use a Python context manager (`with` statement), which handles the connection's setup and teardown automatically. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8001/mcp", # Replace with your actual Streamable HTTP server URL + "transport": "streamable-http" +} + +try: + with MCPServerAdapter(server_params) as tools: + print(f"Available tools from Streamable HTTP MCP server: {[tool.name for tool in tools]}") + + http_agent = Agent( + role="HTTP Service Integrator", + goal="Utilize tools from a remote MCP server via Streamable HTTP.", + backstory="An AI agent adept at interacting with complex web services.", + tools=tools, + verbose=True, + ) + + http_task = Task( + description="Perform a complex data query using a tool from the Streamable HTTP server.", + expected_output="The result of the complex data query.", + agent=http_agent, + ) + + http_crew = Crew( + agents=[http_agent], + tasks=[http_task], + verbose=True, + process=Process.sequential + ) + + result = http_crew.kickoff() + print("\nCrew Task Result (Streamable HTTP - Managed):\n", result) + +except Exception as e: + print(f"Error connecting to or using Streamable HTTP MCP server (Managed): {e}") + print("Ensure the Streamable HTTP MCP server is running and accessible at the specified URL.") + +``` +**Note:** Replace `"http://localhost:8001/mcp"` with the actual URL of your Streamable HTTP MCP server. + +### 2. Manual Connection Lifecycle + +For scenarios requiring more explicit control, you can manage the `MCPServerAdapter` connection manually. + + +It is **critical** to call `mcp_server_adapter.stop()` when you are done to close the connection and free up resources. A `try...finally` block is the safest way to ensure this. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8001/mcp", # Replace with your actual Streamable HTTP server URL + "transport": "streamable-http" +} + +mcp_server_adapter = None +try: + mcp_server_adapter = MCPServerAdapter(server_params) + mcp_server_adapter.start() + tools = mcp_server_adapter.tools + print(f"Available tools (manual Streamable HTTP): {[tool.name for tool in tools]}") + + manual_http_agent = Agent( + role="Advanced Web Service User", + goal="Interact with an MCP server using manually managed Streamable HTTP connections.", + backstory="An AI specialist in fine-tuning HTTP-based service integrations.", + tools=tools, + verbose=True + ) + + data_processing_task = Task( + description="Submit data for processing and retrieve results via Streamable HTTP.", + expected_output="Processed data or confirmation.", + agent=manual_http_agent + ) + + data_crew = Crew( + agents=[manual_http_agent], + tasks=[data_processing_task], + verbose=True, + process=Process.sequential + ) + + result = data_crew.kickoff() + print("\nCrew Task Result (Streamable HTTP - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual Streamable HTTP MCP integration: {e}") + print("Ensure the Streamable HTTP MCP server is running and accessible.") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: + print("Stopping Streamable HTTP MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: + print("Streamable HTTP MCP server adapter was not connected. No stop needed or start failed.") +``` + +## Security Considerations + +When using Streamable HTTP transport, general web security best practices are paramount: +- **Use HTTPS**: Always prefer HTTPS (HTTP Secure) for your MCP server URLs to encrypt data in transit. +- **Authentication**: Implement robust authentication mechanisms if your MCP server exposes sensitive tools or data. +- **Input Validation**: Ensure your MCP server validates all incoming requests and parameters. + +For a comprehensive guide on securing your MCP integrations, please refer to our [Security Considerations](./security.mdx) page and the official [MCP Transport Security documentation](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations). diff --git a/docs/v1.15.13/en/observability/arize-phoenix.mdx b/docs/v1.15.13/en/observability/arize-phoenix.mdx new file mode 100644 index 0000000000..6558d3a600 --- /dev/null +++ b/docs/v1.15.13/en/observability/arize-phoenix.mdx @@ -0,0 +1,152 @@ +--- +title: Arize Phoenix +description: Arize Phoenix integration for CrewAI with OpenTelemetry and OpenInference +icon: magnifying-glass-chart +mode: "wide" +--- + +# Arize Phoenix Integration + +This guide demonstrates how to integrate **Arize Phoenix** with **CrewAI** using OpenTelemetry via the [OpenInference](https://github.com/openinference/openinference) SDK. By the end of this guide, you will be able to trace your CrewAI agents and easily debug your agents. + +> **What is Arize Phoenix?** [Arize Phoenix](https://phoenix.arize.com) is an LLM observability platform that provides tracing and evaluation for AI applications. + +[![Watch a Video Demo of Our Integration with Phoenix](https://storage.googleapis.com/arize-assets/fixtures/setup_crewai.png)](https://www.youtube.com/watch?v=Yc5q3l6F7Ww) + +## Get Started + +We'll walk through a simple example of using CrewAI and integrating it with Arize Phoenix via OpenTelemetry using OpenInference. + +You can also access this guide on [Google Colab](https://colab.research.google.com/github/Arize-ai/phoenix/blob/main/tutorials/tracing/crewai_tracing_tutorial.ipynb). + +### Step 1: Install Dependencies + +```bash +pip install openinference-instrumentation-crewai crewai crewai-tools arize-phoenix-otel +``` + +### Step 2: Set Up Environment Variables + +Setup Phoenix Cloud API keys and configure OpenTelemetry to send traces to Phoenix. Phoenix Cloud is a hosted version of Arize Phoenix, but it is not required to use this integration. + +You can get your free Serper API key [here](https://serper.dev/). + +```python +import os +from getpass import getpass + +# Get your Phoenix Cloud credentials +PHOENIX_API_KEY = getpass("🔑 Enter your Phoenix Cloud API Key: ") + +# Get API keys for services +OPENAI_API_KEY = getpass("🔑 Enter your OpenAI API key: ") +SERPER_API_KEY = getpass("🔑 Enter your Serper API key: ") + +# Set environment variables +os.environ["PHOENIX_CLIENT_HEADERS"] = f"api_key={PHOENIX_API_KEY}" +os.environ["PHOENIX_COLLECTOR_ENDPOINT"] = "https://app.phoenix.arize.com" # Phoenix Cloud, change this to your own endpoint if you are using a self-hosted instance +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +os.environ["SERPER_API_KEY"] = SERPER_API_KEY +``` + +### Step 3: Initialize OpenTelemetry with Phoenix + +Initialize the OpenInference OpenTelemetry instrumentation SDK to start capturing traces and send them to Phoenix. + +```python +from phoenix.otel import register + +tracer_provider = register( + project_name="crewai-tracing-demo", + auto_instrument=True, +) +``` + +### Step 4: Create a CrewAI Application + +We'll create a CrewAI application where two agents collaborate to research and write a blog post about AI advancements. + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool +from openinference.instrumentation.crewai import CrewAIInstrumentor +from phoenix.otel import register + +# setup monitoring for your crew +tracer_provider = register( + endpoint="http://localhost:6006/v1/traces") +CrewAIInstrumentor().instrument(skip_dep_check=True, tracer_provider=tracer_provider) +search_tool = SerperDevTool() + +# Define your agents with roles and goals +researcher = Agent( + role="Senior Research Analyst", + goal="Uncover cutting-edge developments in AI and data science", + backstory="""You work at a leading tech think tank. + Your expertise lies in identifying emerging trends. + You have a knack for dissecting complex data and presenting actionable insights.""", + verbose=True, + allow_delegation=False, + # You can pass an optional llm attribute specifying what model you wanna use. + # llm=ChatOpenAI(model_name="gpt-3.5", temperature=0.7), + tools=[search_tool], +) +writer = Agent( + role="Tech Content Strategist", + goal="Craft compelling content on tech advancements", + backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles. + You transform complex concepts into compelling narratives.""", + verbose=True, + allow_delegation=True, +) + +# Create tasks for your agents +task1 = Task( + description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024. + Identify key trends, breakthrough technologies, and potential industry impacts.""", + expected_output="Full analysis report in bullet points", + agent=researcher, +) + +task2 = Task( + description="""Using the insights provided, develop an engaging blog + post that highlights the most significant AI advancements. + Your post should be informative yet accessible, catering to a tech-savvy audience. + Make it sound cool, avoid complex words so it doesn't sound like AI.""", + expected_output="Full blog post of at least 4 paragraphs", + agent=writer, +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[researcher, writer], tasks=[task1, task2], verbose=1, process=Process.sequential +) + +# Get your crew to work! +result = crew.kickoff() + +print("######################") +print(result) +``` + +### Step 5: View Traces in Phoenix + +After running the agent, you can view the traces generated by your CrewAI application in Phoenix. You should see detailed steps of the agent interactions and LLM calls, which can help you debug and optimize your AI agents. + +Log into your Phoenix Cloud account and navigate to the project you specified in the `project_name` parameter. You'll see a timeline view of your trace with all the agent interactions, tool usages, and LLM calls. + +![Example trace in Phoenix showing agent interactions](https://storage.googleapis.com/arize-assets/fixtures/crewai_traces.png) + + +### Version Compatibility Information +- Python 3.8+ +- CrewAI >= 0.86.0 +- Arize Phoenix >= 7.0.1 +- OpenTelemetry SDK >= 1.31.0 + + +### References +- [Phoenix Documentation](https://docs.arize.com/phoenix/) - Overview of the Phoenix platform. +- [CrewAI Documentation](https://docs.crewai.com/) - Overview of the CrewAI framework. +- [OpenTelemetry Docs](https://opentelemetry.io/docs/) - OpenTelemetry guide +- [OpenInference GitHub](https://github.com/openinference/openinference) - Source code for OpenInference SDK. diff --git a/docs/v1.15.13/en/observability/braintrust.mdx b/docs/v1.15.13/en/observability/braintrust.mdx new file mode 100644 index 0000000000..21ab52c852 --- /dev/null +++ b/docs/v1.15.13/en/observability/braintrust.mdx @@ -0,0 +1,237 @@ +--- +title: Braintrust +description: Braintrust integration for CrewAI with OpenTelemetry tracing and evaluation +icon: magnifying-glass-chart +mode: "wide" +--- + +# Braintrust Integration + +This guide demonstrates how to integrate **Braintrust** with **CrewAI** using OpenTelemetry for comprehensive tracing and evaluation. By the end of this guide, you will be able to trace your CrewAI agents, monitor their performance, and evaluate their outputs using Braintrust's powerful observability platform. + +> **What is Braintrust?** [Braintrust](https://www.braintrust.dev) is an AI evaluation and observability platform that provides comprehensive tracing, evaluation, and monitoring for AI applications with built-in experiment tracking and performance analytics. + +## Get Started + +We'll walk through a simple example of using CrewAI and integrating it with Braintrust via OpenTelemetry for comprehensive observability and evaluation. + +### Step 1: Install Dependencies + +```bash +uv add braintrust[otel] crewai crewai-tools opentelemetry-instrumentation-openai opentelemetry-instrumentation-crewai python-dotenv +``` + +### Step 2: Set Up Environment Variables + +Setup Braintrust API keys and configure OpenTelemetry to send traces to Braintrust. You'll need a Braintrust API key and your OpenAI API key. + +```python +import os +from getpass import getpass + +# Get your Braintrust credentials +BRAINTRUST_API_KEY = getpass("🔑 Enter your Braintrust API Key: ") + +# Get API keys for services +OPENAI_API_KEY = getpass("🔑 Enter your OpenAI API key: ") + +# Set environment variables +os.environ["BRAINTRUST_API_KEY"] = BRAINTRUST_API_KEY +os.environ["BRAINTRUST_PARENT"] = "project_name:crewai-demo" +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +``` + +### Step 3: Initialize OpenTelemetry with Braintrust + +Initialize the Braintrust OpenTelemetry instrumentation to start capturing traces and send them to Braintrust. + +```python +import os +from typing import Any, Dict + +from braintrust.otel import BraintrustSpanProcessor +from crewai import Agent, Crew, Task +from crewai.llm import LLM +from opentelemetry import trace +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.instrumentation.openai import OpenAIInstrumentor +from opentelemetry.sdk.trace import TracerProvider + +def setup_tracing() -> None: + """Setup OpenTelemetry tracing with Braintrust.""" + current_provider = trace.get_tracer_provider() + if isinstance(current_provider, TracerProvider): + provider = current_provider + else: + provider = TracerProvider() + trace.set_tracer_provider(provider) + + provider.add_span_processor(BraintrustSpanProcessor()) + CrewAIInstrumentor().instrument(tracer_provider=provider) + OpenAIInstrumentor().instrument(tracer_provider=provider) + + +setup_tracing() +``` + +### Step 4: Create a CrewAI Application + +We'll create a CrewAI application where two agents collaborate to research and write a blog post about AI advancements, with comprehensive tracing enabled. + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool + +def create_crew() -> Crew: + """Create a crew with multiple agents for comprehensive tracing.""" + llm = LLM(model="gpt-4o-mini") + search_tool = SerperDevTool() + + # Define agents with specific roles + researcher = Agent( + role="Senior Research Analyst", + goal="Uncover cutting-edge developments in AI and data science", + backstory="""You work at a leading tech think tank. + Your expertise lies in identifying emerging trends. + You have a knack for dissecting complex data and presenting actionable insights.""", + verbose=True, + allow_delegation=False, + llm=llm, + tools=[search_tool], + ) + + writer = Agent( + role="Tech Content Strategist", + goal="Craft compelling content on tech advancements", + backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles. + You transform complex concepts into compelling narratives.""", + verbose=True, + allow_delegation=True, + llm=llm, + ) + + # Create tasks for your agents + research_task = Task( + description="""Conduct a comprehensive analysis of the latest advancements in {topic}. + Identify key trends, breakthrough technologies, and potential industry impacts.""", + expected_output="Full analysis report in bullet points", + agent=researcher, + ) + + writing_task = Task( + description="""Using the insights provided, develop an engaging blog + post that highlights the most significant {topic} advancements. + Your post should be informative yet accessible, catering to a tech-savvy audience. + Make it sound cool, avoid complex words so it doesn't sound like AI.""", + expected_output="Full blog post of at least 4 paragraphs", + agent=writer, + context=[research_task], + ) + + # Instantiate your crew with a sequential process + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True, + process=Process.sequential + ) + + return crew + +def run_crew(): + """Run the crew and return results.""" + crew = create_crew() + result = crew.kickoff(inputs={"topic": "AI developments"}) + return result + +# Run your crew +if __name__ == "__main__": + # Instrumentation is already initialized above in this module + result = run_crew() + print(result) +``` + +### Step 5: View Traces in Braintrust + +After running your crew, you can view comprehensive traces in Braintrust through different perspectives: + + + + + Braintrust Trace View + + + + + + Braintrust Timeline View + + + + + + Braintrust Thread View + + + + +### Step 6: Evaluate via SDK (Experiments) + +You can also run evaluations using Braintrust's Eval SDK. This is useful for comparing versions or scoring outputs offline. Below is a Python example using the `Eval` class with the crew we created above: + +```python +# eval_crew.py +from braintrust import Eval +from autoevals import Levenshtein + +def evaluate_crew_task(input_data): + """Task function that wraps our crew for evaluation.""" + crew = create_crew() + result = crew.kickoff(inputs={"topic": input_data["topic"]}) + return str(result) + +Eval( + "AI Research Crew", # Project name + { + "data": lambda: [ + {"topic": "artificial intelligence trends 2024"}, + {"topic": "machine learning breakthroughs"}, + {"topic": "AI ethics and governance"}, + ], + "task": evaluate_crew_task, + "scores": [Levenshtein], + }, +) +``` + +Setup your API key and run: + +```bash +export BRAINTRUST_API_KEY="YOUR_API_KEY" +braintrust eval eval_crew.py +``` + +See the [Braintrust Eval SDK guide](https://www.braintrust.dev/docs/start/eval-sdk) for more details. + +### Key Features of Braintrust Integration + +- **Comprehensive Tracing**: Track all agent interactions, tool usage, and LLM calls +- **Performance Monitoring**: Monitor execution times, token usage, and success rates +- **Experiment Tracking**: Compare different crew configurations and models +- **Automated Evaluation**: Set up custom evaluation metrics for crew outputs +- **Error Tracking**: Monitor and debug failures across your crew executions +- **Cost Analysis**: Track token usage and associated costs + +### Version Compatibility Information +- Python 3.8+ +- CrewAI >= 0.86.0 +- Braintrust >= 0.1.0 +- OpenTelemetry SDK >= 1.31.0 + +### References +- [Braintrust Documentation](https://www.braintrust.dev/docs) - Overview of the Braintrust platform +- [Braintrust CrewAI Integration](https://www.braintrust.dev/docs/integrations/crew-ai) - Official CrewAI integration guide +- [Braintrust Eval SDK](https://www.braintrust.dev/docs/start/eval-sdk) - Run experiments via the SDK +- [CrewAI Documentation](https://docs.crewai.com/) - Overview of the CrewAI framework +- [OpenTelemetry Docs](https://opentelemetry.io/docs/) - OpenTelemetry guide +- [Braintrust GitHub](https://github.com/braintrustdata/braintrust) - Source code for Braintrust SDK diff --git a/docs/v1.15.13/en/observability/datadog.mdx b/docs/v1.15.13/en/observability/datadog.mdx new file mode 100644 index 0000000000..0094446c5d --- /dev/null +++ b/docs/v1.15.13/en/observability/datadog.mdx @@ -0,0 +1,109 @@ +--- +title: Datadog Integration +description: Learn how to integrate Datadog with CrewAI to submit LLM Observability traces to Datadog. +icon: dog +mode: "wide" +--- + +# Integrate Datadog with CrewAI + +This guide will demonstrate how to integrate **[Datadog LLM Observability](https://docs.datadoghq.com/llm_observability/)** with **CrewAI** using [Datadog auto-instrumentation](https://docs.datadoghq.com/llm_observability/instrumentation/auto_instrumentation?tab=python). By the end of this guide, you will be able to submit LLM Observability traces to Datadog and view your CrewAI agent runs in Datadog LLM Observability's [Agentic Execution View](https://docs.datadoghq.com/llm_observability/monitoring/agent_monitoring). + +## What is Datadog LLM Observability? + +[Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/) helps AI engineers, data scientists, and application developers quickly develop, evaluate, and monitor LLM applications. Confidently improve output quality, performance, costs, and overall risk with structured experiments, end-to-end tracing across AI agents, and evaluations. + +## Getting Started + +### Install Dependencies + +```shell +pip install ddtrace crewai crewai-tools +``` + +### Set Environment Variables + +If you do not have a Datadog API key, you can [create an account](https://www.datadoghq.com/) and [get your API key](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys). + +You will also need to specify an ML Application name in the following environment variables. An ML Application is a grouping of LLM Observability traces associated with a specific LLM-based application. See [ML Application Naming Guidelines](https://docs.datadoghq.com/llm_observability/instrumentation/sdk?tab=python#application-naming-guidelines) for more information on limitations with ML Application names. + +```shell +export DD_API_KEY= +export DD_SITE= +export DD_LLMOBS_ENABLED=true +export DD_LLMOBS_ML_APP= +export DD_LLMOBS_AGENTLESS_ENABLED=true +export DD_APM_TRACING_ENABLED=false +``` + +Additionally, configure any LLM provider API keys + +```shell +export OPENAI_API_KEY= +export ANTHROPIC_API_KEY= +export GEMINI_API_KEY= +... +``` + +### Create a CrewAI Agent Application + +```python +# crewai_agent.py +from crewai import Agent, Task, Crew + +from crewai_tools import ( + WebsiteSearchTool +) + +web_rag_tool = WebsiteSearchTool() + +writer = Agent( + role="Writer", + goal="You make math engaging and understandable for young children through poetry", + backstory="You're an expert in writing haikus but you know nothing of math.", + tools=[web_rag_tool], +) + +task = Task( + description=("What is {multiplication}?"), + expected_output=("Compose a haiku that includes the answer."), + agent=writer +) + +crew = Crew( + agents=[writer], + tasks=[task], + share_crew=False +) + +output = crew.kickoff(dict(multiplication="2 * 2")) +``` + +### Run the Application with Datadog Auto-Instrumentation + +With the [environment variables](#set-environment-variables) set, you can now run the application with Datadog auto-instrumentation. + +```shell +ddtrace-run python crewai_agent.py +``` + +### View the Traces in Datadog + +After running the application, you can view the traces in [Datadog LLM Observability's Traces View](https://app.datadoghq.com/llm/traces), selecting the ML Application name you chose from the top-left dropdown. + +Clicking on a trace will show you the details of the trace, including total tokens used, number of LLM calls, models used, and estimated cost. Clicking into a specific span will narrow down these details, and show related input, output, and metadata. + + +Datadog LLM Observability Trace View + + +Additionally, you can view the execution graph view of the trace, which shows the control and data flow of the trace, which will scale with larger agents to show handoffs and relationships between LLM calls, tool calls, and agent interactions. + + +Datadog LLM Observability Agent Execution Flow View + + +## References + +- [Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/) +- [Datadog LLM Observability CrewAI Auto-Instrumentation](https://docs.datadoghq.com/llm_observability/instrumentation/auto_instrumentation?tab=python#crew-ai) diff --git a/docs/v1.15.13/en/observability/galileo.mdx b/docs/v1.15.13/en/observability/galileo.mdx new file mode 100644 index 0000000000..241517ed22 --- /dev/null +++ b/docs/v1.15.13/en/observability/galileo.mdx @@ -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. + +![Galileo trace view](/images/galileo-trace-veiw.png) + +## 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). diff --git a/docs/v1.15.13/en/observability/langdb.mdx b/docs/v1.15.13/en/observability/langdb.mdx new file mode 100644 index 0000000000..adb2d1908d --- /dev/null +++ b/docs/v1.15.13/en/observability/langdb.mdx @@ -0,0 +1,287 @@ +--- +title: LangDB Integration +description: Govern, secure, and optimize your CrewAI workflows with LangDB AI Gateway—access 350+ models, automatic routing, cost optimization, and full observability. +icon: database +mode: "wide" +--- + +# Introduction + +[LangDB AI Gateway](https://langdb.ai) provides OpenAI-compatible APIs to connect with multiple Large Language Models and serves as an observability platform that makes it effortless to trace CrewAI workflows end-to-end while providing access to 350+ language models. With a single `init()` call, all agent interactions, task executions, and LLM calls are captured, providing comprehensive observability and production-ready AI infrastructure for your applications. + + + LangDB CrewAI trace example + + +**Checkout:** [View the live trace example](https://app.langdb.ai/sharing/threads/3becbfed-a1be-ae84-ea3c-4942867a3e22) + +## Features + +### AI Gateway Capabilities +- **Access to 350+ LLMs**: Connect to all major language models through a single integration +- **Virtual Models**: Create custom model configurations with specific parameters and routing rules +- **Virtual MCP**: Enable compatibility and integration with MCP (Model Context Protocol) systems for enhanced agent communication +- **Guardrails**: Implement safety measures and compliance controls for agent behavior + +### Observability & Tracing +- **Automatic Tracing**: Single `init()` call captures all CrewAI interactions +- **End-to-End Visibility**: Monitor agent workflows from start to finish +- **Tool Usage Tracking**: Track which tools agents use and their outcomes +- **Model Call Monitoring**: Detailed insights into LLM interactions +- **Performance Analytics**: Monitor latency, token usage, and costs +- **Debugging Support**: Step-through execution for troubleshooting +- **Real-time Monitoring**: Live traces and metrics dashboard + +## Setup Instructions + + + + Install the LangDB client with CrewAI feature flag: + ```bash + pip install 'pylangdb[crewai]' + ``` + + + Configure your LangDB credentials: + ```bash + export LANGDB_API_KEY="" + export LANGDB_PROJECT_ID="" + export LANGDB_API_BASE_URL='https://api.us-east-1.langdb.ai' + ``` + + + Import and initialize LangDB before configuring your CrewAI code: + ```python + from pylangdb.crewai import init + # Initialize LangDB + init() + ``` + + + Set up your LLM with LangDB headers: + ```python + from crewai import Agent, Task, Crew, LLM + import os + + # Configure LLM with LangDB headers + llm = LLM( + model="openai/gpt-4o", # Replace with the model you want to use + api_key=os.getenv("LANGDB_API_KEY"), + base_url=os.getenv("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.getenv("LANGDB_PROJECT_ID")} + ) + ``` + + + +## Quick Start Example + +Here's a simple example to get you started with LangDB and CrewAI: + +```python +import os +from pylangdb.crewai import init +from crewai import Agent, Task, Crew, LLM + +# Initialize LangDB before any CrewAI imports +init() + +def create_llm(model): + return LLM( + model=model, + api_key=os.environ.get("LANGDB_API_KEY"), + base_url=os.environ.get("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.environ.get("LANGDB_PROJECT_ID")} + ) + +# Define your agent +researcher = Agent( + role="Research Specialist", + goal="Research topics thoroughly", + backstory="Expert researcher with skills in finding information", + llm=create_llm("openai/gpt-4o"), # Replace with the model you want to use + verbose=True +) + +# Create a task +task = Task( + description="Research the given topic and provide a comprehensive summary", + agent=researcher, + expected_output="Detailed research summary with key findings" +) + +# Create and run the crew +crew = Crew(agents=[researcher], tasks=[task]) +result = crew.kickoff() +print(result) +``` + +## Complete Example: Research and Planning Agent + +This comprehensive example demonstrates a multi-agent workflow with research and planning capabilities. + +### Prerequisites + +```bash +pip install crewai 'pylangdb[crewai]' crewai_tools setuptools python-dotenv +``` + +### Environment Setup + +```bash +# LangDB credentials +export LANGDB_API_KEY="" +export LANGDB_PROJECT_ID="" +export LANGDB_API_BASE_URL='https://api.us-east-1.langdb.ai' + +# Additional API keys (optional) +export SERPER_API_KEY="" # For web search capabilities +``` + +### Complete Implementation + +```python +#!/usr/bin/env python3 + +import os +import sys +from pylangdb.crewai import init +init() # Initialize LangDB before any CrewAI imports +from dotenv import load_dotenv +from crewai import Agent, Task, Crew, Process, LLM +from crewai_tools import SerperDevTool + +load_dotenv() + +def create_llm(model): + return LLM( + model=model, + api_key=os.environ.get("LANGDB_API_KEY"), + base_url=os.environ.get("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.environ.get("LANGDB_PROJECT_ID")} + ) + +class ResearchPlanningCrew: + def researcher(self) -> Agent: + return Agent( + role="Research Specialist", + goal="Research topics thoroughly and compile comprehensive information", + backstory="Expert researcher with skills in finding and analyzing information from various sources", + tools=[SerperDevTool()], + llm=create_llm("openai/gpt-4o"), + verbose=True + ) + + def planner(self) -> Agent: + return Agent( + role="Strategic Planner", + goal="Create actionable plans based on research findings", + backstory="Strategic planner who breaks down complex challenges into executable plans", + reasoning=True, + max_reasoning_attempts=3, + llm=create_llm("openai/anthropic/claude-3.7-sonnet"), + verbose=True + ) + + def research_task(self) -> Task: + return Task( + description="Research the topic thoroughly and compile comprehensive information", + agent=self.researcher(), + expected_output="Comprehensive research report with key findings and insights" + ) + + def planning_task(self) -> Task: + return Task( + description="Create a strategic plan based on the research findings", + agent=self.planner(), + expected_output="Strategic execution plan with phases, goals, and actionable steps", + context=[self.research_task()] + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.researcher(), self.planner()], + tasks=[self.research_task(), self.planning_task()], + verbose=True, + process=Process.sequential + ) + +def main(): + topic = sys.argv[1] if len(sys.argv) > 1 else "Artificial Intelligence in Healthcare" + + crew_instance = ResearchPlanningCrew() + + # Update task descriptions with the specific topic + crew_instance.research_task().description = f"Research {topic} thoroughly and compile comprehensive information" + crew_instance.planning_task().description = f"Create a strategic plan for {topic} based on the research findings" + + result = crew_instance.crew().kickoff() + print(result) + +if __name__ == "__main__": + main() +``` + +### Running the Example + +```bash +python main.py "Sustainable Energy Solutions" +``` + +## Viewing Traces in LangDB + +After running your CrewAI application, you can view detailed traces in the LangDB dashboard: + + + LangDB trace dashboard showing CrewAI workflow + + +### What You'll See + +- **Agent Interactions**: Complete flow of agent conversations and task handoffs +- **Tool Usage**: Which tools were called, their inputs, and outputs +- **Model Calls**: Detailed LLM interactions with prompts image.pngand responses +- **Performance Metrics**: Latency, token usage, and cost tracking +- **Execution Timeline**: Step-by-step view of the entire workflow + + +## Troubleshooting + +### Common Issues + +- **No traces appearing**: Ensure `init()` is called before any CrewAI imports +- **Authentication errors**: Verify your LangDB API key and project ID + + +## Resources + + + + Official LangDB documentation and guides + + + Step-by-step tutorials for building AI agents + + + Complete CrewAI integration examples + + + Access your traces and analytics + + + Browse 350+ available language models + + + Self-hosted options and enterprise capabilities + + + +## Next Steps + +This guide covered the basics of integrating LangDB AI Gateway with CrewAI. To further enhance your AI workflows, explore: + +- **Virtual Models**: Create custom model configurations with routing strategies +- **Guardrails & Safety**: Implement content filtering and compliance controls +- **Production Deployment**: Configure fallbacks, retries, and load balancing + +For more advanced features and use cases, visit the [LangDB Documentation](https://docs.langdb.ai) or explore the [Model Catalog](https://app.langdb.ai/models) to discover all available models. diff --git a/docs/v1.15.13/en/observability/langfuse.mdx b/docs/v1.15.13/en/observability/langfuse.mdx new file mode 100644 index 0000000000..2340b593e8 --- /dev/null +++ b/docs/v1.15.13/en/observability/langfuse.mdx @@ -0,0 +1,112 @@ +--- +title: Langfuse Integration +description: Learn how to integrate Langfuse with CrewAI via OpenTelemetry using OpenLit +icon: vials +mode: "wide" +--- + +# Integrate Langfuse with CrewAI + +This notebook demonstrates how to integrate **Langfuse** with **CrewAI** using OpenTelemetry via the **OpenLit** SDK. By the end of this notebook, you will be able to trace your CrewAI applications with Langfuse for improved observability and debugging. + +> **What is Langfuse?** [Langfuse](https://langfuse.com) is an open-source LLM engineering platform. It provides tracing and monitoring capabilities for LLM applications, helping developers debug, analyze, and optimize their AI systems. Langfuse integrates with various tools and frameworks via native integrations, OpenTelemetry, and APIs/SDKs. + +[![Langfuse Overview Video](https://github.com/user-attachments/assets/3926b288-ff61-4b95-8aa1-45d041c70866)](https://langfuse.com/watch-demo) + +## Get Started + +We'll walk through a simple example of using CrewAI and integrating it with Langfuse via OpenTelemetry using OpenLit. + +### Step 1: Install Dependencies + + +```python +%pip install langfuse openlit crewai crewai_tools +``` + +### Step 2: Set Up Environment Variables + +Set your Langfuse API keys and configure OpenTelemetry export settings to send traces to Langfuse. Please refer to the [Langfuse OpenTelemetry Docs](https://langfuse.com/docs/opentelemetry/get-started) for more information on the Langfuse OpenTelemetry endpoint `/api/public/otel` and authentication. + + +```python +import os + +# Get keys for your project from the project settings page: https://cloud.langfuse.com +os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..." +os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..." +os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # 🇪🇺 EU region +# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # 🇺🇸 US region + + +# Your OpenAI key +os.environ["OPENAI_API_KEY"] = "sk-proj-..." +``` +With the environment variables set, we can now initialize the Langfuse client. get_client() initializes the Langfuse client using the credentials provided in the environment variables. + +```python +from langfuse import get_client + +langfuse = get_client() + +# Verify connection +if langfuse.auth_check(): + print("Langfuse client is authenticated and ready!") +else: + print("Authentication failed. Please check your credentials and host.") +``` + +### Step 3: Initialize OpenLit + +Initialize the OpenLit OpenTelemetry instrumentation SDK to start capturing OpenTelemetry traces. + + +```python +import openlit + +openlit.init() +``` + +### Step 4: Create a Simple CrewAI Application + +We'll create a simple CrewAI application where multiple agents collaborate to answer a user's question. + + +```python +from crewai import Agent, Task, Crew + +from crewai_tools import ( + WebsiteSearchTool +) + +web_rag_tool = WebsiteSearchTool() + +writer = Agent( + role="Writer", + goal="You make math engaging and understandable for young children through poetry", + backstory="You're an expert in writing haikus but you know nothing of math.", + tools=[web_rag_tool], + ) + +task = Task(description=("What is {multiplication}?"), + expected_output=("Compose a haiku that includes the answer."), + agent=writer) + +crew = Crew( + agents=[writer], + tasks=[task], + share_crew=False +) +``` + +### Step 5: See Traces in Langfuse + +After running the agent, you can view the traces generated by your CrewAI application in [Langfuse](https://cloud.langfuse.com). You should see detailed steps of the LLM interactions, which can help you debug and optimize your AI agent. + +![CrewAI example trace in Langfuse](https://langfuse.com/images/cookbook/integration_crewai/crewai-example-trace.png) + +_[Public example trace in Langfuse](https://cloud.langfuse.com/project/cloramnkj0002jz088vzn1ja4/traces/e2cf380ffc8d47d28da98f136140642b?timestamp=2025-02-05T15%3A12%3A02.717Z&observation=3b32338ee6a5d9af)_ + +## References + +- [Langfuse OpenTelemetry Docs](https://langfuse.com/docs/opentelemetry/get-started) diff --git a/docs/v1.15.13/en/observability/langtrace.mdx b/docs/v1.15.13/en/observability/langtrace.mdx new file mode 100644 index 0000000000..8257f8eb7a --- /dev/null +++ b/docs/v1.15.13/en/observability/langtrace.mdx @@ -0,0 +1,73 @@ +--- +title: Langtrace Integration +description: How to monitor cost, latency, and performance of CrewAI Agents using Langtrace, an external observability tool. +icon: chart-line +mode: "wide" +--- + +# Langtrace Overview + +Langtrace is an open-source, external tool that helps you set up observability and evaluations for Large Language Models (LLMs), LLM frameworks, and Vector Databases. +While not built directly into CrewAI, Langtrace can be used alongside CrewAI to gain deep visibility into the cost, latency, and performance of your CrewAI Agents. +This integration allows you to log hyperparameters, monitor performance regressions, and establish a process for continuous improvement of your Agents. + +![Overview of a select series of agent session runs](/images/langtrace1.png) +![Overview of agent traces](/images/langtrace2.png) +![Overview of llm traces in details](/images/langtrace3.png) + +## Setup Instructions + + + + Sign up by visiting [https://langtrace.ai/signup](https://langtrace.ai/signup). + + + Set the project type to `CrewAI` and generate an API key. + + + Use the following command: + + ```bash + pip install langtrace-python-sdk + ``` + + + Import and initialize Langtrace at the beginning of your script, before any CrewAI imports: + + ```python + from langtrace_python_sdk import langtrace + langtrace.init(api_key='') + + # Now import CrewAI modules + from crewai import Agent, Task, Crew + ``` + + + +### Features and Their Application to CrewAI + +1. **LLM Token and Cost Tracking** + + - Monitor the token usage and associated costs for each CrewAI agent interaction. + +2. **Trace Graph for Execution Steps** + + - Visualize the execution flow of your CrewAI tasks, including latency and logs. + - Useful for identifying bottlenecks in your agent workflows. + +3. **Dataset Curation with Manual Annotation** + + - Create datasets from your CrewAI task outputs for future training or evaluation. + +4. **Prompt Versioning and Management** + + - Keep track of different versions of prompts used in your CrewAI agents. + - Useful for A/B testing and optimizing agent performance. + +5. **Prompt Playground with Model Comparisons** + + - Test and compare different prompts and models for your CrewAI agents before deployment. + +6. **Testing and Evaluations** + + - Set up automated tests for your CrewAI agents and tasks. diff --git a/docs/v1.15.13/en/observability/maxim.mdx b/docs/v1.15.13/en/observability/maxim.mdx new file mode 100644 index 0000000000..f8a2b46e49 --- /dev/null +++ b/docs/v1.15.13/en/observability/maxim.mdx @@ -0,0 +1,232 @@ +--- +title: "Maxim Integration" +description: "Start Agent monitoring, evaluation, and observability" +icon: "infinity" +mode: "wide" +--- + +# Maxim Overview + +Maxim AI provides comprehensive agent monitoring, evaluation, and observability for your CrewAI applications. With Maxim's one-line integration, you can easily trace and analyse agent interactions, performance metrics, and more. + +## Features + +### Prompt Management + +Maxim's Prompt Management capabilities enable you to create, organize, and optimize prompts for your CrewAI agents. Rather than hardcoding instructions, leverage Maxim’s SDK to dynamically retrieve and apply version-controlled prompts. + + + + Create, refine, experiment and deploy your prompts via the playground. Organize of your prompts using folders and versions, experimenting with the real world cases by linking tools and context, and deploying based on custom logic. + + Easily experiment across models by [**configuring models**](https://www.getmaxim.ai/docs/introduction/quickstart/setting-up-workspace#add-model-api-keys) and selecting the relevant model from the dropdown at the top of the prompt playground. + + + + + As teams build their AI applications, a big part of experimentation is iterating on the prompt structure. In order to collaborate effectively and organize your changes clearly, Maxim allows prompt versioning and comparison runs across versions. + + + + + Iterating on Prompts as you evolve your AI application would need experiments across models, prompt structures, etc. In order to compare versions and make informed decisions about changes, the comparison playground allows a side by side view of results. + + ## **Why use Prompt comparison?** + + Prompt comparison combines multiple single Prompts into one view, enabling a streamlined approach for various workflows: + + 1. **Model comparison**: Evaluate the performance of different models on the same Prompt. + 2. **Prompt optimization**: Compare different versions of a Prompt to identify the most effective formulation. + 3. **Cross-Model consistency**: Ensure consistent outputs across various models for the same Prompt. + 4. **Performance benchmarking**: Analyze metrics like latency, cost, and token count across different models and Prompts. + + + +### Observability & Evals + +Maxim AI provides comprehensive observability & evaluation for your CrewAI agents, helping you understand exactly what's happening during each execution. + + + + Track your agent’s complete lifecycle, including tool calls, agent trajectories, and decision flows effortlessly. + + + + + Run detailed evaluations on full traces or individual nodes with support for: + + - Multi-step interactions and granular trace analysis + - Session Level Evaluations + - Simulations for real-world testing + + + + + +

+ Evaluate captured logs automatically from the UI based on filters and sampling + +

+
+ +

+ Use human evaluation or rating to assess the quality of your logs and evaluate them. + +

+
+ +

+ Evaluate any component of your trace or log to gain insights into your agent’s behavior. + +

+
+
+ --- +
+ + Set thresholds on **error**, **cost, token usage, user feedback, latency** and get real-time alerts via Slack or PagerDuty. + + + + + Visualize Traces over time, usage metrics, latency & error rates with ease. + + + +
+ +## Getting Started + +### Prerequisites + + +- Python version \>=3.10 +- A Maxim account ([sign up here](https://getmaxim.ai/)) +- Generate Maxim API Key +- A CrewAI project + +### Installation + +Install the Maxim SDK via pip: + +```python +pip install maxim-py +``` + +Or add it to your `requirements.txt`: + +``` +maxim-py +``` +### Basic Setup + +### 1. Set up environment variables + +```python +### Environment Variables Setup + +# Create a `.env` file in your project root: + +# Maxim API Configuration +MAXIM_API_KEY=your_api_key_here +MAXIM_LOG_REPO_ID=your_repo_id_here +``` + +### 2. Import the required packages + +```python +from crewai import Agent, Task, Crew, Process +from maxim import Maxim +from maxim.logger.crewai import instrument_crewai +``` + +### 3. Initialise Maxim with your API key + + +```python {8} +# Instrument CrewAI with just one line +instrument_crewai(Maxim().logger()) +``` + +### 4. Create and run your CrewAI application as usual + +```python +# Create your agent +researcher = Agent( + role='Senior Research Analyst', + goal='Uncover cutting-edge developments in AI', + backstory="You are an expert researcher at a tech think tank...", + verbose=True, + llm=llm +) + +# Define the task +research_task = Task( + description="Research the latest AI advancements...", + expected_output="", + agent=researcher +) + +# Configure and run the crew +crew = Crew( + agents=[researcher], + tasks=[research_task], + verbose=True +) + +try: + result = crew.kickoff() +finally: + maxim.cleanup() # Ensure cleanup happens even if errors occur +``` + + +That's it\! All your CrewAI agent interactions will now be logged and available in your Maxim dashboard. + +Check this Google Colab Notebook for a quick reference - [Notebook](https://colab.research.google.com/drive/1ZKIZWsmgQQ46n8TH9zLsT1negKkJA6K8?usp=sharing) + +## Viewing Your Traces + +After running your CrewAI application: + +1. Log in to your [Maxim Dashboard](https://app.getmaxim.ai/login) +2. Navigate to your repository +3. View detailed agent traces, including: + - Agent conversations + - Tool usage patterns + - Performance metrics + - Cost analytics + + + +## Troubleshooting + +### Common Issues + +- **No traces appearing**: Ensure your API key and repository ID are correct +- Ensure you've **`called instrument_crewai()`** **_before_** running your crew. This initializes logging hooks correctly. +- Set `debug=True` in your `instrument_crewai()` call to surface any internal errors: + + ```python + instrument_crewai(logger, debug=True) + ``` +- Configure your agents with `verbose=True` to capture detailed logs: + + ```python + agent = CrewAgent(..., verbose=True) + ``` +- Double-check that `instrument_crewai()` is called **before** creating or executing agents. This might be obvious, but it's a common oversight. + +## Resources + + + + Official CrewAI documentation + + + Official Maxim documentation + + + Maxim Github + + \ No newline at end of file diff --git a/docs/v1.15.13/en/observability/mlflow.mdx b/docs/v1.15.13/en/observability/mlflow.mdx new file mode 100644 index 0000000000..321448477d --- /dev/null +++ b/docs/v1.15.13/en/observability/mlflow.mdx @@ -0,0 +1,207 @@ +--- +title: MLflow Integration +description: Quickly start monitoring your Agents with MLflow. +icon: bars-staggered +mode: "wide" +--- + +# MLflow Overview + +[MLflow](https://mlflow.org/) is an open-source platform to assist machine learning practitioners and teams in handling the complexities of the machine learning process. + +It provides a tracing feature that enhances LLM observability in your Generative AI applications by capturing detailed information about the execution of your application’s services. +Tracing provides a way to record the inputs, outputs, and metadata associated with each intermediate step of a request, enabling you to easily pinpoint the source of bugs and unexpected behaviors. + +![Overview of MLflow crewAI tracing usage](/images/mlflow-tracing.gif) + +### Features + +- **Tracing Dashboard**: Monitor activities of your crewAI agents with detailed dashboards that include inputs, outputs and metadata of spans. +- **Automated Tracing**: A fully automated integration with crewAI, which can be enabled by running `mlflow.crewai.autolog()`. +- **Manual Trace Instrumentation with minor efforts**: Customize trace instrumentation through MLflow's high-level fluent APIs such as decorators, function wrappers and context managers. +- **OpenTelemetry Compatibility**: MLflow Tracing supports exporting traces to an OpenTelemetry Collector, which can then be used to export traces to various backends such as Jaeger, Zipkin, and AWS X-Ray. +- **Package and Deploy Agents**: Package and deploy your crewAI agents to an inference server with a variety of deployment targets. +- **Securely Host LLMs**: Host multiple LLM from various providers in one unified endpoint through MFflow gateway. +- **Evaluation**: Evaluate your crewAI agents with a wide range of metrics using a convenient API `mlflow.evaluate()`. + +## Setup Instructions + + + + ```shell + # The crewAI integration is available in mlflow>=2.19.0 + pip install mlflow + ``` + + + ```shell + # This process is optional, but it is recommended to use MLflow tracking server for better visualization and broader features. + mlflow server + ``` + + + Add the following two lines to your application code: + + ```python + import mlflow + + mlflow.crewai.autolog() + + # Optional: Set a tracking URI and an experiment name if you have a tracking server + mlflow.set_tracking_uri("http://localhost:5000") + mlflow.set_experiment("CrewAI") + ``` + + Example Usage for tracing CrewAI Agents: + + ```python + from crewai import Agent, Crew, Task + from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + from crewai_tools import SerperDevTool, WebsiteSearchTool + + from textwrap import dedent + + content = "Users name is John. He is 30 years old and lives in San Francisco." + string_source = StringKnowledgeSource( + content=content, metadata={"preference": "personal"} + ) + + search_tool = WebsiteSearchTool() + + + class TripAgents: + def city_selection_agent(self): + return Agent( + role="City Selection Expert", + goal="Select the best city based on weather, season, and prices", + backstory="An expert in analyzing travel data to pick ideal destinations", + tools=[ + search_tool, + ], + verbose=True, + ) + + def local_expert(self): + return Agent( + role="Local Expert at this city", + goal="Provide the BEST insights about the selected city", + backstory="""A knowledgeable local guide with extensive information + about the city, it's attractions and customs""", + tools=[search_tool], + verbose=True, + ) + + + class TripTasks: + def identify_task(self, agent, origin, cities, interests, range): + return Task( + description=dedent( + f""" + Analyze and select the best city for the trip based + on specific criteria such as weather patterns, seasonal + events, and travel costs. This task involves comparing + multiple cities, considering factors like current weather + conditions, upcoming cultural or seasonal events, and + overall travel expenses. + Your final answer must be a detailed + report on the chosen city, and everything you found out + about it, including the actual flight costs, weather + forecast and attractions. + + Traveling from: {origin} + City Options: {cities} + Trip Date: {range} + Traveler Interests: {interests} + """ + ), + agent=agent, + expected_output="Detailed report on the chosen city including flight costs, weather forecast, and attractions", + ) + + def gather_task(self, agent, origin, interests, range): + return Task( + description=dedent( + f""" + As a local expert on this city you must compile an + in-depth guide for someone traveling there and wanting + to have THE BEST trip ever! + Gather information about key attractions, local customs, + special events, and daily activity recommendations. + Find the best spots to go to, the kind of place only a + local would know. + This guide should provide a thorough overview of what + the city has to offer, including hidden gems, cultural + hotspots, must-visit landmarks, weather forecasts, and + high level costs. + The final answer must be a comprehensive city guide, + rich in cultural insights and practical tips, + tailored to enhance the travel experience. + + Trip Date: {range} + Traveling from: {origin} + Traveler Interests: {interests} + """ + ), + agent=agent, + expected_output="Comprehensive city guide including hidden gems, cultural hotspots, and practical travel tips", + ) + + + class TripCrew: + def __init__(self, origin, cities, date_range, interests): + self.cities = cities + self.origin = origin + self.interests = interests + self.date_range = date_range + + def run(self): + agents = TripAgents() + tasks = TripTasks() + + city_selector_agent = agents.city_selection_agent() + local_expert_agent = agents.local_expert() + + identify_task = tasks.identify_task( + city_selector_agent, + self.origin, + self.cities, + self.interests, + self.date_range, + ) + gather_task = tasks.gather_task( + local_expert_agent, self.origin, self.interests, self.date_range + ) + + crew = Crew( + agents=[city_selector_agent, local_expert_agent], + tasks=[identify_task, gather_task], + verbose=True, + memory=True, + knowledge={ + "sources": [string_source], + "metadata": {"preference": "personal"}, + }, + ) + + result = crew.kickoff() + return result + + + trip_crew = TripCrew("California", "Tokyo", "Dec 12 - Dec 20", "sports") + result = trip_crew.run() + + print(result) + ``` + Refer to [MLflow Tracing Documentation](https://mlflow.org/docs/latest/llms/tracing/index.html) for more configurations and use cases. + + + Now traces for your crewAI agents are captured by MLflow. + Let's visit MLflow tracking server to view the traces and get insights into your Agents. + + Open `127.0.0.1:5000` on your browser to visit MLflow tracking server. + + MLflow tracing example with crewai + + + + diff --git a/docs/v1.15.13/en/observability/neatlogs.mdx b/docs/v1.15.13/en/observability/neatlogs.mdx new file mode 100644 index 0000000000..24b17cfced --- /dev/null +++ b/docs/v1.15.13/en/observability/neatlogs.mdx @@ -0,0 +1,134 @@ +--- +title: Neatlogs Integration +description: Understand, debug, and share your CrewAI agent runs +icon: magnifying-glass-chart +mode: "wide" +--- + +# Introduction + +Neatlogs helps you **see what your agent did**, **why**, and **share it**. + +It captures every step: thoughts, tool calls, responses, evaluations. No raw logs. Just clear, structured traces. Great for debugging and collaboration. + +## Why use Neatlogs? + +CrewAI agents use multiple tools and reasoning steps. When something goes wrong, you need context — not just errors. + +Neatlogs lets you: + +- Follow the full decision path +- Add feedback directly on steps +- Chat with the trace using AI assistant +- Share runs publicly for feedback +- Turn insights into tasks + +All in one place. + +Manage your traces effortlessly + +![Traces](/images/neatlogs-1.png) +![Trace Response](/images/neatlogs-2.png) + +The best UX to view a CrewAI trace. Post comments anywhere you want. Use AI to debug. + +![Trace Details](/images/neatlogs-3.png) +![Ai Chat Bot With A Trace](/images/neatlogs-4.png) +![Comments Drawer](/images/neatlogs-5.png) + +## Core Features + +- **Trace Viewer**: Track thoughts, tools, and decisions in sequence +- **Inline Comments**: Tag teammates on any trace step +- **Feedback & Evaluation**: Mark outputs as correct or incorrect +- **Error Highlighting**: Automatic flagging of API/tool failures +- **Task Conversion**: Convert comments into assigned tasks +- **Ask the Trace (AI)**: Chat with your trace using Neatlogs AI bot +- **Public Sharing**: Publish trace links to your community + +## Quick Setup with CrewAI + + + + Visit [neatlogs.com](https://neatlogs.com/?utm_source=crewAI-docs), create a project, copy the API key. + + + ```bash + pip install neatlogs + ``` + (Latest version 0.8.0, Python 3.8+; MIT license) + + + Before starting Crew agents, add: + + ```python + import neatlogs + neatlogs.init("YOUR_PROJECT_API_KEY") + ``` + + Agents run as usual. Neatlogs captures everything automatically. + + + + + + +## Under the Hood + +According to GitHub, Neatlogs: + +- Captures thoughts, tool calls, responses, errors, and token stats +- Supports AI-powered task generation and robust evaluation workflows + +All with just two lines of code. + + + +## Watch It Work + +### 🔍 Full Demo (4 min) + + + +### ⚙️ CrewAI Integration (30 s) + + + + + +## Links & Support + +- 📘 [Neatlogs Docs](https://docs.neatlogs.com/) +- 🔐 [Dashboard & API Key](https://app.neatlogs.com/) +- 🐦 [Follow on Twitter](https://twitter.com/neatlogs) +- 📧 Contact: hello@neatlogs.com +- 🛠 [GitHub SDK](https://github.com/NeatLogs/neatlogs) + + + +## TL;DR + +With just: + +```bash +pip install neatlogs + +import neatlogs +neatlogs.init("YOUR_API_KEY") + +You can now capture, understand, share, and act on your CrewAI agent runs in seconds. +No setup overhead. Full trace transparency. Full team collaboration. +``` diff --git a/docs/v1.15.13/en/observability/openlit.mdx b/docs/v1.15.13/en/observability/openlit.mdx new file mode 100644 index 0000000000..17e0831525 --- /dev/null +++ b/docs/v1.15.13/en/observability/openlit.mdx @@ -0,0 +1,182 @@ +--- +title: OpenLIT Integration +description: Quickly start monitoring your Agents in just a single line of code with OpenTelemetry. +icon: magnifying-glass-chart +mode: "wide" +--- + +# OpenLIT Overview + +[OpenLIT](https://github.com/openlit/openlit?src=crewai-docs) is an open-source tool that makes it simple to monitor the performance of AI agents, LLMs, VectorDBs, and GPUs with just **one** line of code. + +It provides OpenTelemetry-native tracing and metrics to track important parameters like cost, latency, interactions and task sequences. +This setup enables you to track hyperparameters and monitor for performance issues, helping you find ways to enhance and fine-tune your agents over time. + + + Overview Agent usage including cost and tokens + Overview of agent otel traces and metrics + Overview of agent traces in details + + +### Features + +- **Analytics Dashboard**: Monitor your Agents health and performance with detailed dashboards that track metrics, costs, and user interactions. +- **OpenTelemetry-native Observability SDK**: Vendor-neutral SDKs to send traces and metrics to your existing observability tools like Grafana, DataDog and more. +- **Cost Tracking for Custom and Fine-Tuned Models**: Tailor cost estimations for specific models using custom pricing files for precise budgeting. +- **Exceptions Monitoring Dashboard**: Quickly spot and resolve issues by tracking common exceptions and errors with a monitoring dashboard. +- **Compliance and Security**: Detect potential threats such as profanity and PII leaks. +- **Prompt Injection Detection**: Identify potential code injection and secret leaks. +- **API Keys and Secrets Management**: Securely handle your LLM API keys and secrets centrally, avoiding insecure practices. +- **Prompt Management**: Manage and version Agent prompts using PromptHub for consistent and easy access across Agents. +- **Model Playground** Test and compare different models for your CrewAI agents before deployment. + +## Setup Instructions + + + + + + ```shell + git clone git@github.com:openlit/openlit.git + ``` + + + From the root directory of the [OpenLIT Repo](https://github.com/openlit/openlit), Run the below command: + ```shell + docker compose up -d + ``` + + + + + ```shell + pip install openlit + ``` + + + Add the following two lines to your application code: + + + ```python + import openlit + openlit.init(otlp_endpoint="http://127.0.0.1:4318") + ``` + + Example Usage for monitoring a CrewAI Agent: + + ```python + from crewai import Agent, Task, Crew, Process + import openlit + + openlit.init(disable_metrics=True) + # Define your agents + researcher = Agent( + role="Researcher", + goal="Conduct thorough research and analysis on AI and AI agents", + backstory="You're an expert researcher, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently researching for a new client.", + allow_delegation=False, + llm='command-r' + ) + + + # Define your task + task = Task( + description="Generate a list of 5 interesting ideas for an article, then write one captivating paragraph for each idea that showcases the potential of a full article on this topic. Return the list of ideas with their paragraphs and your notes.", + expected_output="5 bullet points, each with a paragraph and accompanying notes.", + ) + + # Define the manager agent + manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success. Your role is to coordinate the efforts of the crew members, ensuring that each task is completed on time and to the highest standard.", + allow_delegation=True, + llm='command-r' + ) + + # Instantiate your crew with a custom manager + crew = Crew( + agents=[researcher], + tasks=[task], + manager_agent=manager, + process=Process.hierarchical, + ) + + # Start the crew's work + result = crew.kickoff() + + print(result) + ``` + + + + Add the following two lines to your application code: + ```python + import openlit + + openlit.init() + ``` + + Run the following command to configure the OTEL export endpoint: + ```shell + export OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4318" + ``` + + Example Usage for monitoring a CrewAI Async Agent: + + ```python + import asyncio + from crewai import Crew, Agent, Task + import openlit + + openlit.init(otlp_endpoint="http://127.0.0.1:4318") + + # Create an agent with code execution enabled + coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True, + llm="command-r" + ) + + # Create a task that requires code execution + data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="5 bullet points, each with a paragraph and accompanying notes.", + ) + + # Create a crew and add the task + analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] + ) + + # Async function to kickoff the crew asynchronously + async def async_crew_execution(): + result = await analysis_crew.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + + # Run the async function + asyncio.run(async_crew_execution()) + ``` + + + Refer to OpenLIT [Python SDK repository](https://github.com/openlit/openlit/tree/main/sdk/python) for more advanced configurations and use cases. + + + With the Agent Observability data now being collected and sent to OpenLIT, the next step is to visualize and analyze this data to get insights into your Agent's performance, behavior, and identify areas of improvement. + + Just head over to OpenLIT at `127.0.0.1:3000` on your browser to start exploring. You can login using the default credentials + - **Email**: `user@openlit.io` + - **Password**: `openlituser` + + + Overview Agent usage including cost and tokens + Overview of agent otel traces and metrics + + + + + diff --git a/docs/v1.15.13/en/observability/opik.mdx b/docs/v1.15.13/en/observability/opik.mdx new file mode 100644 index 0000000000..90af97cc7c --- /dev/null +++ b/docs/v1.15.13/en/observability/opik.mdx @@ -0,0 +1,130 @@ +--- +title: Opik Integration +description: Learn how to use Comet Opik to debug, evaluate, and monitor your CrewAI applications with comprehensive tracing, automated evaluations, and production-ready dashboards. +icon: meteor +mode: "wide" +--- + +# Opik Overview + +With [Comet Opik](https://www.comet.com/docs/opik/), debug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards. + + + Opik agent monitoring example with CrewAI + + +Opik provides comprehensive support for every stage of your CrewAI application development: + +- **Log Traces and Spans**: Automatically track LLM calls and application logic to debug and analyze development and production systems. Manually or programmatically annotate, view, and compare responses across projects. +- **Evaluate Your LLM Application's Performance**: Evaluate against a custom test set and run built-in evaluation metrics or define your own metrics in the SDK or UI. +- **Test Within Your CI/CD Pipeline**: Establish reliable performance baselines with Opik's LLM unit tests, built on PyTest. Run online evaluations for continuous monitoring in production. +- **Monitor & Analyze Production Data**: Understand your models' performance on unseen data in production and generate datasets for new dev iterations. + +## Setup +Comet provides a hosted version of the Opik platform, or you can run the platform locally. + +To use the hosted version, simply [create a free Comet account](https://www.comet.com/signup?utm_medium=github&utm_source=crewai_docs) and grab you API Key. + +To run the Opik platform locally, see our [installation guide](https://www.comet.com/docs/opik/self-host/overview/) for more information. + +For this guide we will use CrewAI’s quickstart example. + + + + ```shell + pip install crewai crewai-tools opik --upgrade + ``` + + + ```python + import opik + opik.configure(use_local=False) + ``` + + + First, we set up our API keys for our LLM-provider as environment variables: + + ```python + import os + import getpass + + if "OPENAI_API_KEY" not in os.environ: + os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ") + ``` + + + The first step is to create our project. We will use an example from CrewAI’s documentation: + + ```python + from crewai import Agent, Crew, Task, Process + + + class YourCrewName: + def agent_one(self) -> Agent: + return Agent( + role="Data Analyst", + goal="Analyze data trends in the market", + backstory="An experienced data analyst with a background in economics", + verbose=True, + ) + + def agent_two(self) -> Agent: + return Agent( + role="Market Researcher", + goal="Gather information on market dynamics", + backstory="A diligent researcher with a keen eye for detail", + verbose=True, + ) + + def task_one(self) -> Task: + return Task( + name="Collect Data Task", + description="Collect recent market data and identify trends.", + expected_output="A report summarizing key trends in the market.", + agent=self.agent_one(), + ) + + def task_two(self) -> Task: + return Task( + name="Market Research Task", + description="Research factors affecting market dynamics.", + expected_output="An analysis of factors influencing the market.", + agent=self.agent_two(), + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.agent_one(), self.agent_two()], + tasks=[self.task_one(), self.task_two()], + process=Process.sequential, + verbose=True, + ) + + ``` + + Now we can import Opik’s tracker and run our crew: + + ```python + from opik.integrations.crewai import track_crewai + + track_crewai(project_name="crewai-integration-demo") + + my_crew = YourCrewName().crew() + result = my_crew.kickoff() + + print(result) + ``` + After running your CrewAI application, visit the Opik app to view: + - LLM traces, spans, and their metadata + - Agent interactions and task execution flow + - Performance metrics like latency and token usage + - Evaluation metrics (built-in or custom) + + + +## Resources + +- [🦉 Opik Documentation](https://www.comet.com/docs/opik/) +- [👉 Opik + CrewAI Colab](https://colab.research.google.com/github/comet-ml/opik/blob/main/apps/opik-documentation/documentation/docs/cookbook/crewai.ipynb) +- [🐦 X](https://x.com/cometml) +- [💬 Slack](https://slack.comet.com/) diff --git a/docs/v1.15.13/en/observability/overview.mdx b/docs/v1.15.13/en/observability/overview.mdx new file mode 100644 index 0000000000..171a922f28 --- /dev/null +++ b/docs/v1.15.13/en/observability/overview.mdx @@ -0,0 +1,120 @@ +--- +title: "Overview" +description: "Monitor, evaluate, and optimize your CrewAI agents with comprehensive observability tools" +icon: "face-smile" +mode: "wide" +--- + +## Observability for CrewAI + +Observability is crucial for understanding how your CrewAI agents perform, identifying bottlenecks, and ensuring reliable operation in production environments. This section covers various tools and platforms that provide monitoring, evaluation, and optimization capabilities for your agent workflows. + +## Why Observability Matters + +- **Performance Monitoring**: Track agent execution times, token usage, and resource consumption +- **Quality Assurance**: Evaluate output quality and consistency across different scenarios +- **Debugging**: Identify and resolve issues in agent behavior and task execution +- **Cost Management**: Monitor LLM API usage and associated costs +- **Continuous Improvement**: Gather insights to optimize agent performance over time + +## Available Observability Tools + +### Monitoring & Tracing Platforms + + + + + End-to-end tracing for CrewAI workflows with automatic agent interaction capture. + + + + OpenTelemetry-native monitoring with cost tracking and performance analytics. + + + + Machine learning lifecycle management with tracing and evaluation capabilities. + + + + LLM engineering platform with detailed tracing and analytics. + + + + Open-source observability for LLMs and agent frameworks. + + + + AI observability platform for monitoring and troubleshooting. + + + + AI gateway with comprehensive monitoring and reliability features. + + + + Debug, evaluate, and monitor LLM applications with comprehensive tracing. + + + + Weights & Biases platform for tracking and evaluating AI applications. + + + +### Evaluation & Quality Assurance + + + + Comprehensive evaluation platform for LLM outputs and agent behaviors. + + + +## Key Observability Metrics + +### Performance Metrics +- **Execution Time**: How long agents take to complete tasks +- **Token Usage**: Input/output tokens consumed by LLM calls +- **API Latency**: Response times from external services +- **Success Rate**: Percentage of successfully completed tasks + +### Quality Metrics +- **Output Accuracy**: Correctness of agent responses +- **Consistency**: Reliability across similar inputs +- **Relevance**: How well outputs match expected results +- **Safety**: Compliance with content policies and guidelines + +### Cost Metrics +- **API Costs**: Expenses from LLM provider usage +- **Resource Utilization**: Compute and memory consumption +- **Cost per Task**: Economic efficiency of agent operations +- **Budget Tracking**: Monitoring against spending limits + +## Getting Started + +1. **Choose Your Tools**: Select observability platforms that match your needs +2. **Instrument Your Code**: Add monitoring to your CrewAI applications +3. **Set Up Dashboards**: Configure visualizations for key metrics +4. **Define Alerts**: Create notifications for important events +5. **Establish Baselines**: Measure initial performance for comparison +6. **Iterate and Improve**: Use insights to optimize your agents + +## Best Practices + +### Development Phase +- Use detailed tracing to understand agent behavior +- Implement evaluation metrics early in development +- Monitor resource usage during testing +- Set up automated quality checks + +### Production Phase +- Implement comprehensive monitoring and alerting +- Track performance trends over time +- Monitor for anomalies and degradation +- Maintain cost visibility and control + +### Continuous Improvement +- Regular performance reviews and optimization +- A/B testing of different agent configurations +- Feedback loops for quality improvement +- Documentation of lessons learned + +Choose the observability tools that best fit your use case, infrastructure, and monitoring requirements to ensure your CrewAI agents perform reliably and efficiently. diff --git a/docs/v1.15.13/en/observability/patronus-evaluation.mdx b/docs/v1.15.13/en/observability/patronus-evaluation.mdx new file mode 100644 index 0000000000..0326fede37 --- /dev/null +++ b/docs/v1.15.13/en/observability/patronus-evaluation.mdx @@ -0,0 +1,206 @@ +--- +title: Patronus AI Evaluation +description: Monitor and evaluate CrewAI agent performance using Patronus AI's comprehensive evaluation platform for LLM outputs and agent behaviors. +icon: shield-check +mode: "wide" +--- + +# Patronus AI Evaluation + +## Overview + +[Patronus AI](https://patronus.ai) provides comprehensive evaluation and monitoring capabilities for CrewAI agents, enabling you to assess model outputs, agent behaviors, and overall system performance. This integration allows you to implement continuous evaluation workflows that help maintain quality and reliability in production environments. + +## Key Features + +- **Automated Evaluation**: Real-time assessment of agent outputs and behaviors +- **Custom Criteria**: Define specific evaluation criteria tailored to your use cases +- **Performance Monitoring**: Track agent performance metrics over time +- **Quality Assurance**: Ensure consistent output quality across different scenarios +- **Safety & Compliance**: Monitor for potential issues and policy violations + +## Evaluation Tools + +Patronus provides three main evaluation tools for different use cases: + +1. **PatronusEvalTool**: Allows agents to select the most appropriate evaluator and criteria for the evaluation task. +2. **PatronusPredefinedCriteriaEvalTool**: Uses predefined evaluator and criteria specified by the user. +3. **PatronusLocalEvaluatorTool**: Uses custom function evaluators defined by the user. + +## Installation + +To use these tools, you need to install the Patronus package: + +```shell +uv add patronus +``` + +You'll also need to set up your Patronus API key as an environment variable: + +```shell +export PATRONUS_API_KEY="your_patronus_api_key" +``` + +## Steps to Get Started + +To effectively use the Patronus evaluation tools, follow these steps: + +1. **Install Patronus**: Install the Patronus package using the command above. +2. **Set Up API Key**: Set your Patronus API key as an environment variable. +3. **Choose the Right Tool**: Select the appropriate Patronus evaluation tool based on your needs. +4. **Configure the Tool**: Configure the tool with the necessary parameters. + +## Examples + +### Using PatronusEvalTool + +The following example demonstrates how to use the `PatronusEvalTool`, which allows agents to select the most appropriate evaluator and criteria: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusEvalTool + +# Initialize the tool +patronus_eval_tool = PatronusEvalTool() + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code and verify that the output is code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate and evaluate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence. Select the most appropriate evaluator and criteria for evaluating your output.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +### Using PatronusPredefinedCriteriaEvalTool + +The following example demonstrates how to use the `PatronusPredefinedCriteriaEvalTool`, which uses predefined evaluator and criteria: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusPredefinedCriteriaEvalTool + +# Initialize the tool with predefined criteria +patronus_eval_tool = PatronusPredefinedCriteriaEvalTool( + evaluators=[{"evaluator": "judge", "criteria": "contains-code"}] +) + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +### Using PatronusLocalEvaluatorTool + +The following example demonstrates how to use the `PatronusLocalEvaluatorTool`, which uses custom function evaluators: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusLocalEvaluatorTool +from patronus import Client, EvaluationResult +import random + +# Initialize the Patronus client +client = Client() + +# Register a custom evaluator +@client.register_local_evaluator("random_evaluator") +def random_evaluator(**kwargs): + score = random.random() + return EvaluationResult( + score_raw=score, + pass_=score >= 0.5, + explanation="example explanation", + ) + +# Initialize the tool with the custom evaluator +patronus_eval_tool = PatronusLocalEvaluatorTool( + patronus_client=client, + evaluator="random_evaluator", + evaluated_model_gold_answer="example label", +) + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +## Parameters + +### PatronusEvalTool + +The `PatronusEvalTool` does not require any parameters during initialization. It automatically fetches available evaluators and criteria from the Patronus API. + +### PatronusPredefinedCriteriaEvalTool + +The `PatronusPredefinedCriteriaEvalTool` accepts the following parameters during initialization: + +- **evaluators**: Required. A list of dictionaries containing the evaluator and criteria to use. For example: `[{"evaluator": "judge", "criteria": "contains-code"}]`. + +### PatronusLocalEvaluatorTool + +The `PatronusLocalEvaluatorTool` accepts the following parameters during initialization: + +- **patronus_client**: Required. The Patronus client instance. +- **evaluator**: Optional. The name of the registered local evaluator to use. Default is an empty string. +- **evaluated_model_gold_answer**: Optional. The gold answer to use for evaluation. Default is an empty string. + +## Usage + +When using the Patronus evaluation tools, you provide the model input, output, and context, and the tool returns the evaluation results from the Patronus API. + +For the `PatronusEvalTool` and `PatronusPredefinedCriteriaEvalTool`, the following parameters are required when calling the tool: + +- **evaluated_model_input**: The agent's task description in simple text. +- **evaluated_model_output**: The agent's output of the task. +- **evaluated_model_retrieved_context**: The agent's context. + +For the `PatronusLocalEvaluatorTool`, the same parameters are required, but the evaluator and gold answer are specified during initialization. + +## Conclusion + +The Patronus evaluation tools provide a powerful way to evaluate and score model inputs and outputs using the Patronus AI platform. By enabling agents to evaluate their own outputs or the outputs of other agents, these tools can help improve the quality and reliability of CrewAI workflows. \ No newline at end of file diff --git a/docs/v1.15.13/en/observability/portkey.mdx b/docs/v1.15.13/en/observability/portkey.mdx new file mode 100644 index 0000000000..851cd358aa --- /dev/null +++ b/docs/v1.15.13/en/observability/portkey.mdx @@ -0,0 +1,823 @@ +--- +title: Portkey Integration +description: How to use Portkey with CrewAI +icon: key +mode: "wide" +--- + +Portkey CrewAI Header Image + + + +## Introduction + +Portkey enhances CrewAI with production-readiness features, turning your experimental agent crews into robust systems by providing: + +- **Complete observability** of every agent step, tool use, and interaction +- **Built-in reliability** with fallbacks, retries, and load balancing +- **Cost tracking and optimization** to manage your AI spend +- **Access to 200+ LLMs** through a single integration +- **Guardrails** to keep agent behavior safe and compliant +- **Version-controlled prompts** for consistent agent performance + + +### Installation & Setup + + + +```bash +pip install -U crewai portkey-ai +``` + + + +Create a Portkey API key with optional budget/rate limits from the [Portkey dashboard](https://app.portkey.ai/). You can also attach configurations for reliability, caching, and more to this key. More on this later. + + + +The integration is simple - you just need to update the LLM configuration in your CrewAI setup: + +```python +from crewai import LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Create an LLM instance with Portkey integration +gpt_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", # We are using a Virtual key, so this is a placeholder + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_LLM_VIRTUAL_KEY", + trace_id="unique-trace-id", # Optional, for request tracing + ) +) + +#Use them in your Crew Agents like this: + + @agent + def lead_market_analyst(self) -> Agent: + return Agent( + config=self.agents_config['lead_market_analyst'], + verbose=True, + memory=False, + llm=gpt_llm + ) + +``` + + +**What are Virtual Keys?** Virtual keys in Portkey securely store your LLM provider API keys (OpenAI, Anthropic, etc.) in an encrypted vault. They allow for easier key rotation and budget management. [Learn more about virtual keys here](https://portkey.ai/docs/product/ai-gateway/virtual-keys). + + + + +## Production Features + +### 1. Enhanced Observability + +Portkey provides comprehensive observability for your CrewAI agents, helping you understand exactly what's happening during each execution. + + + + + + + +Traces provide a hierarchical view of your crew's execution, showing the sequence of LLM calls, tool invocations, and state transitions. + +```python +# Add trace_id to enable hierarchical tracing in Portkey +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + trace_id="unique-session-id" # Add unique trace ID + ) +) +``` + + + + + + + +Portkey logs every interaction with LLMs, including: + +- Complete request and response payloads +- Latency and token usage metrics +- Cost calculations +- Tool calls and function executions + +All logs can be filtered by metadata, trace IDs, models, and more, making it easy to debug specific crew runs. + + + + + + + +Portkey provides built-in dashboards that help you: + +- Track cost and token usage across all crew runs +- Analyze performance metrics like latency and success rates +- Identify bottlenecks in your agent workflows +- Compare different crew configurations and LLMs + +You can filter and segment all metrics by custom metadata to analyze specific crew types, user groups, or use cases. + + + + + Analytics with metadata filters + + +Add custom metadata to your CrewAI LLM configuration to enable powerful filtering and segmentation: + +```python +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + metadata={ + "crew_type": "research_crew", + "environment": "production", + "_user": "user_123", # Special _user field for user analytics + "request_source": "mobile_app" + } + ) +) +``` + +This metadata can be used to filter logs, traces, and metrics on the Portkey dashboard, allowing you to analyze specific crew runs, users, or environments. + + + +### 2. Reliability - Keep Your Crews Running Smoothly + +When running crews in production, things can go wrong - API rate limits, network issues, or provider outages. Portkey's reliability features ensure your agents keep running smoothly even when problems occur. + +It's simple to enable fallback in your CrewAI setup by using a Portkey Config: + +```python +from crewai import LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Create LLM with fallback configuration +portkey_llm = LLM( + model="gpt-4o", + max_tokens=1000, + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + config={ + "strategy": { + "mode": "fallback" + }, + "targets": [ + { + "provider": "openai", + "api_key": "YOUR_OPENAI_API_KEY", + "override_params": {"model": "gpt-4o"} + }, + { + "provider": "anthropic", + "api_key": "YOUR_ANTHROPIC_API_KEY", + "override_params": {"model": "claude-3-opus-20240229"} + } + ] + } + ) +) + +# Use this LLM configuration with your agents +``` + +This configuration will automatically try Claude if the GPT-4o request fails, ensuring your crew can continue operating. + + + + Handles temporary failures automatically. If an LLM call fails, Portkey will retry the same request for the specified number of times - perfect for rate limits or network blips. + + + Prevent your agents from hanging. Set timeouts to ensure you get responses (or can fail gracefully) within your required timeframes. + + + Send different requests to different providers. Route complex reasoning to GPT-4, creative tasks to Claude, and quick responses to Gemini based on your needs. + + + Keep running even if your primary provider fails. Automatically switch to backup providers to maintain availability. + + + Spread requests across multiple API keys or providers. Great for high-volume crew operations and staying within rate limits. + + + +### 3. Prompting in CrewAI + +Portkey's Prompt Engineering Studio helps you create, manage, and optimize the prompts used in your CrewAI agents. Instead of hardcoding prompts or instructions, use Portkey's prompt rendering API to dynamically fetch and apply your versioned prompts. + + +![Prompt Playground Interface](https://raw.githubusercontent.com/siddharthsambharia-portkey/Portkey-Product-Images/refs/heads/main/CrewAI%20Portkey%20Docs.webp) + + + + +Prompt Playground is a place to compare, test and deploy perfect prompts for your AI application. It's where you experiment with different models, test variables, compare outputs, and refine your prompt engineering strategy before deploying to production. It allows you to: + +1. Iteratively develop prompts before using them in your agents +2. Test prompts with different variables and models +3. Compare outputs between different prompt versions +4. Collaborate with team members on prompt development + +This visual environment makes it easier to craft effective prompts for each step in your CrewAI agents' workflow. + + + +The Prompt Render API retrieves your prompt templates with all parameters configured: + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL, Portkey + +# Initialize Portkey admin client +portkey_admin = Portkey(api_key="YOUR_PORTKEY_API_KEY") + +# Retrieve prompt using the render API +prompt_data = portkey_client.prompts.render( + prompt_id="YOUR_PROMPT_ID", + variables={ + "agent_role": "Senior Research Scientist", + } +) + +backstory_agent_prompt=prompt_data.data.messages[0]["content"] + + +# Set up LLM with Portkey integration +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY" + ) +) + +# Create agent using the rendered prompt +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory=backstory_agent, # Use the rendered prompt + verbose=True, + llm=portkey_llm +) +``` + + + +You can: +- Create multiple versions of the same prompt +- Compare performance between versions +- Roll back to previous versions if needed +- Specify which version to use in your code: + +```python +# Use a specific prompt version +prompt_data = portkey_admin.prompts.render( + prompt_id="YOUR_PROMPT_ID@version_number", + variables={ + "agent_role": "Senior Research Scientist", + "agent_goal": "Discover groundbreaking insights" + } +) +``` + + + +Portkey prompts use Mustache-style templating for easy variable substitution: + +``` +You are a {{agent_role}} with expertise in {{domain}}. + +Your mission is to {{agent_goal}} by leveraging your knowledge +and experience in the field. + +Always maintain a {{tone}} tone and focus on providing {{focus_area}}. +``` + +When rendering, simply pass the variables: + +```python +prompt_data = portkey_admin.prompts.render( + prompt_id="YOUR_PROMPT_ID", + variables={ + "agent_role": "Senior Research Scientist", + "domain": "artificial intelligence", + "agent_goal": "discover groundbreaking insights", + "tone": "professional", + "focus_area": "practical applications" + } +) +``` + + + + + Learn more about Portkey's prompt management features + + +### 4. Guardrails for Safe Crews + +Guardrails ensure your CrewAI agents operate safely and respond appropriately in all situations. + +**Why Use Guardrails?** + +CrewAI agents can experience various failure modes: +- Generating harmful or inappropriate content +- Leaking sensitive information like PII +- Hallucinating incorrect information +- Generating outputs in incorrect formats + +Portkey's guardrails add protections for both inputs and outputs. + +**Implementing Guardrails** + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Create LLM with guardrails +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "input_guardrails": ["guardrails-id-xxx", "guardrails-id-yyy"], + "output_guardrails": ["guardrails-id-zzz"] + } + ) +) + +# Create agent with guardrailed LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +Portkey's guardrails can: +- Detect and redact PII in both inputs and outputs +- Filter harmful or inappropriate content +- Validate response formats against schemas +- Check for hallucinations against ground truth +- Apply custom business logic and rules + + + Explore Portkey's guardrail features to enhance agent safety + + +### 5. User Tracking with Metadata + +Track individual users through your CrewAI agents using Portkey's metadata system. + +**What is Metadata in Portkey?** + +Metadata allows you to associate custom data with each request, enabling filtering, segmentation, and analytics. The special `_user` field is specifically designed for user tracking. + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLM with user tracking +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + metadata={ + "_user": "user_123", # Special _user field for user analytics + "user_tier": "premium", + "user_company": "Acme Corp", + "session_id": "abc-123" + } + ) +) + +# Create agent with tracked LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +**Filter Analytics by User** + +With metadata in place, you can filter analytics by user and analyze performance metrics on a per-user basis: + + + + + +This enables: +- Per-user cost tracking and budgeting +- Personalized user analytics +- Team or organization-level metrics +- Environment-specific monitoring (staging vs. production) + + + Explore how to use custom metadata to enhance your analytics + + +### 6. Caching for Efficient Crews + +Implement caching to make your CrewAI agents more efficient and cost-effective: + + + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLM with simple caching +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "cache": { + "mode": "simple" + } + } + ) +) + +# Create agent with cached LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +Simple caching performs exact matches on input prompts, caching identical requests to avoid redundant model executions. + + + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLM with semantic caching +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "cache": { + "mode": "semantic" + } + } + ) +) + +# Create agent with semantically cached LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +Semantic caching considers the contextual similarity between input requests, caching responses for semantically similar inputs. + + + +### 7. Model Interoperability + +CrewAI supports multiple LLM providers, and Portkey extends this capability by providing access to over 200 LLMs through a unified interface. You can easily switch between different models without changing your core agent logic: + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Set up LLMs with different providers +openai_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY" + ) +) + +anthropic_llm = LLM( + model="claude-3-5-sonnet-latest", + max_tokens=1000, + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_ANTHROPIC_VIRTUAL_KEY" + ) +) + +# Choose which LLM to use for each agent based on your needs +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=openai_llm # Use anthropic_llm for Anthropic +) +``` + +Portkey provides access to LLMs from providers including: + +- OpenAI (GPT-4o, GPT-4 Turbo, etc.) +- Anthropic (Claude 3.5 Sonnet, Claude 3 Opus, etc.) +- Mistral AI (Mistral Large, Mistral Medium, etc.) +- Google Vertex AI (Gemini 1.5 Pro, etc.) +- Cohere (Command, Command-R, etc.) +- AWS Bedrock (Claude, Titan, etc.) +- Local/Private Models + + + See the full list of LLM providers supported by Portkey + + +## Set Up Enterprise Governance for CrewAI + +**Why Enterprise Governance?** +If you are using CrewAI inside your organization, you need to consider several governance aspects: +- **Cost Management**: Controlling and tracking AI spending across teams +- **Access Control**: Managing which teams can use specific models +- **Usage Analytics**: Understanding how AI is being used across the organization +- **Security & Compliance**: Maintaining enterprise security standards +- **Reliability**: Ensuring consistent service across all users + +Portkey adds a comprehensive governance layer to address these enterprise needs. Let's implement these controls step by step. + + + +Virtual Keys are Portkey's secure way to manage your LLM provider API keys. They provide essential controls like: +- Budget limits for API usage +- Rate limiting capabilities +- Secure API key storage + +To create a virtual key: +Go to [Virtual Keys](https://app.portkey.ai/virtual-keys) in the Portkey App. Save and copy the virtual key ID + + + + + + +Save your virtual key ID - you'll need it for the next step. + + + + +Configs in Portkey define how your requests are routed, with features like advanced routing, fallbacks, and retries. + +To create your config: +1. Go to [Configs](https://app.portkey.ai/configs) in Portkey dashboard +2. Create new config with: + ```json + { + "virtual_key": "YOUR_VIRTUAL_KEY_FROM_STEP1", + "override_params": { + "model": "gpt-4o" // Your preferred model name + } + } + ``` +3. Save and note the Config name for the next step + + + + + + + + +Now create a Portkey API key and attach the config you created in Step 2: + +1. Go to [API Keys](https://app.portkey.ai/api-keys) in Portkey and Create new API key +2. Select your config from `Step 2` +3. Generate and save your API key + + + + + + + + +After setting up your Portkey API key with the attached config, connect it to your CrewAI agents: + +```python +from crewai import Agent, LLM +from portkey_ai import PORTKEY_GATEWAY_URL + +# Configure LLM with your API key +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="YOUR_PORTKEY_API_KEY" +) + +# Create agent with Portkey-enabled LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + + + + + +### Step 1: Implement Budget Controls & Rate Limits + +Virtual Keys enable granular control over LLM access at the team/department level. This helps you: +- Set up [budget limits](https://portkey.ai/docs/product/ai-gateway/virtual-keys/budget-limits) +- Prevent unexpected usage spikes using Rate limits +- Track departmental spending + +#### Setting Up Department-Specific Controls: +1. Navigate to [Virtual Keys](https://app.portkey.ai/virtual-keys) in Portkey dashboard +2. Create new Virtual Key for each department with budget limits and rate limits +3. Configure department-specific limits + + + + + + + +### Step 2: Define Model Access Rules + +As your AI usage scales, controlling which teams can access specific models becomes crucial. Portkey Configs provide this control layer with features like: + +#### Access Control Features: +- **Model Restrictions**: Limit access to specific models +- **Data Protection**: Implement guardrails for sensitive data +- **Reliability Controls**: Add fallbacks and retry logic + +#### Example Configuration: +Here's a basic configuration to route requests to OpenAI, specifically using GPT-4o: + +```json +{ + "strategy": { + "mode": "single" + }, + "targets": [ + { + "virtual_key": "YOUR_OPENAI_VIRTUAL_KEY", + "override_params": { + "model": "gpt-4o" + } + } + ] +} +``` + + Create your config on the [Configs page](https://app.portkey.ai/configs) in your Portkey dashboard. + + + Configs can be updated anytime to adjust controls without affecting running applications. + + + + + ### Step 3: Implement Access Controls + + Create User-specific API keys that automatically: + - Track usage per user/team with the help of virtual keys + - Apply appropriate configs to route requests + - Collect relevant metadata to filter logs + - Enforce access permissions + + Create API keys through the [Portkey App](https://app.portkey.ai/) + + Example using Python SDK: + ```python + from portkey_ai import Portkey + + portkey = Portkey(api_key="YOUR_ADMIN_API_KEY") + + api_key = portkey.api_keys.create( + name="engineering-team", + type="organisation", + workspace_id="YOUR_WORKSPACE_ID", + defaults={ + "config_id": "your-config-id", + "metadata": { + "environment": "production", + "department": "engineering" + } + }, + scopes=["logs.view", "configs.read"] + ) + ``` + + For detailed key management instructions, see the [Portkey documentation](https://portkey.ai/docs). + + + + ### Step 4: Deploy & Monitor + After distributing API keys to your team members, your enterprise-ready CrewAI setup is ready to go. Each team member can now use their designated API keys with appropriate access levels and budget controls. + + Monitor usage in Portkey dashboard: + - Cost tracking by department + - Model usage patterns + - Request volumes + - Error rates + + + + + +### Enterprise Features Now Available +**Your CrewAI integration now has:** +- Departmental budget controls +- Model access governance +- Usage tracking & attribution +- Security guardrails +- Reliability features + + +## Frequently Asked Questions + + + + Portkey adds production-readiness to CrewAI through comprehensive observability (traces, logs, metrics), reliability features (fallbacks, retries, caching), and access to 200+ LLMs through a unified interface. This makes it easier to debug, optimize, and scale your agent applications. + + + + Yes! Portkey integrates seamlessly with existing CrewAI applications. You just need to update your LLM configuration code with the Portkey-enabled version. The rest of your agent and crew code remains unchanged. + + + + Portkey supports all CrewAI features, including agents, tools, human-in-the-loop workflows, and all task process types (sequential, hierarchical, etc.). It adds observability and reliability without limiting any of the framework's functionality. + + + + Yes, Portkey allows you to use a consistent `trace_id` across multiple agents in a crew to track the entire workflow. This is especially useful for complex crews where you want to understand the full execution path across multiple agents. + + + + Portkey allows you to add custom metadata to your LLM configuration, which you can then use for filtering. Add fields like `crew_name`, `crew_type`, or `session_id` to easily find and analyze specific crew executions. + + + + Yes! Portkey uses your own API keys for the various LLM providers. It securely stores them as virtual keys, allowing you to easily manage and rotate keys without changing your code. + + + + +## Resources + + + +

Official CrewAI documentation

+
+ +

Get personalized guidance on implementing this integration

+
+
diff --git a/docs/v1.15.13/en/observability/tracing.mdx b/docs/v1.15.13/en/observability/tracing.mdx new file mode 100644 index 0000000000..ce620946ad --- /dev/null +++ b/docs/v1.15.13/en/observability/tracing.mdx @@ -0,0 +1,214 @@ +--- +title: CrewAI Tracing +description: Built-in tracing for CrewAI Crews and Flows with the CrewAI AMP platform +icon: magnifying-glass-chart +mode: "wide" +--- + +# CrewAI Built-in Tracing + +CrewAI provides built-in tracing capabilities that allow you to monitor and debug your Crews and Flows in real-time. This guide demonstrates how to enable tracing for both **Crews** and **Flows** using CrewAI's integrated observability platform. + +> **What is CrewAI Tracing?** CrewAI's built-in tracing provides comprehensive observability for your AI agents, including agent decisions, task execution timelines, tool usage, and LLM calls - all accessible through the [CrewAI AMP platform](https://app.crewai.com). + +![CrewAI Tracing Interface](/images/crewai-tracing.png) + +## Prerequisites + +Before you can use CrewAI tracing, you need: + +1. **CrewAI AMP Account**: Sign up for a free account at [app.crewai.com](https://app.crewai.com) +2. **CLI Authentication**: Use the CrewAI CLI to authenticate your local environment + +```bash +crewai login +``` + +## Setup Instructions + +### Step 1: Create Your CrewAI AMP Account + +Visit [app.crewai.com](https://app.crewai.com) and create your free account. This will give you access to the CrewAI AMP platform where you can view traces, metrics, and manage your crews. + +### Step 2: Install CrewAI CLI and Authenticate + +If you haven't already, install CrewAI with the CLI tools: + +```bash +uv add 'crewai[tools]' +``` + +Then authenticate your CLI with your CrewAI AMP account: + +```bash +crewai login +``` + +This command will: + +1. Open your browser to the authentication page +2. Prompt you to enter a device code +3. Authenticate your local environment with your CrewAI AMP account +4. Enable tracing capabilities for your local development + +### Step 3: Enable Tracing in Your Crew + +You can enable tracing for your Crew by setting the `tracing` parameter to `True`: + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool + +# Define your agents +researcher = Agent( + role="Senior Research Analyst", + goal="Uncover cutting-edge developments in AI and data science", + backstory="""You work at a leading tech think tank. + Your expertise lies in identifying emerging trends. + You have a knack for dissecting complex data and presenting actionable insights.""", + verbose=True, + tools=[SerperDevTool()], +) + +writer = Agent( + role="Tech Content Strategist", + goal="Craft compelling content on tech advancements", + backstory="""You are a renowned Content Strategist, known for your insightful and engaging articles. + You transform complex concepts into compelling narratives.""", + verbose=True, +) + +# Create tasks for your agents +research_task = Task( + description="""Conduct a comprehensive analysis of the latest advancements in AI in 2024. + Identify key trends, breakthrough technologies, and potential industry impacts.""", + expected_output="Full analysis report in bullet points", + agent=researcher, +) + +writing_task = Task( + description="""Using the insights provided, develop an engaging blog + post that highlights the most significant AI advancements. + Your post should be informative yet accessible, catering to a tech-savvy audience.""", + expected_output="Full blog post of at least 4 paragraphs", + agent=writer, +) + +# Enable tracing in your crew +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + tracing=True, # Enable built-in tracing + verbose=True +) + +# Execute your crew +result = crew.kickoff() +``` + +### Step 4: Enable Tracing in Your Flow + +Similarly, you can enable tracing for CrewAI Flows: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + counter: int = 0 + message: str = "" + +class ExampleFlow(Flow[ExampleState]): + def __init__(self): + super().__init__(tracing=True) # Enable tracing for the flow + + @start() + def first_method(self): + print("Starting the flow") + self.state.counter = 1 + self.state.message = "Flow started" + return "continue" + + @listen("continue") + def second_method(self): + print("Continuing the flow") + self.state.counter += 1 + self.state.message = "Flow continued" + return "finish" + + @listen("finish") + def final_method(self): + print("Finishing the flow") + self.state.counter += 1 + self.state.message = "Flow completed" + +# Create and run the flow with tracing enabled +flow = ExampleFlow(tracing=True) +result = flow.kickoff() +``` + +### Step 5: View Traces in the CrewAI AMP Dashboard + +After running the crew or flow, you can view the traces generated by your CrewAI application in the CrewAI AMP dashboard. You should see detailed steps of the agent interactions, tool usages, and LLM calls. +Just click on the link below to view the traces or head over to the traces tab in the dashboard [here](https://app.crewai.com/crewai_plus/trace_batches) +![CrewAI Tracing Interface](/images/view-traces.png) + +### Alternative: Environment Variable Configuration + +You can also enable tracing globally by setting an environment variable: + +```bash +export CREWAI_TRACING_ENABLED=true +``` + +Or add it to your `.env` file: + +```env +CREWAI_TRACING_ENABLED=true +``` + +When this environment variable is set, all Crews and Flows will automatically have tracing enabled, even without explicitly setting `tracing=True`. + +## Viewing Your Traces + +### Access the CrewAI AMP Dashboard + +1. Visit [app.crewai.com](https://app.crewai.com) and log in to your account +2. Navigate to your project dashboard +3. Click on the **Traces** tab to view execution details + +### What You'll See in Traces + +CrewAI tracing provides comprehensive visibility into: + +- **Agent Decisions**: See how agents reason through tasks and make decisions +- **Task Execution Timeline**: Visual representation of task sequences and dependencies +- **Tool Usage**: Monitor which tools are called and their results +- **LLM Calls**: Track all language model interactions, including prompts and responses +- **Performance Metrics**: Execution times, token usage, and costs +- **Error Tracking**: Detailed error information and stack traces + +### Trace Features + +- **Execution Timeline**: Click through different stages of execution +- **Detailed Logs**: Access comprehensive logs for debugging +- **Performance Analytics**: Analyze execution patterns and optimize performance +- **Export Capabilities**: Download traces for further analysis + +### Authentication Issues + +If you encounter authentication problems: + +1. Ensure you're logged in: `crewai login` +2. Check your internet connection +3. Verify your account at [app.crewai.com](https://app.crewai.com) + +### Traces Not Appearing + +If traces aren't showing up in the dashboard: + +1. Confirm `tracing=True` is set in your Crew/Flow +2. Check that `CREWAI_TRACING_ENABLED=true` if using environment variables +3. Ensure you're authenticated with `crewai login` +4. Verify your crew/flow is actually executing diff --git a/docs/v1.15.13/en/observability/truefoundry.mdx b/docs/v1.15.13/en/observability/truefoundry.mdx new file mode 100644 index 0000000000..bc41cc6245 --- /dev/null +++ b/docs/v1.15.13/en/observability/truefoundry.mdx @@ -0,0 +1,147 @@ +--- +title: TrueFoundry Integration +icon: chart-line +mode: "wide" +--- + +TrueFoundry provides an enterprise-ready [AI Gateway](https://www.truefoundry.com/ai-gateway) which can integrate with agentic frameworks like CrewAI and provides governance and observability for your AI Applications. TrueFoundry AI Gateway serves as a unified interface for LLM access, providing: + +- **Unified API Access**: Connect to 250+ LLMs (OpenAI, Claude, Gemini, Groq, Mistral) through one API +- **Low Latency**: Sub-3ms internal latency with intelligent routing and load balancing +- **Enterprise Security**: SOC 2, HIPAA, GDPR compliance with RBAC and audit logging +- **Quota and cost management**: Token-based quotas, rate limiting, and comprehensive usage tracking +- **Observability**: Full request/response logging, metrics, and traces with customizable retention + +## How TrueFoundry Integrates with CrewAI + + +### Installation & Setup + + + +```bash +pip install crewai +``` + + + +1. Sign up for a [TrueFoundry account](https://www.truefoundry.com/register) +2. Follow the steps here in [Quick start](https://docs.truefoundry.com/gateway/quick-start) + + + +![TrueFoundry Code Configuration](/images/new-code-snippet.png) + +```python +from crewai import LLM + +# Create an LLM instance with TrueFoundry AI Gateway +truefoundry_llm = LLM( + model="openai-main/gpt-4o", # Similarly, you can call any model from any provider + base_url="your_truefoundry_gateway_base_url", + api_key="your_truefoundry_api_key" +) + +# Use in your CrewAI agents +from crewai import Agent + +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + llm=truefoundry_llm, + verbose=True + ) +``` + + + +### Complete CrewAI Example + +```python +from crewai import Agent, Task, Crew, LLM + +# Configure LLM with TrueFoundry +llm = LLM( + model="openai-main/gpt-4o", + base_url="your_truefoundry_gateway_base_url", + api_key="your_truefoundry_api_key" +) + +# Create agents +researcher = Agent( + role='Research Analyst', + goal='Conduct detailed market research', + backstory='Expert market analyst with attention to detail', + llm=llm, + verbose=True +) + +writer = Agent( + role='Content Writer', + goal='Create comprehensive reports', + backstory='Experienced technical writer', + llm=llm, + verbose=True +) + +# Create tasks +research_task = Task( + description='Research AI market trends for 2024', + agent=researcher, + expected_output='Comprehensive research summary' +) + +writing_task = Task( + description='Create a market research report', + agent=writer, + expected_output='Well-structured report with insights', + context=[research_task] +) + +# Create and execute crew +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True +) + +result = crew.kickoff() +``` + +### Observability and Governance + +Monitor your CrewAI agents through TrueFoundry's metrics tab: +![TrueFoundry metrics](/images/gateway-metrics.png) + +With Truefoundry's AI gateway, you can monitor and analyze: + +- **Performance Metrics**: Track key latency metrics like Request Latency, Time to First Token (TTFS), and Inter-Token Latency (ITL) with P99, P90, and P50 percentiles +- **Cost and Token Usage**: Gain visibility into your application's costs with detailed breakdowns of input/output tokens and the associated expenses for each model +- **Usage Patterns**: Understand how your application is being used with detailed analytics on user activity, model distribution, and team-based usage +- **Rate limit and Load balancing**: You can set up rate limiting, load balancing and fallback for your models + +## Tracing + +For a more detailed understanding on tracing, please see [getting-started-tracing](https://docs.truefoundry.com/docs/tracing/tracing-getting-started).For tracing, you can add the Traceloop SDK: +For tracing, you can add the Traceloop SDK: + +```bash +pip install traceloop-sdk +``` + +```python +from traceloop.sdk import Traceloop + +# Initialize enhanced tracing +Traceloop.init( + api_endpoint="https://your-truefoundry-endpoint/api/tracing", + headers={ + "Authorization": f"Bearer {your_truefoundry_pat_token}", + "TFY-Tracing-Project": "your_project_name", + }, +) +``` + +This provides additional trace correlation across your entire CrewAI workflow. +![TrueFoundry CrewAI Tracing](/images/tracing_crewai.png) \ No newline at end of file diff --git a/docs/v1.15.13/en/observability/weave.mdx b/docs/v1.15.13/en/observability/weave.mdx new file mode 100644 index 0000000000..2d4c4bf1d8 --- /dev/null +++ b/docs/v1.15.13/en/observability/weave.mdx @@ -0,0 +1,125 @@ +--- +title: Weave Integration +description: Learn how to use Weights & Biases (W&B) Weave to track, experiment with, evaluate, and improve your CrewAI applications. +icon: radar +mode: "wide" +--- + +# Weave Overview + +[Weights & Biases (W&B) Weave](https://weave-docs.wandb.ai/) is a framework for tracking, experimenting with, evaluating, deploying, and improving LLM-based applications. + +![Overview of W&B Weave CrewAI tracing usage](/images/weave-tracing.gif) + +Weave provides comprehensive support for every stage of your CrewAI application development: + +- **Tracing & Monitoring**: Automatically track LLM calls and application logic to debug and analyze production systems +- **Systematic Iteration**: Refine and iterate on prompts, datasets, and models +- **Evaluation**: Use custom or pre-built scorers to systematically assess and enhance agent performance +- **Guardrails**: Protect your agents with pre- and post-safeguards for content moderation and prompt safety + +Weave automatically captures traces for your CrewAI applications, enabling you to monitor and analyze your agents' performance, interactions, and execution flow. This helps you build better evaluation datasets and optimize your agent workflows. + +## Setup Instructions + + + + ```shell + pip install crewai weave + ``` + + + Sign up for a [Weights & Biases account](https://wandb.ai) if you haven't already. You'll need this to view your traces and metrics. + + + Add the following code to your application: + + ```python + import weave + + # Initialize Weave with your project name + weave.init(project_name="crewai_demo") + ``` + + After initialization, Weave will provide a URL where you can view your traces and metrics. + + + ```python + from crewai import Agent, Task, Crew, LLM, Process + + # Create an LLM with a temperature of 0 to ensure deterministic outputs + llm = LLM(model="gpt-4o", temperature=0) + + # Create agents + researcher = Agent( + role='Research Analyst', + goal='Find and analyze the best investment opportunities', + backstory='Expert in financial analysis and market research', + llm=llm, + verbose=True, + allow_delegation=False, + ) + + writer = Agent( + role='Report Writer', + goal='Write clear and concise investment reports', + backstory='Experienced in creating detailed financial reports', + llm=llm, + verbose=True, + allow_delegation=False, + ) + + # Create tasks + research_task = Task( + description='Deep research on the {topic}', + expected_output='Comprehensive market data including key players, market size, and growth trends.', + agent=researcher + ) + + writing_task = Task( + description='Write a detailed report based on the research', + expected_output='The report should be easy to read and understand. Use bullet points where applicable.', + agent=writer + ) + + # Create a crew + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True, + process=Process.sequential, + ) + + # Run the crew + result = crew.kickoff(inputs={"topic": "AI in material science"}) + print(result) + ``` + + + After running your CrewAI application, visit the Weave URL provided during initialization to view: + - LLM calls and their metadata + - Agent interactions and task execution flow + - Performance metrics like latency and token usage + - Any errors or issues that occurred during execution + + + Weave tracing example with CrewAI + + + + +## Features + +- Weave automatically captures all CrewAI operations: agent interactions and task executions; LLM calls with metadata and token usage; tool usage and results. +- The integration supports all CrewAI execution methods: `kickoff()`, `kickoff_for_each()`, `kickoff_async()`, and `kickoff_for_each_async()`. +- Automatic tracing of all [crewAI-tools](https://github.com/crewAIInc/crewAI-tools). +- Flow feature support with decorator patching (`@start`, `@listen`, `@router`, `@or_`, `@and_`). +- Track custom guardrails passed to CrewAI `Task` with `@weave.op()`. + +For detailed information on what's supported, visit the [Weave CrewAI documentation](https://weave-docs.wandb.ai/guides/integrations/crewai/#getting-started-with-flow). + +## Resources + +- [📘 Weave Documentation](https://weave-docs.wandb.ai) +- [📊 Example Weave x CrewAI dashboard](https://wandb.ai/ayut/crewai_demo/weave/traces?cols=%7B%22wb_run_id%22%3Afalse%2C%22attributes.weave.client_version%22%3Afalse%2C%22attributes.weave.os_name%22%3Afalse%2C%22attributes.weave.os_release%22%3Afalse%2C%22attributes.weave.os_version%22%3Afalse%2C%22attributes.weave.source%22%3Afalse%2C%22attributes.weave.sys_version%22%3Afalse%7D&peekPath=%2Fayut%2Fcrewai_demo%2Fcalls%2F0195c838-38cb-71a2-8a15-651ecddf9d89) +- [🐦 X](https://x.com/weave_wb) diff --git a/docs/v1.15.13/en/quickstart.mdx b/docs/v1.15.13/en/quickstart.mdx new file mode 100644 index 0000000000..6305f047aa --- /dev/null +++ b/docs/v1.15.13/en/quickstart.mdx @@ -0,0 +1,260 @@ +--- +title: Quickstart +description: Build your first CrewAI Flow in minutes — orchestration, state, and an agent crew that produces a real report. +icon: rocket +mode: "wide" +--- + +### Watch: Building CrewAI Agents & Flows with Coding Agent Skills + +Install our coding agent skills (Claude Code, Codex, ...) to quickly get your coding agents up and running with CrewAI. + +You can install it with `npx skills add crewaiinc/skills` + + + +In this guide you will **create a Flow** that sets a research topic, runs a **crew with one agent** (a researcher using web search), and ends with a **markdown report** on disk. Flows are the recommended way to structure production apps: they own **state** and **execution order**, while **agents** do the work inside a crew step. + +If you have not installed CrewAI yet, follow the [installation guide](/en/installation) first. + +## Prerequisites + +- Python environment and the CrewAI CLI (see [installation](/en/installation)) +- An LLM configured with the right API keys — see [LLMs](/en/concepts/llms#setting-up-your-llm) +- A [Serper.dev](https://serper.dev/) API key (`SERPER_API_KEY`) for web search in this tutorial + +## Build your first Flow + + + + From your terminal, scaffold a Flow project (the folder name uses underscores, e.g. `latest_ai_flow`): + + + ```shell Terminal + crewai create flow latest-ai-flow + cd latest_ai_flow + ``` + + + This creates a Flow app under `src/latest_ai_flow/`, including a starter crew under `crews/content_crew/` that you will replace with a minimal **single-agent** research crew in the next steps. + + + + Create `src/latest_ai_flow/crews/content_crew/agents/researcher.jsonc` (create the `agents/` directory if needed). Variables like `{topic}` are filled from `crew.kickoff(inputs=...)`. + + ```jsonc agents/researcher.jsonc + { + "role": "{topic} Senior Data Researcher", + "goal": "Uncover cutting-edge developments in {topic}", + "backstory": "You're a seasoned researcher who finds relevant information and presents it clearly.", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true + } + } + ``` + + + + + Create `src/latest_ai_flow/crews/content_crew/crew.jsonc`: + + ```jsonc crew.jsonc + { + "name": "Research Crew", + "agents": ["researcher"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research about {topic}. Use web search to find recent, credible information.", + "expected_output": "A markdown report with clear sections: key trends, notable tools or companies, and implications. Aim for 800-1200 words. No fenced code blocks around the whole document.", + "agent": "researcher", + "output_file": "output/report.md", + "markdown": true + } + ], + "process": "sequential", + "verbose": true + } + ``` + + + + + Replace the generated `content_crew.py` with a small loader that turns `crew.jsonc` into a `Crew`. + + ```python content_crew.py + # src/latest_ai_flow/crews/content_crew/content_crew.py + from pathlib import Path + + from crewai.project import load_crew + + + def kickoff_content_crew(inputs: dict): + crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc")) + return crew.kickoff(inputs={**default_inputs, **inputs}) + ``` + + + + + Connect the crew to a Flow: a `@start()` step sets the topic in **state**, and a `@listen` step runs the crew. The task’s `output_file` still writes `output/report.md`. + + ```python main.py + # src/latest_ai_flow/main.py + from pydantic import BaseModel + + from crewai.flow import Flow, listen, start + + from latest_ai_flow.crews.content_crew.content_crew import kickoff_content_crew + + + class ResearchFlowState(BaseModel): + topic: str = "" + report: str = "" + + + class LatestAiFlow(Flow[ResearchFlowState]): + @start() + def prepare_topic(self, crewai_trigger_payload: dict | None = None): + if crewai_trigger_payload: + self.state.topic = crewai_trigger_payload.get("topic", "AI Agents") + else: + self.state.topic = "AI Agents" + print(f"Topic: {self.state.topic}") + + @listen(prepare_topic) + def run_research(self): + result = kickoff_content_crew(inputs={"topic": self.state.topic}) + self.state.report = result.raw + print("Research crew finished.") + + @listen(run_research) + def summarize(self): + print("Report path: output/report.md") + + + def kickoff(): + LatestAiFlow().kickoff() + + + def plot(): + LatestAiFlow().plot() + + + if __name__ == "__main__": + kickoff() + ``` + + + If your package name differs from `latest_ai_flow`, change the `kickoff_content_crew` import to match your project’s module path. + + + + + In `.env` at the project root, set: + + - `SERPER_API_KEY` — from [Serper.dev](https://serper.dev/) + - Your model provider keys as required — see [LLM setup](/en/concepts/llms#setting-up-your-llm) + + + + + ```shell Terminal + crewai install + crewai run + ``` + + + `crewai run` executes the Flow entrypoint defined in your project (same command as for crews; project type is `"flow"` in `pyproject.toml`). + + + + + + + You should see logs from the Flow and the crew. Open **`output/report.md`** for the generated report (excerpt): + + + ```markdown output/report.md + # AI Agents: Recent Landscape and Trends + + ## Executive summary + … + + ## Key trends + - **Tool use and orchestration** — … + - **Enterprise adoption** — … + + ## Implications + … + ``` + + + Your actual file will be longer and reflect live search results. + + + +## How this run fits together + +1. **Flow** — `LatestAiFlow` runs `prepare_topic` first, then `run_research`, then `summarize`. State (`topic`, `report`) lives on the Flow. +2. **Crew** — `kickoff_content_crew` loads `crew.jsonc` and runs one task with one agent: the researcher uses **Serper** to search the web, then writes the structured report. +3. **Artifact** — The task’s `output_file` writes the report under `output/report.md`. + +To go deeper on Flow patterns (routing, persistence, human-in-the-loop), see [Build your first Flow](/en/guides/flows/first-flow) and [Flows](/en/concepts/flows). For crews without a Flow, see [Crews](/en/concepts/crews). For a single `Agent` and `kickoff()` without tasks, see [Agents](/en/concepts/agents#direct-agent-interaction-with-kickoff). + + +You now have an end-to-end Flow with an agent crew and a saved report — a solid base to add more steps, crews, or tools. + + +### Naming consistency + +The names in `crew.jsonc` must match the files and task references you use: + +- `agents: ["researcher"]` loads `agents/researcher.jsonc` +- `tasks[].agent: "researcher"` assigns the task to that agent + +## Deploying + +Push your Flow to **[CrewAI AMP](https://app.crewai.com)** once it runs locally and your project is in a **GitHub** repository. From the project root: + + +```bash Authenticate +crewai login +``` + +```bash Create deployment +crewai deploy create +``` + +```bash Check status & logs +crewai deploy status +crewai deploy logs +``` + +```bash Ship updates after you change code +crewai deploy push +``` + +```bash List or remove deployments +crewai deploy list +crewai deploy remove +``` + + + + The first deploy usually takes **around 1 minute**. Full prerequisites and the web UI flow are in [Deploy to AMP](https://docs-platform.crewai.com/platform/en/guides/deploy-to-amp). + + + + + Step-by-step AMP deployment (CLI and dashboard). + + + Discuss ideas, share projects, and connect with other CrewAI developers. + + diff --git a/docs/v1.15.13/en/skills.mdx b/docs/v1.15.13/en/skills.mdx new file mode 100644 index 0000000000..91789242d7 --- /dev/null +++ b/docs/v1.15.13/en/skills.mdx @@ -0,0 +1,50 @@ +--- +title: Skills +description: Install crewaiinc/skills from the official registry at skills.sh—Flows, Crews, and docs-aware agents for Claude Code, Cursor, Codex, and more. +icon: wand-magic-sparkles +mode: "wide" +--- + +# Skills + +**Give your AI coding agent CrewAI context in one command.** + +CrewAI **Skills** are published on **[skills.sh/crewaiinc/skills](https://skills.sh/crewaiinc/skills)**—the official registry for `crewaiinc/skills`, including individual skills (for example **design-agent**, **getting-started**, **design-task**, and **ask-docs**), install stats, and audits. They teach coding agents—like Claude Code, Cursor, and Codex—how to scaffold Flows, configure Crews, use tools, and follow CrewAI patterns. Run the install below (or paste it into your agent). + +```shell Terminal +npx skills add crewaiinc/skills +``` + +That pulls the official skill pack into your agent workflow so it can apply CrewAI conventions without you re-explaining the framework each session. Source code and issues live on [GitHub](https://github.com/crewAIInc/skills). + +## What your agent gets + +- **Flows** — structure stateful apps, steps, and crew kickoffs the CrewAI way +- **Crews & agents** — JSON-first patterns (`crew.jsonc`, `agents/*.jsonc`), roles, tasks, and delegation +- **Tools & integrations** — hook agents to search, APIs, and common CrewAI tools +- **Project layout** — align with CLI scaffolds and repo conventions +- **Up-to-date patterns** — skills track current CrewAI docs and recommended practices + +## Learn more on this site + + + + How to use `AGENTS.md` and coding-agent workflows with CrewAI. + + + Build your first Flow and crew end-to-end. + + + Install the CrewAI CLI and Python package. + + + Official listing for `crewaiinc/skills`—skills, installs, and audits. + + + Source, updates, and issues for the skill pack. + + + +### Video: CrewAI with coding agent skills + + + +### 11. API 키 + +`crewai create crew` 명령어를 실행하면, CLI에서 선택할 수 있는 LLM 제공업체 목록이 표시되고, 그 다음으로 선택한 제공업체에 대한 모델 선택이 이어집니다. 선택한 모델은 생성된 `.env`에 저장되며 각 에이전트 JSONC 파일은 자체 `llm`을 설정할 수 있습니다. + +LLM 제공업체와 모델을 선택하면, API 키를 입력하라는 메시지가 표시됩니다. + +#### 사용 가능한 LLM 공급자 + +다음은 CLI에서 제안하는 가장 인기 있는 LLM 공급자 목록입니다: + +- OpenAI +- Groq +- Anthropic +- Google Gemini +- SambaNova + +공급자를 선택하면, CLI가 해당 공급자에서 사용 가능한 모델을 보여주고 API 키 입력을 요청합니다. + +#### 기타 옵션 + +"기타"를 선택하면 LiteLLM에서 지원하는 공급자 목록에서 선택할 수 있습니다. + +공급자를 선택하면 CLI에서 Key 이름과 API 키 입력을 요청합니다. + +각 공급자의 Key 이름은 다음 링크에서 확인할 수 있습니다: + +- [LiteLLM 공급자](https://docs.litellm.ai/docs/providers) + +### 12. 구성 관리 + +CrewAI의 CLI 구성 설정을 관리합니다. + +```shell Terminal +crewai config [COMMAND] [OPTIONS] +``` + +#### 명령어: + +- `list`: 모든 CLI 구성 매개변수 표시 + +```shell Terminal +crewai config list +``` + +- `set`: CLI 구성 매개변수 설정 + +```shell Terminal +crewai config set +``` + +- `reset`: 모든 CLI 구성 매개변수를 기본값으로 초기화 + +```shell Terminal +crewai config reset +``` + +#### 사용 가능한 구성 파라미터 + +- `enterprise_base_url`: CrewAI AMP 인스턴스의 기본 URL +- `oauth2_provider`: 인증에 사용되는 OAuth2 공급자 (예: workos, okta, auth0) +- `oauth2_audience`: OAuth2 audience 값으로, 일반적으로 대상 API 또는 리소스를 식별하는 데 사용됨 +- `oauth2_client_id`: 인증 요청 시 사용되는 공급자가 발급한 OAuth2 클라이언트 ID +- `oauth2_domain`: 토큰 발급에 사용되는 OAuth2 공급자의 도메인 (예: your-org.auth0.com) + +#### 예시 + +현재 설정 표시: + +```shell Terminal +crewai config list +``` + +예시 출력: + +| 설정 | 값 | 설명 | +| :------------------ | :--------------------- | :------------------------------------------------------------------- | +| enterprise_base_url | https://app.crewai.com | CrewAI AMP 인스턴스의 기본 URL | +| org_name | Not set | 현재 활성화된 조직의 이름 | +| org_uuid | Not set | 현재 활성화된 조직의 UUID | +| oauth2_provider | workos | 인증에 사용되는 OAuth2 제공자 (예: workos, okta, auth0) | +| oauth2_audience | client_01YYY | 일반적으로 대상 API/리소스를 식별하는 데 사용되는 OAuth2 audience 값 | +| oauth2_client_id | client_01XXX | 제공자로부터 발급된 OAuth2 client ID (인증 요청 시 사용) | +| oauth2_domain | login.crewai.com | OAuth2 제공자의 도메인 (예: your-org.auth0.com) | + +엔터프라이즈 기본 URL 설정: + +```shell Terminal +crewai config set enterprise_base_url https://my-enterprise.crewai.com +``` + +OAuth2 제공자 설정: + +```shell Terminal +crewai config set oauth2_provider auth0 +``` + +OAuth2 도메인 설정: + +```shell Terminal +crewai config set oauth2_domain my-company.auth0.com +``` + +모든 설정을 기본값으로 재설정: + +```shell Terminal +crewai config reset +``` + + + 설정 값은 `~/.config/crewai/settings.json`에 저장됩니다. 조직 이름과 UUID와 + 같은 일부 설정 값은 읽기 전용이며 인증 및 조직 명령을 통해 관리됩니다. 도구 + 저장소 관련 설정은 숨겨져 있으며 사용자가 직접 설정할 수 없습니다. + diff --git a/docs/v1.15.13/ko/concepts/collaboration.mdx b/docs/v1.15.13/ko/concepts/collaboration.mdx new file mode 100644 index 0000000000..c9c11b6013 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/collaboration.mdx @@ -0,0 +1,363 @@ +--- +title: 협업 +description: CrewAI 팀 내에서 에이전트가 함께 작업하고, 작업을 위임하며, 효과적으로 소통하는 방법에 대해 설명합니다. +icon: screen-users +mode: "wide" +--- + +## 개요 + +CrewAI에서의 협업은 에이전트들이 팀으로서 함께 작업하며, 각자의 전문성을 활용하기 위해 작업을 위임하고 질문을 주고받을 수 있도록 합니다. `allow_delegation=True`로 설정하면, 에이전트들은 자동으로 강력한 협업 도구에 접근할 수 있습니다. + +## 빠른 시작: 협업 활성화 + +```python +from crewai import Agent, Crew, Task + +# Enable collaboration for agents +researcher = Agent( + role="Research Specialist", + goal="Conduct thorough research on any topic", + backstory="Expert researcher with access to various sources", + allow_delegation=True, # 🔑 Key setting for collaboration + verbose=True +) + +writer = Agent( + role="Content Writer", + goal="Create engaging content based on research", + backstory="Skilled writer who transforms research into compelling content", + allow_delegation=True, # 🔑 Enables asking questions to other agents + verbose=True +) + +# Agents can now collaborate automatically +crew = Crew( + agents=[researcher, writer], + tasks=[...], + verbose=True +) +``` + +## 에이전트 협업 방식 + +`allow_delegation=True`로 설정하면, CrewAI는 에이전트에게 두 가지 강력한 도구를 자동으로 제공합니다. + +### 1. **업무 위임 도구** +에이전트가 특정 전문성을 가진 팀원에게 작업을 할당할 수 있습니다. + +```python +# Agent automatically gets this tool: +# Delegate work to coworker(task: str, context: str, coworker: str) +``` + +### 2. **질문하기 도구** +에이전트가 동료로부터 정보를 수집하기 위해 특정 질문을 할 수 있게 해줍니다. + +```python +# Agent automatically gets this tool: +# Ask question to coworker(question: str, context: str, coworker: str) +``` + +## 협업의 실제 + +아래는 에이전트들이 콘텐츠 제작 작업에 협력하는 완성된 예시입니다: + +```python +from crewai import Agent, Crew, Task, Process + +# Create collaborative agents +researcher = Agent( + role="Research Specialist", + goal="Find accurate, up-to-date information on any topic", + backstory="""You're a meticulous researcher with expertise in finding + reliable sources and fact-checking information across various domains.""", + allow_delegation=True, + verbose=True +) + +writer = Agent( + role="Content Writer", + goal="Create engaging, well-structured content", + backstory="""You're a skilled content writer who excels at transforming + research into compelling, readable content for different audiences.""", + allow_delegation=True, + verbose=True +) + +editor = Agent( + role="Content Editor", + goal="Ensure content quality and consistency", + backstory="""You're an experienced editor with an eye for detail, + ensuring content meets high standards for clarity and accuracy.""", + allow_delegation=True, + verbose=True +) + +# Create a task that encourages collaboration +article_task = Task( + description="""Write a comprehensive 1000-word article about 'The Future of AI in Healthcare'. + + The article should include: + - Current AI applications in healthcare + - Emerging trends and technologies + - Potential challenges and ethical considerations + - Expert predictions for the next 5 years + + Collaborate with your teammates to ensure accuracy and quality.""", + expected_output="A well-researched, engaging 1000-word article with proper structure and citations", + agent=writer # Writer leads, but can delegate research to researcher +) + +# Create collaborative crew +crew = Crew( + agents=[researcher, writer, editor], + tasks=[article_task], + process=Process.sequential, + verbose=True +) + +result = crew.kickoff() +``` + +## 협업 패턴 + +### 패턴 1: 조사 → 작성 → 편집 +```python +research_task = Task( + description="Research the latest developments in quantum computing", + expected_output="Comprehensive research summary with key findings and sources", + agent=researcher +) + +writing_task = Task( + description="Write an article based on the research findings", + expected_output="Engaging 800-word article about quantum computing", + agent=writer, + context=[research_task] # Gets research output as context +) + +editing_task = Task( + description="Edit and polish the article for publication", + expected_output="Publication-ready article with improved clarity and flow", + agent=editor, + context=[writing_task] # Gets article draft as context +) +``` + +### 패턴 2: 협업 단일 작업 +```python +collaborative_task = Task( + description="""Create a marketing strategy for a new AI product. + + Writer: Focus on messaging and content strategy + Researcher: Provide market analysis and competitor insights + + Work together to create a comprehensive strategy.""", + expected_output="Complete marketing strategy with research backing", + agent=writer # Lead agent, but can delegate to researcher +) +``` + +## 계층적 협업 + +복잡한 프로젝트의 경우, 매니저 에이전트를 활용하여 계층적 프로세스를 사용하세요: + +```python +from crewai import Agent, Crew, Task, Process + +# Manager agent coordinates the team +manager = Agent( + role="Project Manager", + goal="Coordinate team efforts and ensure project success", + backstory="Experienced project manager skilled at delegation and quality control", + allow_delegation=True, + verbose=True +) + +# Specialist agents +researcher = Agent( + role="Researcher", + goal="Provide accurate research and analysis", + backstory="Expert researcher with deep analytical skills", + allow_delegation=False, # Specialists focus on their expertise + verbose=True +) + +writer = Agent( + role="Writer", + goal="Create compelling content", + backstory="Skilled writer who creates engaging content", + allow_delegation=False, + verbose=True +) + +# Manager-led task +project_task = Task( + description="Create a comprehensive market analysis report with recommendations", + expected_output="Executive summary, detailed analysis, and strategic recommendations", + agent=manager # Manager will delegate to specialists +) + +# Hierarchical crew +crew = Crew( + agents=[manager, researcher, writer], + tasks=[project_task], + process=Process.hierarchical, # Manager coordinates everything + manager_llm="gpt-4o", # Specify LLM for manager + verbose=True +) +``` + +## 협업을 위한 모범 사례 + +### 1. **명확한 역할 정의** +```python +# ✅ Good: Specific, complementary roles +researcher = Agent(role="Market Research Analyst", ...) +writer = Agent(role="Technical Content Writer", ...) + +# ❌ Avoid: Overlapping or vague roles +agent1 = Agent(role="General Assistant", ...) +agent2 = Agent(role="Helper", ...) +``` + +### 2. **전략적 위임 활성화** +```python +# ✅ Enable delegation for coordinators and generalists +lead_agent = Agent( + role="Content Lead", + allow_delegation=True, # Can delegate to specialists + ... +) + +# ✅ Disable for focused specialists (optional) +specialist_agent = Agent( + role="Data Analyst", + allow_delegation=False, # Focuses on core expertise + ... +) +``` + +### 3. **컨텍스트 공유** +```python +# ✅ Use context parameter for task dependencies +writing_task = Task( + description="Write article based on research", + agent=writer, + context=[research_task], # Shares research results + ... +) +``` + +### 4. **명확한 작업 설명** +```python +# ✅ 구체적이고 실행 가능한 설명 +Task( + description="""Research competitors in the AI chatbot space. + Focus on: pricing models, key features, target markets. + Provide data in a structured format.""", + ... +) + +# ❌ 협업에 도움이 되지 않는 모호한 설명 +Task(description="Do some research about chatbots", ...) +``` + +## 협업 문제 해결 + +### 문제: 에이전트들이 협업하지 않음 +**증상:** 에이전트들이 각자 작업하며, 위임이 이루어지지 않음 +```python +# ✅ Solution: Ensure delegation is enabled +agent = Agent( + role="...", + allow_delegation=True, # This is required! + ... +) +``` + +### 문제: 지나친 이중 확인 +**증상:** 에이전트가 과도하게 질문을 하여 진행이 느려짐 +```python +# ✅ Solution: Provide better context and specific roles +Task( + description="""Write a technical blog post about machine learning. + + Context: Target audience is software developers with basic ML knowledge. + Length: 1200 words + Include: code examples, practical applications, best practices + + If you need specific technical details, delegate research to the researcher.""", + ... +) +``` + +### 문제: 위임 루프 +**증상:** 에이전트들이 무한히 서로에게 위임함 +```python +# ✅ Solution: Clear hierarchy and responsibilities +manager = Agent(role="Manager", allow_delegation=True) +specialist1 = Agent(role="Specialist A", allow_delegation=False) # No re-delegation +specialist2 = Agent(role="Specialist B", allow_delegation=False) +``` + +## 고급 협업 기능 + +### 맞춤 협업 규칙 +```python +# Set specific collaboration guidelines in agent backstory +agent = Agent( + role="Senior Developer", + backstory="""You lead development projects and coordinate with team members. + + Collaboration guidelines: + - Delegate research tasks to the Research Analyst + - Ask the Designer for UI/UX guidance + - Consult the QA Engineer for testing strategies + - Only escalate blocking issues to the Project Manager""", + allow_delegation=True +) +``` + +### 협업 모니터링 +```python +def track_collaboration(output): + """Track collaboration patterns""" + if "Delegate work to coworker" in output.raw: + print("🤝 Delegation occurred") + if "Ask question to coworker" in output.raw: + print("❓ Question asked") + +crew = Crew( + agents=[...], + tasks=[...], + step_callback=track_collaboration, # Monitor collaboration + verbose=True +) +``` + +## 메모리와 학습 + +에이전트가 과거 협업을 기억할 수 있도록 합니다: + +```python +agent = Agent( + role="Content Lead", + memory=True, # Remembers past interactions + allow_delegation=True, + verbose=True +) +``` + +메모리가 활성화되면, 에이전트는 이전 협업에서 학습하여 시간이 지남에 따라 더 나은 위임 결정을 내릴 수 있습니다. + +## 다음 단계 + +- **예제 시도하기**: 기본 협업 예제부터 시작하세요 +- **역할 실험하기**: 다양한 에이전트 역할 조합을 테스트해 보세요 +- **상호작용 모니터링**: 협업 과정을 직접 보려면 `verbose=True`를 사용하세요 +- **작업 설명 최적화**: 명확한 작업이 더 나은 협업으로 이어집니다 +- **확장하기**: 복잡한 프로젝트에는 계층적 프로세스를 시도해 보세요 + +협업은 개별 AI 에이전트를 복잡하고 다면적인 문제를 함께 해결할 수 있는 강력한 팀으로 변화시킵니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/concepts/crews.mdx b/docs/v1.15.13/ko/concepts/crews.mdx new file mode 100644 index 0000000000..d62f762435 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/crews.mdx @@ -0,0 +1,462 @@ +--- +title: 크루 +description: crewAI 프레임워크에서 크루를 이해하고 다양한 속성과 기능을 활용하기. +icon: people-group +mode: "wide" +--- + +## 개요 + +crewAI에서 crew는 일련의 작업을 달성하기 위해 함께 협력하는 에이전트들의 그룹을 나타냅니다. 각 crew는 작업 실행, 에이전트 간 협업, 그리고 전체 워크플로우에 대한 전략을 정의합니다. + +## Crew 속성 + +| 속성 | 파라미터 | 설명 | +| :-------------------------------------- | :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Tasks** | `tasks` | crew에 할당된 작업들의 리스트. | +| **Agents** | `agents` | crew의 일원이 되는 에이전트들의 리스트. | +| **Process** _(선택사항)_ | `process` | crew가 따르는 프로세스 플로우(예: 순차, 계층적). 기본값은 `sequential`. | +| **Verbose** _(선택사항)_ | `verbose` | 실행 중 로그의 상세도 설정. 기본값은 `False`. | +| **Manager LLM** _(선택사항)_ | `manager_llm` | 계층적 프로세스에서 매니저 에이전트가 사용하는 언어 모델. **계층적 프로세스를 사용할 때 필수.** | +| **Function Calling LLM** _(선택사항)_ | `function_calling_llm` | 전달 시, crew 전체의 모든 agent에 대해 도구의 function calling에 이 LLM을 사용. 각 agent마다 개별 LLM을 가질 수 있으며, 이 경우 crew의 function calling LLM을 오버라이드 함. | +| **Config** _(선택사항)_ | `config` | crew용으로 선택적인 구성 설정. `Json` 또는 `Dict[str, Any]` 형식 사용. | +| **Max RPM** _(선택사항)_ | `max_rpm` | 실행 중 crew가 준수하는 분당 최대 요청 수. 기본값은 `None`. | +| **Memory** _(선택사항)_ | `memory` | 실행 메모리(단기, 장기, 엔터티 메모리) 저장에 사용됨. | +| **Cache** _(선택사항)_ | `cache` | 도구 실행 결과를 캐시에 저장할지 여부. 기본값은 `True`. | +| **Embedder** _(선택사항)_ | `embedder` | crew에서 사용할 embedder 설정. 현재는 주로 메모리에서 사용. 기본값은 `{"provider": "openai"}`. | +| **Step Callback** _(선택사항)_ | `step_callback` | 각 agent의 단계가 끝난 후 호출되는 함수. agent의 작업 기록이나 기타 작업 수행에 사용 가능; agent별 `step_callback`을 오버라이드하지 않음. | +| **Task Callback** _(선택사항)_ | `task_callback` | 각 작업 완료 후 호출되는 함수. 작업 실행 후 모니터링이나 추가 작업에 유용. | +| **Share Crew** _(선택사항)_ | `share_crew` | 라이브러리 개선 및 모델 학습을 위해 crew 정보와 실행을 crewAI 팀에 공유할지 여부. | +| **Output Log File** _(선택사항)_ | `output_log_file` | `True`로 설정 시 로그를 현재 디렉터리에 logs.txt로 저장하거나 파일 경로 지정 가능. 파일명이 .json으로 끝나면 JSON 형식, 아니면 txt 형식으로 로그를 저장. 기본값은 `None`. | +| **Manager Agent** _(선택사항)_ | `manager_agent` | 매니저로 사용할 커스텀 agent를 설정. | +| **Prompt File** _(선택사항)_ | `prompt_file` | crew에서 사용할 prompt JSON 파일 경로. | +| **Planning** *(선택사항)* | `planning` | Crew에 계획 수립 기능을 추가. 활성화하면 각 Crew 반복 전에 모든 Crew 데이터를 AgentPlanner로 전송하여 작업계획을 세우고, 이 계획이 각 작업 설명에 추가됨. | +| **Planning LLM** *(선택사항)* | `planning_llm` | 계획 과정에서 AgentPlanner가 사용하는 언어 모델. | +| **Knowledge Sources** _(선택사항)_ | `knowledge_sources` | crew 수준에서 사용 가능한 지식 소스. 모든 agent가 접근 가능. | +| **Stream** _(선택사항)_ | `stream` | 스트리밍 출력을 활성화하여 crew 실행 중 실시간 업데이트를 받을 수 있습니다. 청크를 반복할 수 있는 `CrewStreamingOutput` 객체를 반환합니다. 기본값은 `False`. | + + +**Crew Max RPM**: `max_rpm` 속성은 crew가 분당 처리할 수 있는 최대 요청 수를 설정하며, 개별 agent의 `max_rpm` 설정을 crew 단위로 지정할 경우 오버라이드합니다. + + +## 크루 생성하기 + +CrewAI에서 크루를 생성하는 주요 방법은 **JSONC 구성(새 crew 권장)**을 사용하는 방법과 클래식 프로젝트나 고급 사용 사례에서 **코드로 직접 정의**하는 방법입니다. + +### JSONC 구성 (권장) + +`crewai create crew `으로 만든 새 프로젝트는 crew 수준 설정과 태스크를 `crew.jsonc`에 두고, 각 에이전트를 `agents/`의 별도 파일에 둡니다. `crewai run`은 `crew.jsonc` 또는 `crew.json`을 감지해 에이전트를 로드하고, 빠진 placeholder 값을 물은 뒤 crew를 시작합니다. + +```jsonc crew.jsonc +{ + "name": "Market Research Crew", + "agents": ["researcher", "analyst"], + "tasks": [ + { + "name": "research", + "description": "Research {topic} and collect the most relevant facts.", + "expected_output": "Structured research notes about {topic}.", + "agent": "researcher" + }, + { + "name": "analysis", + "description": "Analyze the research and write a concise report.", + "expected_output": "A markdown report with findings and recommendations.", + "agent": "analyst", + "context": ["research"], + "output_file": "output/report.md" + } + ], + "process": "sequential", + "verbose": true, + "memory": true, + "inputs": { + "topic": "AI Agents" + } +} +``` + +`agents`의 각 문자열은 먼저 `agents/.jsonc`, 그 다음 `agents/.json`으로 해석됩니다. 계층형 crew는 `"process": "hierarchical"`와 `manager_llm` 또는 `manager_agent`를 사용하세요. + + +신뢰하는 출처의 JSON crew 프로젝트만 실행하세요. `custom:` 도구와 `{"python": "module.attribute"}` 참조는 crew 로드 시 로컬 Python 코드를 실행합니다. + + +### 클래식 YAML 구성 + +`crewai create crew --classic`으로 만든 클래식 프로젝트는 `crew.py`, `config/agents.yaml`, `config/tasks.yaml`, `@CrewBase`, `@agent`, `@task`, `@crew` 데코레이터를 사용합니다. + +이 방식은 기존 Python/YAML 프로젝트와 Python 데코레이터 제어가 필요한 팀을 위해 계속 지원됩니다. + +클래식 프로젝트를 만든 후, `CrewBase`를 상속받는 클래스에서 데코레이터를 이용해 agent, task, 그리고 crew 자체를 정의할 수 있습니다. + +#### 데코레이터가 적용된 예시 Crew 클래스 + +```python code +from crewai import Agent, Crew, Task, Process +from crewai.project import CrewBase, agent, task, crew, before_kickoff, after_kickoff +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List + +@CrewBase +class YourCrewName: + """Description of your crew""" + + agents: List[BaseAgent] + tasks: List[Task] + + # YAML 구성 파일 경로 + # YAML로 정의된 에이전트와 태스크의 예시는 아래 링크를 참고하세요: + # - Task: https://docs.crewai.com/concepts/tasks#yaml-configuration-recommended + # - Agents: https://docs.crewai.com/concepts/agents#yaml-configuration-recommended + agents_config = 'config/agents.yaml' + tasks_config = 'config/tasks.yaml' + + @before_kickoff + def prepare_inputs(self, inputs): + # crew 시작 전에 입력값을 수정합니다 + inputs['additional_data'] = "Some extra information" + return inputs + + @after_kickoff + def process_output(self, output): + # crew가 종료된 후 출력값을 수정합니다 + output.raw += "\nProcessed after kickoff." + return output + + @agent + def agent_one(self) -> Agent: + return Agent( + config=self.agents_config['agent_one'], # type: ignore[index] + verbose=True + ) + + @agent + def agent_two(self) -> Agent: + return Agent( + config=self.agents_config['agent_two'], # type: ignore[index] + verbose=True + ) + + @task + def task_one(self) -> Task: + return Task( + config=self.tasks_config['task_one'] # type: ignore[index] + ) + + @task + def task_two(self) -> Task: + return Task( + config=self.tasks_config['task_two'] # type: ignore[index] + ) + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, # @agent 데코레이터로 자동 수집 + tasks=self.tasks, # @task 데코레이터로 자동 수집 + process=Process.sequential, + verbose=True, + ) +``` + +위 코드를 실행하는 방법: + +```python code +YourCrewName().crew().kickoff(inputs={"any": "input here"}) +``` + + +태스크들은 정의된 순서대로 실행됩니다. + + +`CrewBase` 클래스와 이 데코레이터들은 에이전트와 태스크의 수집을 자동화하여 +수동으로 관리할 필요를 줄여줍니다. + +#### `annotations.py`의 데코레이터 개요 + +CrewAI는 `annotations.py` 파일에서 크루 클래스 내의 메서드를 특별히 처리하기 위해 사용하는 여러 데코레이터를 제공합니다: + +- `@CrewBase`: 클래스를 크루 기본 클래스로 표시합니다. +- `@agent`: `Agent` 객체를 반환하는 메서드임을 나타냅니다. +- `@task`: `Task` 객체를 반환하는 메서드임을 나타냅니다. +- `@crew`: `Crew` 객체를 반환하는 메서드임을 나타냅니다. +- `@before_kickoff`: (옵션) 크루가 시작되기 전에 실행될 메서드를 표시합니다. +- `@after_kickoff`: (옵션) 크루가 종료된 후에 실행될 메서드를 표시합니다. + +이러한 데코레이터들은 크루의 구조를 구성하는 데 도움이 되며, 에이전트와 태스크를 수동으로 나열하지 않아도 자동으로 수집할 수 있도록 해줍니다. + +### 직접 코드 정의 (대안) + +또는 YAML 구성 파일을 사용하지 않고 코드에서 직접 crew를 정의할 수 있습니다. + +```python code +from crewai import Agent, Crew, Task, Process +from crewai_tools import YourCustomTool + +class YourCrewName: + def agent_one(self) -> Agent: + return Agent( + role="Data Analyst", + goal="Analyze data trends in the market", + backstory="An experienced data analyst with a background in economics", + verbose=True, + tools=[YourCustomTool()] + ) + + def agent_two(self) -> Agent: + return Agent( + role="Market Researcher", + goal="Gather information on market dynamics", + backstory="A diligent researcher with a keen eye for detail", + verbose=True + ) + + def task_one(self) -> Task: + return Task( + description="Collect recent market data and identify trends.", + expected_output="A report summarizing key trends in the market.", + agent=self.agent_one() + ) + + def task_two(self) -> Task: + return Task( + description="Research factors affecting market dynamics.", + expected_output="An analysis of factors influencing the market.", + agent=self.agent_two() + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.agent_one(), self.agent_two()], + tasks=[self.task_one(), self.task_two()], + process=Process.sequential, + verbose=True + ) +``` + +위 코드를 실행하는 방법: + +```python code +YourCrewName().crew().kickoff(inputs={}) +``` + +이 예시에서: + +- 에이전트와 태스크는 데코레이터 없이 클래스 내에서 직접 정의됩니다. +- 에이전트와 태스크 목록을 수동으로 생성하고 관리합니다. +- 이 방식은 더 많은 제어를 제공하지만, 대규모 프로젝트의 경우 유지보수가 어려울 수 있습니다. + +## Crew Output + +CrewAI 프레임워크에서 crew의 출력은 `CrewOutput` 클래스 내에 캡슐화되어 있습니다. +이 클래스는 crew 실행 결과를 구조화된 방식으로 접근할 수 있도록 하며, 원시 문자열, JSON, Pydantic 모델과 같은 다양한 형식을 포함합니다. +`CrewOutput`에는 최종 task 출력 결과, 토큰 사용량, 그리고 개별 task 출력 결과가 포함됩니다. + +### Crew 출력 속성 + +| 속성 | 매개변수 | 타입 | 설명 | +| :--------------- | :--------------- | :--------------------------- | :----------------------------------------------------------------------------------------- | +| **Raw** | `raw` | `str` | crew의 원시 출력값입니다. 출력의 기본 형식입니다. | +| **Pydantic** | `pydantic` | `Optional[BaseModel]` | crew의 구조화된 출력을 나타내는 Pydantic 모델 객체입니다. | +| **JSON Dict** | `json_dict` | `Optional[Dict[str, Any]]` | crew의 JSON 출력을 나타내는 딕셔너리입니다. | +| **Tasks Output** | `tasks_output` | `List[TaskOutput]` | crew 내 각 작업의 출력을 나타내는 `TaskOutput` 객체의 리스트입니다. | +| **Token Usage** | `token_usage` | `Dict[str, Any]` | 실행 중 언어 모델의 성능에 대한 통찰을 제공하는 토큰 사용 요약 정보입니다. | + +### Crew 출력 메서드 및 속성 + +| 메서드/속성 | 설명 | +| :-------------- | :------------------------------------------------------------------------------------------------ | +| **json** | 출력 형식이 JSON인 경우 crew 출력의 JSON 문자열 표현을 반환합니다. | +| **to_dict** | JSON 및 Pydantic 출력을 사전으로 변환합니다. | +| \***\*str\*\*** | crew 출력의 문자열 표현을 반환합니다. 우선순위는 Pydantic, 그 다음 JSON, 마지막으로 raw입니다. | + +### Crew 출력 접근하기 + +crew가 실행된 후에는 `Crew` 객체의 `output` 속성을 통해 출력값에 접근할 수 있습니다. `CrewOutput` 클래스는 이 출력값을 다루고 표시하는 다양한 방법을 제공합니다. + +#### 예시 + +```python Code +# Example crew execution +crew = Crew( + agents=[research_agent, writer_agent], + tasks=[research_task, write_article_task], + verbose=True +) + +crew_output = crew.kickoff() + +# Accessing the crew output +print(f"Raw Output: {crew_output.raw}") +if crew_output.json_dict: + print(f"JSON Output: {json.dumps(crew_output.json_dict, indent=2)}") +if crew_output.pydantic: + print(f"Pydantic Output: {crew_output.pydantic}") +print(f"Tasks Output: {crew_output.tasks_output}") +print(f"Token Usage: {crew_output.token_usage}") +``` + +## 크루 로그 접근하기 + +`output_log_file`을 `True(Boolean)` 또는 `file_name(str)`로 설정하면 크루 실행의 실시간 로그를 볼 수 있습니다. 이벤트 로그는 `file_name.txt`와 `file_name.json` 두 가지 형식 모두를 지원합니다. +`True(Boolean)`로 설정할 경우에는 `logs.txt`로 저장됩니다. + +`output_log_file`이 `False(Boolean)` 또는 `None`으로 설정된 경우에는 로그가 저장되지 않습니다. + +```python Code +# 크루 로그 저장하기 +crew = Crew(output_log_file = True) # 로그는 logs.txt로 저장됩니다 +crew = Crew(output_log_file = file_name) # 로그는 file_name.txt로 저장됩니다 +crew = Crew(output_log_file = file_name.txt) # 로그는 file_name.txt로 저장됩니다 +crew = Crew(output_log_file = file_name.json) # 로그는 file_name.json으로 저장됩니다 +``` + +## 메모리 활용 + +crew는 메모리(단기, 장기 및 엔티티 메모리)를 활용하여 시간이 지남에 따라 실행 및 학습을 향상시킬 수 있습니다. 이 기능을 통해 crew는 실행 메모리를 저장하고 회상할 수 있어, 의사결정 및 작업 실행 전략에 도움이 됩니다. + +## 캐시 활용 + +캐시는 도구 실행 결과를 저장하는 데 사용될 수 있으며, 동일한 작업을 반복 실행할 필요를 줄여 프로세스의 효율성을 높입니다. + +## Crew 사용 메트릭 + +crew 실행 후, `usage_metrics` 속성에 접근하여 crew가 실행한 모든 작업에 대한 언어 모델(LLM) 사용 메트릭을 확인할 수 있습니다. 이를 통해 운영 효율성과 개선이 필요한 영역에 대한 인사이트를 얻을 수 있습니다. + +`total_tokens`는 청구된 총합(`prompt_tokens + completion_tokens`)입니다. `cached_prompt_tokens` 및 `cache_creation_tokens`와 같은 breakdown 필드는 이미 해당 총합에 포함된 부분 집합을 설명하며 `total_tokens` 위에 다시 더하지 않습니다. 전체 계약은 Flows 개념 문서의 **UsageMetrics field semantics** 섹션을 참조하세요. + +```python Code +# Access the crew's usage metrics +crew = Crew(agents=[agent1, agent2], tasks=[task1, task2]) +crew.kickoff() +print(crew.usage_metrics) +``` + +## Crew 실행 프로세스 + +- **순차적 프로세스**: 작업이 하나씩 차례로 실행되어 linear flow의 작업 흐름을 제공합니다. +- **계층적 프로세스**: 매니저 agent가 crew를 조정하여 작업을 위임하고 결과를 검증한 후 다음 단계로 이동합니다. **참고**: 이 프로세스에는 `manager_llm` 또는 `manager_agent`가 필요하며, 프로세스 flow 검증을 위해 필수적입니다. + +### 크루 시작하기 + +크루가 구성되면, `kickoff()` 메서드를 사용하여 워크플로를 시작하세요. 이렇게 하면 정의된 프로세스 플로우에 따라 실행 과정이 시작됩니다. + +```python Code +# Start the crew's task execution +result = my_crew.kickoff() +print(result) +``` + +### Crew를 시작하는 다양한 방법 + +crew가 구성되면, 적절한 시작 방법으로 workflow를 시작하세요. CrewAI는 kickoff 프로세스를 더 잘 제어할 수 있도록 여러 방법을 제공합니다. + +#### 동기 메서드 + +- `kickoff()`: 정의된 process flow에 따라 실행 프로세스를 시작합니다. +- `kickoff_for_each()`: 입력 이벤트나 컬렉션 내 각 항목에 대해 순차적으로 task를 실행합니다. + +#### 비동기 메서드 + +CrewAI는 비동기 실행을 위해 두 가지 접근 방식을 제공합니다: + +| 메서드 | 타입 | 설명 | +|--------|------|-------------| +| `akickoff()` | 네이티브 async | 전체 실행 체인에서 진정한 async/await 사용 | +| `akickoff_for_each()` | 네이티브 async | 리스트의 각 입력에 대해 네이티브 async 실행 | +| `kickoff_async()` | 스레드 기반 | 동기 실행을 `asyncio.to_thread`로 래핑 | +| `kickoff_for_each_async()` | 스레드 기반 | 리스트의 각 입력에 대해 스레드 기반 async | + + +고동시성 워크로드의 경우 `akickoff()` 및 `akickoff_for_each()`가 권장됩니다. 이들은 작업 실행, 메모리 작업, 지식 검색에 네이티브 async를 사용합니다. + + +```python Code +# Start the crew's task execution +result = my_crew.kickoff() +print(result) + +# Example of using kickoff_for_each +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +results = my_crew.kickoff_for_each(inputs=inputs_array) +for result in results: + print(result) + +# Example of using native async with akickoff +inputs = {'topic': 'AI in healthcare'} +async_result = await my_crew.akickoff(inputs=inputs) +print(async_result) + +# Example of using native async with akickoff_for_each +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +async_results = await my_crew.akickoff_for_each(inputs=inputs_array) +for async_result in async_results: + print(async_result) + +# Example of using thread-based kickoff_async +inputs = {'topic': 'AI in healthcare'} +async_result = await my_crew.kickoff_async(inputs=inputs) +print(async_result) + +# Example of using thread-based kickoff_for_each_async +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +async_results = await my_crew.kickoff_for_each_async(inputs=inputs_array) +for async_result in async_results: + print(async_result) +``` + +이러한 메서드는 crew 내에서 task를 관리하고 실행하는 데 유연성을 제공하며, 동기 및 비동기 workflow 모두 필요에 맞게 사용할 수 있도록 지원합니다. 자세한 비동기 예제는 [Crew 비동기 시작](/ko/learn/kickoff-async) 가이드를 참조하세요. + +### 스트리밍 Crew 실행 + +crew 실행을 실시간으로 확인하려면 스트리밍을 활성화하여 출력이 생성되는 대로 받을 수 있습니다: + +```python Code +# 스트리밍 활성화 +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True +) + +# 스트리밍 출력을 반복 +streaming = crew.kickoff(inputs={"topic": "AI"}) +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# 최종 결과 접근 +result = streaming.result +``` + +스트리밍에 대한 자세한 내용은 [스트리밍 Crew 실행](/ko/learn/streaming-crew-execution) 가이드를 참조하세요. + +### 특정 Task에서 다시 실행하기 + +이제 CLI 명령어 `replay`를 사용하여 특정 task에서 다시 실행할 수 있습니다. + +CrewAI의 replay 기능을 사용하면 커맨드라인 인터페이스(CLI)를 통해 특정 task에서 다시 실행할 수 있습니다. `crewai replay -t ` 명령어를 실행하면 replay 과정에서 사용할 `task_id`를 지정할 수 있습니다. + +Kickoff은 이제 최신 kickoff에서 반환된 task output을 로컬에 저장하므로, 해당 지점부터 다시 실행할 수 있습니다. + +### CLI를 사용하여 특정 작업에서 다시 실행하기 + +replay 기능을 사용하려면 다음 단계를 따라주세요: + +1. 터미널 또는 명령 프롬프트를 엽니다. +2. CrewAI 프로젝트가 위치한 디렉터리로 이동합니다. +3. 아래 명령어를 실행합니다: + +최신 kickoff 작업 ID를 확인하려면 다음을 사용하세요: + +```shell +crewai log-tasks-outputs +``` + +그런 다음, 특정 작업에서 다시 실행하려면 다음을 사용하세요: + +```shell +crewai replay -t +``` + +이 명령어들을 사용하면 이전에 실행된 작업의 컨텍스트를 유지하면서 최신 kickoff 작업부터 다시 실행할 수 있습니다. diff --git a/docs/v1.15.13/ko/concepts/event-listener.mdx b/docs/v1.15.13/ko/concepts/event-listener.mdx new file mode 100644 index 0000000000..aec99523ca --- /dev/null +++ b/docs/v1.15.13/ko/concepts/event-listener.mdx @@ -0,0 +1,415 @@ +--- +title: '이벤트 리스너' +description: 'CrewAI 이벤트에 연결하여 맞춤형 통합 및 모니터링 구축' +icon: spinner +mode: "wide" +--- + +## 개요 + +CrewAI는 강력한 이벤트 시스템을 제공하여 crew 실행 중 발생하는 다양한 이벤트를 수신하고 이에 반응할 수 있도록 합니다. 이 기능을 통해 맞춤형 통합, 모니터링 솔루션, 로깅 시스템 또는 CrewAI의 내부 이벤트에 따라 트리거되어야 하는 기타 모든 기능을 구축할 수 있습니다. + +## 작동 방식 + +CrewAI는 실행 수명 주기 전반에 걸쳐 이벤트를 발생시키는 이벤트 버스 아키텍처를 사용합니다. 이벤트 시스템은 다음과 같은 구성 요소로 구축되어 있습니다: + +1. **CrewAIEventsBus**: 이벤트 등록 및 발생을 관리하는 싱글톤 이벤트 버스 +2. **BaseEvent**: 시스템 내 모든 이벤트의 기본 클래스 +3. **BaseEventListener**: 커스텀 이벤트 리스너 생성을 위한 추상 기본 클래스 + +CrewAI에서 특정 동작(예: Crew가 실행을 시작하거나 Agent가 task를 완료하거나 tool이 사용될 때)이 발생하면, 시스템은 해당 이벤트를 발생시킵니다. 이러한 이벤트에 대한 핸들러를 등록하여 해당 이벤트가 발생할 때 커스텀 코드를 실행할 수 있습니다. + + +CrewAI AOP는 event 시스템을 활용하여 모든 prompt, completion 및 관련 메타데이터를 추적, 저장 및 시각화하는 내장 Prompt Tracing 기능을 제공합니다. 이 기능을 통해 agent 운영에 대한 강력한 디버깅 기능과 투명성을 얻을 수 있습니다. + +![Prompt Tracing Dashboard](/images/enterprise/traces-overview.png) + +Prompt Tracing을 통해 다음과 같은 작업이 가능합니다: +- LLM에 전송된 모든 prompt의 전체 기록 보기 +- token 사용량 및 비용 추적 +- agent reasoning 실패 디버깅 +- 팀 내에서 prompt 시퀀스 공유 +- 다양한 prompt 전략 비교 +- 컴플라이언스 및 감사를 위한 trace 내보내기 + + +## 커스텀 이벤트 리스너 생성하기 + +커스텀 이벤트 리스너를 생성하려면 다음 단계를 따라야 합니다: + +1. `BaseEventListener`를 상속하는 클래스를 생성합니다. +2. `setup_listeners` 메서드를 구현합니다. +3. 원하는 이벤트에 대한 핸들러를 등록합니다. +4. 해당 파일에서 리스너의 인스턴스를 생성합니다. + +아래는 커스텀 이벤트 리스너 클래스의 간단한 예시입니다: + +```python +from crewai.events import ( + CrewKickoffStartedEvent, + CrewKickoffCompletedEvent, + AgentExecutionCompletedEvent, +) +from crewai.events import BaseEventListener + +class MyCustomListener(BaseEventListener): + def __init__(self): + super().__init__() + + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(CrewKickoffStartedEvent) + def on_crew_started(source, event): + print(f"Crew '{event.crew_name}' has started execution!") + + @crewai_event_bus.on(CrewKickoffCompletedEvent) + def on_crew_completed(source, event): + print(f"Crew '{event.crew_name}' has completed execution!") + print(f"Output: {event.output}") + + @crewai_event_bus.on(AgentExecutionCompletedEvent) + def on_agent_execution_completed(source, event): + print(f"Agent '{event.agent.role}' completed task") + print(f"Output: {event.output}") +``` + +## 리스너를 올바르게 등록하기 + +리스너 클래스를 정의하는 것만으로는 충분하지 않습니다. 해당 클래스의 인스턴스를 생성하고 애플리케이션에 임포트되었는지 확인해야 합니다. 이렇게 하면 다음과 같은 효과가 있습니다: + +1. 이벤트 핸들러가 이벤트 버스에 등록됩니다. +2. 리스너 인스턴스가 메모리에 유지됩니다(가비지 컬렉션되지 않음). +3. 이벤트가 발생할 때 리스너가 활성화됩니다. + +### 옵션 1: Crew 또는 Flow 구현에서 가져오기 및 인스턴스화 + +가장 중요한 것은 Crew 또는 Flow가 정의되고 실행되는 파일에서 리스너의 인스턴스를 생성하는 것입니다. + +#### 크루 기반 애플리케이션의 경우 + +크루 구현 파일 상단에 리스너를 생성하고 임포트하세요: + +```python +# In your crew.py file +from crewai import Agent, Crew, Task +from my_listeners import MyCustomListener + +# Create an instance of your listener +my_listener = MyCustomListener() + +class MyCustomCrew: + # Your crew implementation... + + def crew(self): + return Crew( + agents=[...], + tasks=[...], + # ... + ) +``` + +#### 플로우 기반 애플리케이션의 경우 + +플로우 구현 파일 상단에 리스너를 생성하고 임포트하세요: + +```python +# main.py 또는 flow.py 파일에서 +from crewai.flow import Flow, listen, start +from my_listeners import MyCustomListener + +# 리스너 인스턴스 생성 +my_listener = MyCustomListener() + +class MyCustomFlow(Flow): + # 플로우 구현... + + @start() + def first_step(self): + # ... +``` + +이렇게 하면 크루 또는 플로우가 실행될 때 리스너가 로드되고 활성화됩니다. + +### 옵션 2: 리스너를 위한 패키지 생성 + +여러 개의 리스너가 있는 경우 등 보다 구조적인 접근 방식을 원한다면 다음과 같이 진행하세요: + +1. 리스너를 위한 패키지를 생성합니다: + +``` +my_project/ + ├── listeners/ + │ ├── __init__.py + │ ├── my_custom_listener.py + │ └── another_listener.py +``` + +2. `my_custom_listener.py`에서 리스너 클래스를 정의하고 인스턴스를 생성합니다: + +```python +# my_custom_listener.py +from crewai.events import BaseEventListener +# ... import events ... + +class MyCustomListener(BaseEventListener): + # ... implementation ... + +# 리스너 인스턴스 생성 +my_custom_listener = MyCustomListener() +``` + +3. `__init__.py`에서 리스너 인스턴스를 임포트하여 로드되도록 합니다: + +```python +# __init__.py +from .my_custom_listener import my_custom_listener +from .another_listener import another_listener + +# 다른 곳에서 접근이 필요하다면 익스포트할 수도 있습니다 +__all__ = ['my_custom_listener', 'another_listener'] +``` + +4. Crew나 Flow 파일에서 리스너 패키지를 임포트합니다: + +```python +# crew.py 또는 flow.py 파일 내에서 +import my_project.listeners # 모든 리스너가 로드됩니다 + +class MyCustomCrew: + # Your crew implementation... +``` + +이것이 CrewAI 코드베이스에서 서드파티 이벤트 리스너가 등록되는 방식입니다. + +## 사용 가능한 이벤트 유형 + +CrewAI는 여러분이 청취할 수 있는 다양한 이벤트를 제공합니다: + +### Crew 이벤트 + +- **CrewKickoffStartedEvent**: Crew가 실행을 시작할 때 발생 +- **CrewKickoffCompletedEvent**: Crew가 실행을 완료할 때 발생 +- **CrewKickoffFailedEvent**: Crew가 실행을 완료하지 못할 때 발생 +- **CrewTestStartedEvent**: Crew가 테스트를 시작할 때 발생 +- **CrewTestCompletedEvent**: Crew가 테스트를 완료할 때 발생 +- **CrewTestFailedEvent**: Crew가 테스트를 완료하지 못할 때 발생 +- **CrewTrainStartedEvent**: Crew가 훈련을 시작할 때 발생 +- **CrewTrainCompletedEvent**: Crew가 훈련을 완료할 때 발생 +- **CrewTrainFailedEvent**: Crew가 훈련을 완료하지 못할 때 발생 +- **CrewTestResultEvent**: Crew 테스트 결과가 사용 가능할 때 발생합니다. 품질 점수, 실행 시간, 사용된 모델을 포함합니다. + +### 에이전트 이벤트 + +- **AgentExecutionStartedEvent**: 에이전트가 작업 실행을 시작할 때 발생함 +- **AgentExecutionCompletedEvent**: 에이전트가 작업 실행을 완료할 때 발생함 +- **AgentExecutionErrorEvent**: 에이전트가 실행 도중 오류를 만날 때 발생함 +- **LiteAgentExecutionStartedEvent**: LiteAgent가 실행을 시작할 때 발생합니다. 에이전트 정보, 도구, 메시지를 포함합니다. +- **LiteAgentExecutionCompletedEvent**: LiteAgent가 실행을 완료할 때 발생합니다. 에이전트 정보와 출력을 포함합니다. +- **LiteAgentExecutionErrorEvent**: LiteAgent가 실행 중 오류를 만날 때 발생합니다. 에이전트 정보와 오류 메시지를 포함합니다. +- **AgentEvaluationStartedEvent**: 에이전트 평가가 시작될 때 발생합니다. 에이전트 ID, 에이전트 역할, 선택적 태스크 ID, 반복 횟수를 포함합니다. +- **AgentEvaluationCompletedEvent**: 에이전트 평가가 완료될 때 발생합니다. 에이전트 ID, 에이전트 역할, 선택적 태스크 ID, 반복 횟수, 메트릭 카테고리, 점수를 포함합니다. +- **AgentEvaluationFailedEvent**: 에이전트 평가가 실패할 때 발생합니다. 에이전트 ID, 에이전트 역할, 선택적 태스크 ID, 반복 횟수, 오류 메시지를 포함합니다. + +### 작업 이벤트 + +- **TaskStartedEvent**: 작업이 실행을 시작할 때 발생 +- **TaskCompletedEvent**: 작업이 실행을 완료할 때 발생 +- **TaskFailedEvent**: 작업이 실행을 완료하지 못할 때 발생 +- **TaskEvaluationEvent**: 작업이 평가될 때 발생 + +### 도구 사용 이벤트 + +- **ToolUsageStartedEvent**: 도구 실행이 시작될 때 발생함 +- **ToolUsageFinishedEvent**: 도구 실행이 완료될 때 발생함 +- **ToolUsageErrorEvent**: 도구 실행 중 오류가 발생할 때 발생함 +- **ToolValidateInputErrorEvent**: 도구 입력 검증 중 오류가 발생할 때 발생함 +- **ToolExecutionErrorEvent**: 도구 실행 중 오류가 발생할 때 발생함 +- **ToolSelectionErrorEvent**: 도구 선택 시 오류가 발생할 때 발생함 + +### MCP 이벤트 + +- **MCPConnectionStartedEvent**: MCP 서버 연결을 시작할 때 발생합니다. 서버 이름, URL, 전송 유형, 연결 시간 초과, 재연결 시도 여부를 포함합니다. +- **MCPConnectionCompletedEvent**: MCP 서버에 성공적으로 연결될 때 발생합니다. 서버 이름, 연결 시간(밀리초), 재연결 여부를 포함합니다. +- **MCPConnectionFailedEvent**: MCP 서버 연결이 실패할 때 발생합니다. 서버 이름, 오류 메시지, 오류 유형(`timeout`, `authentication`, `network` 등)을 포함합니다. +- **MCPToolExecutionStartedEvent**: MCP 도구 실행을 시작할 때 발생합니다. 서버 이름, 도구 이름, 도구 인수를 포함합니다. +- **MCPToolExecutionCompletedEvent**: MCP 도구 실행이 성공적으로 완료될 때 발생합니다. 서버 이름, 도구 이름, 결과, 실행 시간(밀리초)을 포함합니다. +- **MCPToolExecutionFailedEvent**: MCP 도구 실행이 실패할 때 발생합니다. 서버 이름, 도구 이름, 오류 메시지, 오류 유형(`timeout`, `validation`, `server_error` 등)을 포함합니다. +- **MCPConfigFetchFailedEvent**: MCP 서버 구성을 가져오는 데 실패할 때 발생합니다(예: 계정에서 MCP가 연결되지 않았거나, API 오류, 구성을 가져온 후 연결 실패). slug, 오류 메시지, 오류 유형(`not_connected`, `api_error`, `connection_failed`)을 포함합니다. + +### 지식 이벤트 + +- **KnowledgeRetrievalStartedEvent**: 지식 검색이 시작될 때 발생 +- **KnowledgeRetrievalCompletedEvent**: 지식 검색이 완료될 때 발생 +- **KnowledgeQueryStartedEvent**: 지식 쿼리가 시작될 때 발생 +- **KnowledgeQueryCompletedEvent**: 지식 쿼리가 완료될 때 발생 +- **KnowledgeQueryFailedEvent**: 지식 쿼리가 실패할 때 발생 +- **KnowledgeSearchQueryFailedEvent**: 지식 검색 쿼리가 실패할 때 발생 + +### LLM 가드레일 이벤트 + +- **LLMGuardrailStartedEvent**: 가드레일 검증이 시작될 때 발생합니다. 적용되는 가드레일에 대한 세부 정보와 재시도 횟수를 포함합니다. +- **LLMGuardrailCompletedEvent**: 가드레일 검증이 완료될 때 발생합니다. 검증의 성공/실패, 결과 및 오류 메시지(있는 경우)에 대한 세부 정보를 포함합니다. +- **LLMGuardrailFailedEvent**: 가드레일 검증이 실패할 때 발생합니다. 오류 메시지와 재시도 횟수를 포함합니다. + +### Flow 이벤트 + +- **FlowCreatedEvent**: Flow가 생성될 때 발생 +- **FlowStartedEvent**: Flow가 실행을 시작할 때 발생 +- **FlowFinishedEvent**: Flow가 실행을 완료할 때 발생 +- **FlowFailedEvent**: Flow 실행이 실패할 때 발생합니다. Flow 이름과 실행을 종료시킨 예외를 포함합니다. +- **FlowPausedEvent**: 사람의 피드백을 기다리며 Flow가 일시 중지될 때 발생합니다. Flow 이름, Flow ID, 메서드 이름, 현재 상태, 피드백 요청 시 표시되는 메시지, 라우팅을 위한 선택적 결과 목록을 포함합니다. +- **FlowPlotEvent**: Flow가 플롯될 때 발생 +- **MethodExecutionStartedEvent**: Flow 메서드가 실행을 시작할 때 발생 +- **MethodExecutionFinishedEvent**: Flow 메서드가 실행을 완료할 때 발생 +- **MethodExecutionFailedEvent**: Flow 메서드가 실행을 완료하지 못할 때 발생 +- **MethodExecutionPausedEvent**: 사람의 피드백을 기다리며 Flow 메서드가 일시 중지될 때 발생합니다. Flow 이름, 메서드 이름, 현재 상태, Flow ID, 피드백 요청 시 표시되는 메시지, 라우팅을 위한 선택적 결과 목록을 포함합니다. + +### Human In The Loop 이벤트 + +- **FlowInputRequestedEvent**: `Flow.ask()`를 통해 Flow가 사용자 입력을 요청할 때 발생합니다. Flow 이름, 메서드 이름, 사용자에게 표시되는 질문 또는 프롬프트, 선택적 메타데이터(예: 사용자 ID, 채널, 세션 컨텍스트)를 포함합니다. +- **FlowInputReceivedEvent**: `Flow.ask()` 이후 사용자 입력이 수신될 때 발생합니다. Flow 이름, 메서드 이름, 원래 질문, 사용자의 응답(시간 초과 시 `None`), 선택적 요청 메타데이터, 프로바이더의 선택적 응답 메타데이터(예: 응답자, 스레드 ID, 타임스탬프)를 포함합니다. +- **HumanFeedbackRequestedEvent**: `@human_feedback` 데코레이터가 적용된 메서드가 사람 리뷰어의 입력을 필요로 할 때 발생합니다. Flow 이름, 메서드 이름, 사람에게 검토를 위해 표시되는 메서드 출력, 피드백 요청 시 표시되는 메시지, 라우팅을 위한 선택적 결과 목록을 포함합니다. +- **HumanFeedbackReceivedEvent**: `@human_feedback` 데코레이터가 적용된 메서드에 대해 사람이 피드백을 제공할 때 발생합니다. Flow 이름, 메서드 이름, 사람이 제공한 원본 텍스트 피드백, 축약된 결과 문자열(emit이 지정된 경우)을 포함합니다. + +### LLM 이벤트 + +- **LLMCallStartedEvent**: LLM 호출이 시작될 때 발생 +- **LLMCallCompletedEvent**: LLM 호출이 완료될 때 발생 +- **LLMCallFailedEvent**: LLM 호출이 실패할 때 발생 +- **LLMStreamChunkEvent**: 스트리밍 LLM 응답 중 각 청크를 받을 때마다 발생 +- **LLMThinkingChunkEvent**: thinking 모델에서 사고/추론 청크가 수신될 때 발생합니다. 청크 텍스트와 선택적 응답 ID를 포함합니다. + +### 메모리 이벤트 + +- **MemoryQueryStartedEvent**: 메모리 쿼리가 시작될 때 발생합니다. 쿼리, limit, 선택적 score threshold를 포함합니다. +- **MemoryQueryCompletedEvent**: 메모리 쿼리가 성공적으로 완료될 때 발생합니다. 쿼리, 결과, limit, score threshold, 쿼리 실행 시간을 포함합니다. +- **MemoryQueryFailedEvent**: 메모리 쿼리 실행에 실패할 때 발생합니다. 쿼리, limit, score threshold, 오류 메시지를 포함합니다. +- **MemorySaveStartedEvent**: 메모리 저장 작업이 시작될 때 발생합니다. 저장할 값, 메타데이터, 선택적 agent 역할을 포함합니다. +- **MemorySaveCompletedEvent**: 메모리 저장 작업이 성공적으로 완료될 때 발생합니다. 저장된 값, 메타데이터, agent 역할, 저장 실행 시간을 포함합니다. +- **MemorySaveFailedEvent**: 메모리 저장 작업에 실패할 때 발생합니다. 값, 메타데이터, agent 역할, 오류 메시지를 포함합니다. +- **MemoryRetrievalStartedEvent**: 태스크 프롬프트를 위한 메모리 검색이 시작될 때 발생합니다. 선택적 태스크 ID를 포함합니다. +- **MemoryRetrievalCompletedEvent**: 태스크 프롬프트를 위한 메모리 검색이 성공적으로 완료될 때 발생합니다. 태스크 ID, 메모리 내용, 검색 실행 시간을 포함합니다. +- **MemoryRetrievalFailedEvent**: 태스크 프롬프트를 위한 메모리 검색이 실패할 때 발생합니다. 선택적 태스크 ID와 오류 메시지를 포함합니다. + +### 추론 이벤트 + +- **AgentReasoningStartedEvent**: 에이전트가 태스크에 대한 추론을 시작할 때 발생합니다. 에이전트 역할, 태스크 ID, 시도 횟수를 포함합니다. +- **AgentReasoningCompletedEvent**: 에이전트가 추론 과정을 마칠 때 발생합니다. 에이전트 역할, 태스크 ID, 생성된 계획, 에이전트가 진행할 준비가 되었는지 여부를 포함합니다. +- **AgentReasoningFailedEvent**: 추론 과정이 실패할 때 발생합니다. 에이전트 역할, 태스크 ID, 오류 메시지를 포함합니다. + +### 관찰 이벤트 + +- **StepObservationStartedEvent**: Planner가 단계 결과를 관찰하기 시작할 때 발생합니다. 매 단계 실행 후, 관찰 LLM 호출 전에 발생합니다. 에이전트 역할, 단계 번호, 단계 설명을 포함합니다. +- **StepObservationCompletedEvent**: Planner가 단계 결과 관찰을 마칠 때 발생합니다. 단계 성공 여부, 학습된 핵심 정보, 남은 계획의 유효성, 전체 재계획 필요 여부, 제안된 개선 사항을 포함합니다. +- **StepObservationFailedEvent**: 관찰 LLM 호출 자체가 실패할 때 발생합니다. 시스템은 기본적으로 계획을 계속 진행합니다. 오류 메시지를 포함합니다. +- **PlanRefinementEvent**: Planner가 전체 재계획 없이 다음 단계 설명을 개선할 때 발생합니다. 개선된 단계 수와 적용된 개선 사항을 포함합니다. +- **PlanReplanTriggeredEvent**: 남은 계획이 근본적으로 잘못된 것으로 판단되어 Planner가 전체 재계획을 트리거할 때 발생합니다. 재계획 이유, 재계획 횟수, 보존된 완료 단계 수를 포함합니다. +- **GoalAchievedEarlyEvent**: Planner가 목표가 조기에 달성되었음을 감지하고 나머지 단계를 건너뛸 때 발생합니다. 남은 단계 수와 완료된 단계 수를 포함합니다. + +### A2A (Agent-to-Agent) 이벤트 + +#### 위임 이벤트 + +- **A2ADelegationStartedEvent**: A2A 위임이 시작될 때 발생합니다. 엔드포인트 URL, 태스크 설명, 에이전트 ID, 컨텍스트 ID, 멀티턴 여부, 턴 번호, agent card 메타데이터, 프로토콜 버전, 프로바이더 정보, 선택적 skill ID를 포함합니다. +- **A2ADelegationCompletedEvent**: A2A 위임이 완료될 때 발생합니다. 완료 상태(`completed`, `input_required`, `failed` 등), 결과, 오류 메시지, 컨텍스트 ID, agent card 메타데이터를 포함합니다. +- **A2AParallelDelegationStartedEvent**: 여러 A2A 에이전트로의 병렬 위임이 시작될 때 발생합니다. 엔드포인트 목록과 태스크 설명을 포함합니다. +- **A2AParallelDelegationCompletedEvent**: 여러 A2A 에이전트로의 병렬 위임이 완료될 때 발생합니다. 엔드포인트 목록, 성공 수, 실패 수, 결과 요약을 포함합니다. + +#### 대화 이벤트 + +- **A2AConversationStartedEvent**: 멀티턴 A2A 대화 시작 시 한 번 발생합니다. 첫 번째 메시지 교환 전에 발생합니다. 에이전트 ID, 엔드포인트, 컨텍스트 ID, agent card 메타데이터, 프로토콜 버전, 프로바이더 정보를 포함합니다. +- **A2AMessageSentEvent**: A2A 에이전트에 메시지가 전송될 때 발생합니다. 메시지 내용, 턴 번호, 컨텍스트 ID, 메시지 ID, 멀티턴 여부를 포함합니다. +- **A2AResponseReceivedEvent**: A2A 에이전트로부터 응답이 수신될 때 발생합니다. 응답 내용, 턴 번호, 컨텍스트 ID, 메시지 ID, 상태, 최종 응답 여부를 포함합니다. +- **A2AConversationCompletedEvent**: 멀티턴 A2A 대화 종료 시 한 번 발생합니다. 최종 상태(`completed` 또는 `failed`), 최종 결과, 오류 메시지, 컨텍스트 ID, 총 턴 수를 포함합니다. + +#### 스트리밍 이벤트 + +- **A2AStreamingStartedEvent**: A2A 위임을 위한 스트리밍 모드가 시작될 때 발생합니다. 태스크 ID, 컨텍스트 ID, 엔드포인트, 턴 번호, 멀티턴 여부를 포함합니다. +- **A2AStreamingChunkEvent**: 스트리밍 청크가 수신될 때 발생합니다. 청크 텍스트, 청크 인덱스, 최종 청크 여부, 태스크 ID, 컨텍스트 ID, 턴 번호를 포함합니다. + +#### 폴링 및 푸시 알림 이벤트 + +- **A2APollingStartedEvent**: A2A 위임을 위한 폴링 모드가 시작될 때 발생합니다. 태스크 ID, 컨텍스트 ID, 폴링 간격(초), 엔드포인트를 포함합니다. +- **A2APollingStatusEvent**: 각 폴링 반복 시 발생합니다. 태스크 ID, 컨텍스트 ID, 현재 태스크 상태, 경과 시간, 폴링 횟수를 포함합니다. +- **A2APushNotificationRegisteredEvent**: 푸시 알림 콜백이 등록될 때 발생합니다. 태스크 ID, 컨텍스트 ID, 콜백 URL, 엔드포인트를 포함합니다. +- **A2APushNotificationReceivedEvent**: 원격 A2A 에이전트로부터 푸시 알림이 수신될 때 발생합니다. 태스크 ID, 컨텍스트 ID, 현재 상태를 포함합니다. +- **A2APushNotificationSentEvent**: 콜백 URL로 푸시 알림이 전송될 때 발생합니다. 태스크 ID, 컨텍스트 ID, 콜백 URL, 상태, 전달 성공 여부, 선택적 오류 메시지를 포함합니다. +- **A2APushNotificationTimeoutEvent**: 푸시 알림 대기가 시간 초과될 때 발생합니다. 태스크 ID, 컨텍스트 ID, 시간 초과 시간(초)을 포함합니다. + +#### 연결 및 인증 이벤트 + +- **A2AAgentCardFetchedEvent**: agent card가 성공적으로 가져올 때 발생합니다. 엔드포인트, 에이전트 이름, agent card 메타데이터, 프로토콜 버전, 프로바이더 정보, 캐시 여부, 가져오기 시간(밀리초)을 포함합니다. +- **A2AAuthenticationFailedEvent**: A2A 에이전트 인증이 실패할 때 발생합니다. 엔드포인트, 시도된 인증 유형(예: `bearer`, `oauth2`, `api_key`), 오류 메시지, HTTP 상태 코드를 포함합니다. +- **A2AConnectionErrorEvent**: A2A 통신 중 연결 오류가 발생할 때 발생합니다. 엔드포인트, 오류 메시지, 오류 유형(예: `timeout`, `connection_refused`, `dns_error`), HTTP 상태 코드, 시도 중인 작업을 포함합니다. +- **A2ATransportNegotiatedEvent**: A2A 에이전트와 전송 프로토콜이 협상될 때 발생합니다. 협상된 전송, 협상된 URL, 선택 소스(`client_preferred`, `server_preferred`, `fallback`), 클라이언트/서버 지원 전송을 포함합니다. +- **A2AContentTypeNegotiatedEvent**: A2A 에이전트와 콘텐츠 유형이 협상될 때 발생합니다. 클라이언트/서버 입출력 모드, 협상된 입출력 모드, 협상 성공 여부를 포함합니다. + +#### 아티팩트 이벤트 + +- **A2AArtifactReceivedEvent**: 원격 A2A 에이전트로부터 아티팩트가 수신될 때 발생합니다. 태스크 ID, 아티팩트 ID, 아티팩트 이름, 설명, MIME 유형, 크기(바이트), 콘텐츠 추가 여부를 포함합니다. + +#### 서버 태스크 이벤트 + +- **A2AServerTaskStartedEvent**: A2A 서버 태스크 실행이 시작될 때 발생합니다. 태스크 ID와 컨텍스트 ID를 포함합니다. +- **A2AServerTaskCompletedEvent**: A2A 서버 태스크 실행이 완료될 때 발생합니다. 태스크 ID, 컨텍스트 ID, 결과를 포함합니다. +- **A2AServerTaskCanceledEvent**: A2A 서버 태스크 실행이 취소될 때 발생합니다. 태스크 ID와 컨텍스트 ID를 포함합니다. +- **A2AServerTaskFailedEvent**: A2A 서버 태스크 실행이 실패할 때 발생합니다. 태스크 ID, 컨텍스트 ID, 오류 메시지를 포함합니다. + +#### 컨텍스트 수명 주기 이벤트 + +- **A2AContextCreatedEvent**: A2A 컨텍스트가 생성될 때 발생합니다. 컨텍스트는 대화 또는 워크플로우에서 관련 태스크를 그룹화합니다. 컨텍스트 ID와 생성 타임스탬프를 포함합니다. +- **A2AContextExpiredEvent**: TTL로 인해 A2A 컨텍스트가 만료될 때 발생합니다. 컨텍스트 ID, 생성 타임스탬프, 수명(초), 태스크 수를 포함합니다. +- **A2AContextIdleEvent**: A2A 컨텍스트가 유휴 상태가 될 때(설정된 임계값 동안 활동 없음) 발생합니다. 컨텍스트 ID, 유휴 시간(초), 태스크 수를 포함합니다. +- **A2AContextCompletedEvent**: A2A 컨텍스트의 모든 태스크가 완료될 때 발생합니다. 컨텍스트 ID, 총 태스크 수, 지속 시간(초)을 포함합니다. +- **A2AContextPrunedEvent**: A2A 컨텍스트가 정리(삭제)될 때 발생합니다. 컨텍스트 ID, 태스크 수, 수명(초)을 포함합니다. + +## 이벤트 핸들러 구조 + +각 이벤트 핸들러는 두 개의 매개변수를 받습니다: + +1. **source**: 이벤트를 발생시킨 객체 +2. **event**: 이벤트별 데이터를 포함하는 이벤트 인스턴스 + +이벤트 객체의 구조는 이벤트 타입에 따라 다르지만, 모든 이벤트는 `BaseEvent`를 상속하며 다음을 포함합니다: + +- **timestamp**: 이벤트가 발생한 시간 +- **type**: 이벤트 타입을 나타내는 문자열 식별자 + +추가 필드는 이벤트 타입에 따라 다릅니다. 예를 들어, `CrewKickoffCompletedEvent`에는 `crew_name`과 `output` 필드가 포함됩니다. + + +## 고급 사용법: Scoped Handlers + +임시 이벤트 처리가 필요한 경우(테스트 또는 특정 작업에 유용함), `scoped_handlers` 컨텍스트 관리자를 사용할 수 있습니다: + +```python +from crewai.events import crewai_event_bus, CrewKickoffStartedEvent + +with crewai_event_bus.scoped_handlers(): + @crewai_event_bus.on(CrewKickoffStartedEvent) + def temp_handler(source, event): + print("This handler only exists within this context") + + # Do something that emits events + +# 컨텍스트 밖에서는 임시 핸들러가 제거됩니다 +``` + +## 사용 사례 + +이벤트 리스너는 다양한 목적으로 사용할 수 있습니다: + +1. **로깅 및 모니터링**: Crew의 실행을 추적하고 중요한 이벤트를 기록합니다 +2. **분석**: Crew의 성능과 동작에 대한 데이터를 수집합니다 +3. **디버깅**: 특정 문제를 디버깅하기 위해 임시 리스너를 설정합니다 +4. **통합**: CrewAI를 모니터링 플랫폼, 데이터베이스 또는 알림 서비스와 같은 외부 시스템과 연결합니다 +5. **사용자 정의 동작**: 특정 이벤트에 따라 사용자 정의 동작을 트리거합니다 + +## 모범 사례 + +1. **핸들러를 가볍게 유지하세요**: 이벤트 핸들러는 경량이어야 하며, 블로킹 작업을 피해야 합니다. +2. **오류 처리**: 예외가 메인 실행에 영향을 주지 않도록 이벤트 핸들러에 적절한 오류 처리를 포함하세요. +3. **정리**: 리스너가 자원을 할당한다면, 이를 적절하게 정리하는지 확인하세요. +4. **선택적 리스닝**: 실제로 처리해야 하는 이벤트에만 리스닝하세요. +5. **테스트**: 이벤트 리스너가 예상대로 동작하는지 독립적으로 테스트하세요. + +CrewAI의 이벤트 시스템을 활용하면 기능을 확장하고 기존 인프라와 원활하게 통합할 수 있습니다. diff --git a/docs/v1.15.13/ko/concepts/files.mdx b/docs/v1.15.13/ko/concepts/files.mdx new file mode 100644 index 0000000000..c07a39fadf --- /dev/null +++ b/docs/v1.15.13/ko/concepts/files.mdx @@ -0,0 +1,267 @@ +--- +title: 파일 +description: 멀티모달 처리를 위해 이미지, PDF, 오디오, 비디오, 텍스트 파일을 에이전트에 전달하세요. +icon: file-image +--- + +## 개요 + +CrewAI는 네이티브 멀티모달 파일 입력을 지원하여 이미지, PDF, 오디오, 비디오, 텍스트 파일을 에이전트에 직접 전달할 수 있습니다. 파일은 각 LLM 프로바이더의 API 요구사항에 맞게 자동으로 포맷됩니다. + + +파일 지원을 위해서는 선택적 `crewai-files` 패키지가 필요합니다. 다음 명령어로 설치하세요: + +```bash +uv add 'crewai[file-processing]' +``` + + + +파일 처리 API는 현재 얼리 액세스 단계입니다. + + +## 파일 타입 + +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) | ✓ | | ✓ | | | + + +Google Gemini 모델은 비디오를 포함한 모든 파일 타입을 지원합니다 (최대 1시간, 2GB). 비디오 콘텐츠를 처리해야 할 때 Gemini를 사용하세요. + + + +프로바이더가 지원하지 않는 파일 타입을 전달하면 (예: OpenAI에 비디오) `UnsupportedFileTypeError`가 발생합니다. 처리해야 하는 파일 타입에 따라 프로바이더를 선택하세요. + + +## 파일 전송 방식 + +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** | ✓ | | ✓ | + + +이를 직접 관리할 필요가 없습니다. CrewAI는 파일 크기와 프로바이더 기능에 따라 가장 효율적인 방법을 자동으로 사용합니다. 파일 업로드 API가 없는 프로바이더는 모든 파일에 인라인 base64를 사용합니다. + + +## 파일 처리 모드 + +프로바이더 제한을 초과할 때 파일 처리 방식을 제어합니다: + +```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"), + } +) +``` diff --git a/docs/v1.15.13/ko/concepts/flows.mdx b/docs/v1.15.13/ko/concepts/flows.mdx new file mode 100644 index 0000000000..5c2e21d5a7 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/flows.mdx @@ -0,0 +1,1075 @@ +--- +title: Flows +description: CrewAI Flows를 사용하여 AI 워크플로우를 생성하고 관리하는 방법을 알아보세요. +icon: arrow-progress +mode: "wide" +--- + +## 개요 + +CrewAI Flows는 AI 워크플로우의 생성 및 관리를 간소화하기 위해 설계된 강력한 기능입니다. Flows를 사용하면 개발자는 다양한 코딩 작업과 각 Crew를 효율적으로 결합하고 조정할 수 있어, 정교한 AI 자동화를 구축할 수 있는 견고한 프레임워크를 제공합니다. + +Flows는 구조화된 이벤트 기반 워크플로우를 생성할 수 있게 해줍니다. 이를 통해 여러 작업을 원활하게 연결하고, 상태를 관리하며, AI 애플리케이션에서 실행 흐름을 제어할 수 있습니다. Flows를 사용하면 CrewAI의 전체 역량을 활용하는 다단계 프로세스를 손쉽게 설계하고 구현할 수 있습니다. + +1. **간편한 워크플로우 생성**: 여러 Crew와 작업을 손쉽게 연결하여 복잡한 AI 워크플로우를 만듭니다. + +2. **상태 관리**: Flows를 통해 워크플로우 내의 다양한 작업 간에 상태를 쉽고 효율적으로 관리 및 공유할 수 있습니다. + +3. **이벤트 기반 아키텍처**: 이벤트 기반 모델을 기반으로 하여, 역동적이고 반응성 높은 워크플로우를 구현할 수 있습니다. + +4. **유연한 제어 흐름**: 워크플로우 내에서 조건문, 반복문, 분기 등을 구현할 수 있습니다. + +## 시작하기 + +OpenAI를 사용하여 한 작업에서 무작위 도시를 생성하고, 그 도시를 사용해 다른 작업에서 재미있는 사실을 생성하는 간단한 Flow를 만들어보겠습니다. + +```python Code + +from crewai.flow.flow import Flow, listen, start +from dotenv import load_dotenv +from litellm import completion + +load_dotenv() + +class ExampleFlow(Flow): + model = "gpt-4o-mini" + + @start() + def generate_city(self): + print("Starting flow") + # Each flow state automatically gets a unique ID + print(f"Flow State ID: {self.state['id']}") + + response = completion( + model=self.model, + messages=[ + { + "role": "user", + "content": "Return the name of a random city in the world.", + }, + ], + ) + + random_city = response["choices"][0]["message"]["content"] + # Store the city in our state + self.state["city"] = random_city + print(f"Random City: {random_city}") + + return random_city + + @listen(generate_city) + def generate_fun_fact(self, random_city): + response = completion( + model=self.model, + messages=[ + { + "role": "user", + "content": f"Tell me a fun fact about {random_city}", + }, + ], + ) + + fun_fact = response["choices"][0]["message"]["content"] + # Store the fun fact in our state + self.state["fun_fact"] = fun_fact + return fun_fact + + + +flow = ExampleFlow() +flow.plot() +result = flow.kickoff() + +print(f"Generated fun fact: {result}") +``` +![Flow Visual image](/images/crewai-flow-1.png) +위 예제에서는 OpenAI를 사용하여 무작위 도시를 생성하고, 해당 도시에 대한 재미있는 사실을 생성하는 간단한 Flow를 만들었습니다. 이 Flow는 `generate_city`와 `generate_fun_fact`라는 두 가지 작업으로 구성되어 있습니다. `generate_city` 작업이 Flow의 시작점이며, `generate_fun_fact` 작업이 `generate_city` 작업의 출력을 감지합니다. + +각 Flow 인스턴스는 상태(state)에 자동으로 고유 식별자(UUID)를 부여 받아, 흐름 실행을 추적하고 관리하는 데 도움이 됩니다. 상태에는 실행 중에 유지되는 추가 데이터(예: 생성된 도시와 재미있는 사실)도 저장할 수 있습니다. + +Flow를 실행하면 다음과 같은 과정을 따릅니다: +1. 상태를 위한 고유 ID를 생성 +2. 무작위 도시를 생성하여 상태에 저장 +3. 해당 도시에 대한 재미있는 사실을 생성하여 상태에 저장 +4. 결과를 콘솔에 출력 + +상태의 고유 ID와 저장된 데이터는 흐름 실행을 추적하고, 작업 간의 컨텍스트를 유지하는 데 유용합니다. + +**참고:** OpenAI API 요청 인증을 위해 `OPENAI_API_KEY`를 `.env` 파일에 설정해야 합니다. 이 키는 필수입니다. + +### @start() + +`@start()` 데코레이터는 메서드를 Flow의 시작 지점으로 표시하는 데 사용됩니다. Flow가 시작되면 `@start()`로 데코레이트된 모든 메서드가 병렬로 실행됩니다. 하나의 Flow에서 여러 개의 start 메서드를 가질 수 있으며, Flow가 시작될 때 이들은 모두 실행됩니다. + +### @listen() + +`@listen()` 데코레이터는 Flow 내에서 다른 태스크의 출력을 수신하는 리스너로 메서드를 표시하는 데 사용됩니다. `@listen()`으로 데코레이션된 메서드는 지정된 태스크가 출력을 내보낼 때 실행됩니다. 이 메서드는 자신이 리스닝하고 있는 태스크의 출력을 인자로 접근할 수 있습니다. + +#### 사용법 + +`@listen()` 데코레이터는 여러 가지 방법으로 사용할 수 있습니다: + +1. **메서드 이름으로 리스닝하기**: 리스닝하고자 하는 메서드의 이름을 문자열로 전달할 수 있습니다. 해당 메서드가 완료되면, 리스너 메서드가 트리거됩니다. + + ```python Code + @listen("generate_city") + def generate_fun_fact(self, random_city): + # Implementation + ``` + +2. **메서드 자체로 리스닝하기**: 메서드 자체를 전달할 수도 있습니다. 해당 메서드가 완료되면, 리스너 메서드가 트리거됩니다. + ```python Code + @listen(generate_city) + def generate_fun_fact(self, random_city): + # Implementation + ``` + +### Flow 출력 + +Flow의 출력을 접근하고 다루는 것은 AI 워크플로우를 더 큰 애플리케이션이나 시스템에 통합하는 데 필수적입니다. CrewAI Flow는 최종 출력물을 쉽게 가져오고, 중간 결과에 접근하며, Flow의 전체 상태를 관리할 수 있는 직관적인 메커니즘을 제공합니다. + +#### 최종 출력값 가져오기 + +Flow를 실행하면, 최종 출력값은 마지막으로 완료된 메서드에 의해 결정됩니다. `kickoff()` 메서드는 이 마지막 메서드의 결과를 반환합니다. + +최종 출력값을 확인하는 방법은 다음과 같습니다: + + +```python Code +from crewai.flow.flow import Flow, listen, start + +class OutputExampleFlow(Flow): + @start() + def first_method(self): + return "Output from first_method" + + @listen(first_method) + def second_method(self, first_output): + return f"Second method received: {first_output}" + + +flow = OutputExampleFlow() +flow.plot("my_flow_plot") +final_output = flow.kickoff() + +print("---- Final Output ----") +print(final_output) +``` + +```text Output +---- Final Output ---- +Second method received: Output from first_method +``` + + +![Flow Visual image](/images/crewai-flow-2.png) + +이 예제에서 `second_method`가 마지막으로 완료된 메서드이므로, 해당 메서드의 결과가 Flow의 최종 출력값이 됩니다. +`kickoff()` 메서드는 이 최종 출력값을 반환하며, 이 값은 콘솔에 출력됩니다. +`plot()` 메서드는 HTML 파일을 생성하며, 이를 통해 flow를 쉽게 이해할 수 있습니다. + +#### 상태에 접근하고 업데이트하기 + +최종 출력을 가져오는 것 외에도, Flow 내에서 상태(state)에 접근하고 업데이트할 수 있습니다. 상태는 Flow의 다양한 메소드 간 데이터를 저장하고 공유하는 데 사용할 수 있습니다. Flow가 실행된 후에는, 실행 중에 추가되거나 업데이트된 정보를 조회하기 위해 상태에 접근할 수 있습니다. + +다음은 상태를 업데이트하고 접근하는 방법의 예시입니다: + + + +```python Code +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + counter: int = 0 + message: str = "" + +class StateExampleFlow(Flow[ExampleState]): + + @start() + def first_method(self): + self.state.message = "Hello from first_method" + self.state.counter += 1 + + @listen(first_method) + def second_method(self): + self.state.message += " - updated by second_method" + self.state.counter += 1 + return self.state.message + +flow = StateExampleFlow() +flow.plot("my_flow_plot") +final_output = flow.kickoff() +print(f"Final Output: {final_output}") +print("Final State:") +print(flow.state) +``` + +```text Output +Final Output: Hello from first_method - updated by second_method +Final State: +counter=2 message='Hello from first_method - updated by second_method' +``` + + + +![Flow Visual image](/images/crewai-flow-2.png) + +이 예시에서 상태는 `first_method`와 `second_method` 모두에 의해 업데이트됩니다. +Flow가 실행된 후, 이러한 메소드들에 의해 수행된 업데이트 내용을 확인하려면 최종 상태에 접근할 수 있습니다. + +최종 메소드의 출력이 반환되고 상태에 접근할 수 있도록 함으로써, CrewAI Flow는 AI 워크플로우의 결과를 더 큰 애플리케이션이나 시스템에 쉽게 통합할 수 있게 하며, +Flow 실행 과정 전반에 걸쳐 상태를 유지하고 접근하면서도 이를 용이하게 만듭니다. + +## 플로우 사용 메트릭 + +Flow 실행이 완료된 후, `usage_metrics` 속성에 접근하여 실행 동안 발생한 **모든 LLM 호출**의 토큰 사용량 집계를 확인할 수 있습니다. 여기에는 Flow가 오케스트레이션한 모든 Crew의 호출, Agent의 도구 내부에서 발생한 호출, 그리고 Flow 메서드에서 직접 호출한 `LLM.call(...)`이 모두 포함됩니다. 이는 CrewAI Enterprise UI에 표시되는 총량과 동등한 SDK 측 값입니다. + +```python Code +from crewai import LLM +from crewai.flow.flow import Flow, listen, start + +class UsageMetricsFlow(Flow): + @start() + def run_first_crew(self): + self.state.first_result = FirstCrew().crew().kickoff() + + @listen(run_first_crew) + def call_llm_directly(self): + # 직접 LLM 호출 — flow.usage_metrics에서도 집계됩니다 + llm = LLM(model="openai/gpt-4o-mini") + self.state.summary = llm.call("핵심 내용을 요약해 주세요.") + + @listen(call_llm_directly) + def run_second_crew(self): + self.state.second_result = SecondCrew().crew().kickoff() + +flow = UsageMetricsFlow() +flow.kickoff() + +print(flow.usage_metrics) +# UsageMetrics(total_tokens=8579, prompt_tokens=6210, completion_tokens=2369, +# cached_prompt_tokens=0, reasoning_tokens=0, +# cache_creation_tokens=0, successful_requests=5) +``` + + + `flow.usage_metrics`는 `flow.kickoff().token_usage`와 **동일하지 않습니다**. + 후자는 `CrewOutput`을 반환한 **마지막** `@listen` 메서드의 + `CrewOutput.token_usage`만 반환하므로, 이전에 실행된 Crew들과 Flow 메서드에서 + 직접 호출한 `LLM.call(...)`은 전혀 포함되지 않습니다. Flow 실행에 대한 + **전체** 토큰 집계가 필요할 때는 항상 `flow.usage_metrics`를 사용하십시오. + + +### UsageMetrics 필드 의미 + +반환되는 [`UsageMetrics`](https://github.com/crewAIInc/crewAI/blob/main/lib/crewai/src/crewai/types/usage_metrics.py) 객체는 제공자 중립 계약을 사용합니다: + +| 필드 | 의미 | +| --- | --- | +| `total_tokens` | 청구된 총합: `prompt_tokens + completion_tokens` | +| `prompt_tokens` | 요청에 대해 청구된 전체 입력/프롬프트 토큰 | +| `completion_tokens` | 요청에 대해 청구된 출력/완료 토큰 | +| `cached_prompt_tokens` | 프롬프트 토큰 중 캐시 읽기 부분 집합 (breakdown 전용) | +| `cache_creation_tokens` | 프롬프트 토큰 중 캐시 쓰기 부분 집합 (breakdown 전용, Anthropic) | +| `reasoning_tokens` | 제공자가 별도로 보고하는 추론/사고 부분 집합 (breakdown 전용) | +| `successful_requests` | 집계된 LLM 호출 수 | + +`cached_prompt_tokens`, `cache_creation_tokens`, `reasoning_tokens`와 같은 breakdown 필드는 `total_tokens` **위에 추가되지 않습니다** — 이미 `prompt_tokens` 또는 `completion_tokens`에 포함된 부분을 설명합니다. + +Anthropic의 경우 캐시 읽기 및 쓰기 카운터가 `prompt_tokens`에 포함되므로, 캐시된 워크로드가 `total_tokens`에 완전히 반영됩니다. OpenAI 스타일 제공자는 캐시된 입력을 이미 `prompt_tokens`에 포함합니다. CrewAI는 가시성을 위해 캐시된 부분을 별도로 표시합니다. + +반환되는 [`UsageMetrics`](https://github.com/crewAIInc/crewAI/blob/main/lib/crewai/src/crewai/types/usage_metrics.py)의 각 항목은 단일 `flow.kickoff()` 실행 동안 발생한 모든 LLM 호출의 합계입니다. 다음 `kickoff()` 호출(및 `kickoff_for_each`의 각 반복)에서 카운터가 초기화되므로 연속 실행이 이중으로 집계되지 않습니다. 이 속성은 `kickoff()` 완료 후 언제든지 안전하게 읽을 수 있으며, 실행 중에 읽으면 그 시점까지 누적된 부분 합계를 반환합니다. + +## 플로우 상태 관리 + +상태를 효과적으로 관리하는 것은 신뢰할 수 있고 유지 보수가 용이한 AI 워크플로를 구축하는 데 매우 중요합니다. CrewAI 플로우는 비정형 및 정형 상태 관리를 위한 강력한 메커니즘을 제공하여, 개발자가 자신의 애플리케이션에 가장 적합한 접근 방식을 선택할 수 있도록 합니다. + +### 비구조적 상태 관리 + +비구조적 상태 관리에서는 모든 상태가 `Flow` 클래스의 `state` 속성에 저장됩니다. +이 방식은 엄격한 스키마를 정의하지 않고도 개발자가 상태 속성을 즉석에서 추가하거나 수정할 수 있는 유연성을 제공합니다. +비구조적 상태에서도 CrewAI Flows는 각 상태 인스턴스에 대한 고유 식별자(UUID)를 자동으로 생성하고 유지합니다. + +```python Code +from crewai.flow.flow import Flow, listen, start + +class UnstructuredExampleFlow(Flow): + + @start() + def first_method(self): + # The state automatically includes an 'id' field + print(f"State ID: {self.state['id']}") + self.state['counter'] = 0 + self.state['message'] = "Hello from structured flow" + + @listen(first_method) + def second_method(self): + self.state['counter'] += 1 + self.state['message'] += " - updated" + + @listen(second_method) + def third_method(self): + self.state['counter'] += 1 + self.state['message'] += " - updated again" + + print(f"State after third_method: {self.state}") + + +flow = UnstructuredExampleFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +![Flow Visual image](/images/crewai-flow-3.png) + +**참고:** `id` 필드는 흐름의 실행 전체에 걸쳐 자동으로 생성되어 보존됩니다. 이를 직접 관리하거나 설정할 필요가 없으며, 새로운 데이터로 상태를 업데이트할 때도 자동으로 유지됩니다. + +**핵심 포인트:** + +- **유연성:** `self.state`에 미리 정해진 제약 없이 속성을 동적으로 추가할 수 있습니다. +- **단순성:** 상태 구조가 최소이거나 크게 달라지는 단순한 워크플로우에 이상적입니다. + +### 구조화된 상태 관리 + +구조화된 상태 관리는 미리 정의된 스키마를 활용하여 워크플로 전반에 걸쳐 일관성과 타입 안전성을 보장합니다. Pydantic의 `BaseModel`과 같은 모델을 사용하면 상태의 정확한 형태를 정의할 수 있어, 개발 환경에서 더 나은 검증 및 자동 완성이 가능합니다. + +CrewAI Flows의 각 상태는 인스턴스 추적 및 관리를 돕기 위해 자동으로 고유 식별자(UUID)를 할당받습니다. 이 ID는 Flow 시스템에 의해 자동으로 생성되고 관리됩니다. + +```python Code +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + + +class ExampleState(BaseModel): + # Note: 'id' field is automatically added to all states + counter: int = 0 + message: str = "" + + +class StructuredExampleFlow(Flow[ExampleState]): + + @start() + def first_method(self): + # Access the auto-generated ID if needed + print(f"State ID: {self.state.id}") + self.state.message = "Hello from structured flow" + + @listen(first_method) + def second_method(self): + self.state.counter += 1 + self.state.message += " - updated" + + @listen(second_method) + def third_method(self): + self.state.counter += 1 + self.state.message += " - updated again" + + print(f"State after third_method: {self.state}") + + +flow = StructuredExampleFlow() +flow.kickoff() +``` + +![Flow Visual image](/images/crewai-flow-3.png) + +**핵심 포인트:** + +- **정의된 스키마:** `ExampleState`는 상태 구조를 명확히 정의하여 코드 가독성과 유지보수성을 향상시킵니다. +- **타입 안전성:** Pydantic을 활용하면 상태의 속성이 지정된 타입을 준수하도록 보장하여 런타임 오류를 줄일 수 있습니다. +- **자동 완성:** IDE에서 정의된 상태 모델을 기반으로 더 나은 자동 완성과 오류 확인이 가능합니다. + +### 비구조적 상태 관리와 구조적 상태 관리 선택하기 + +- **비구조적 상태 관리를 사용할 때:** + + - 워크플로의 상태가 단순하거나 매우 동적일 때. + - 엄격한 상태 정의보다 유연성이 우선시될 때. + - 스키마 정의의 오버헤드 없이 빠른 프로토타이핑이 필요할 때. + +- **구조적 상태 관리를 사용할 때:** + - 워크플로에 잘 정의되고 일관된 상태 구조가 필요할 때. + - 애플리케이션의 신뢰성을 위해 타입 안전성과 검증이 중요할 때. + - 더 나은 개발자 경험을 위해 IDE의 자동 완성 및 타입 체크 기능을 활용하고자 할 때. + +CrewAI Flows는 비구조적 및 구조적 상태 관리 옵션을 모두 제공함으로써, 개발자들이 다양한 애플리케이션 요구 사항에 맞춰 유연하면서도 견고한 AI 워크플로를 구축할 수 있도록 지원합니다. + +## 플로우 지속성 + +@persist 데코레이터는 CrewAI 플로우에서 자동 상태 지속성을 활성화하여, 플로우 상태를 재시작이나 다른 워크플로우 실행 간에도 유지할 수 있도록 합니다. 이 데코레이터는 클래스 수준이나 메서드 수준 모두에 적용할 수 있어, 상태 지속성을 관리하는 데 유연성을 제공합니다. + +### 클래스 레벨 영속성 + +클래스 레벨에서 @persist 데코레이터를 적용하면 모든 flow 메서드 상태가 자동으로 영속됩니다: + +```python +@persist # 기본적으로 SQLiteFlowPersistence 사용 +class MyFlow(Flow[MyState]): + @start() + def initialize_flow(self): + # 이 메서드는 상태가 자동으로 영속됩니다 + self.state.counter = 1 + print("Initialized flow. State ID:", self.state.id) + + @listen(initialize_flow) + def next_step(self): + # 상태(self.state.id 포함)는 자동으로 다시 로드됩니다 + self.state.counter += 1 + print("Flow state is persisted. Counter:", self.state.counter) +``` + +### 메서드 수준의 지속성 + +더 세밀한 제어를 위해, @persist를 특정 메서드에 적용할 수 있습니다: + +```python +class AnotherFlow(Flow[dict]): + @persist # Persists only this method's state + @start() + def begin(self): + if "runs" not in self.state: + self.state["runs"] = 0 + self.state["runs"] += 1 + print("Method-level persisted runs:", self.state["runs"]) +``` + +### 영속 상태 포크하기 + +`@persist`는 `kickoff` / `kickoff_async`에서 두 가지 별개의 하이드레이션 모드를 지원합니다: + +- `kickoff(inputs={"id": })` — **재개(resume)**: 제공된 UUID에 대한 최신 스냅샷을 로드하고 동일한 `flow_uuid` 아래에서 계속 기록합니다. 기록이 확장됩니다. +- `kickoff(restore_from_state_id=)` — **포크(fork)**: 제공된 UUID에 대한 최신 스냅샷을 로드하고 새 실행의 상태를 하이드레이트한 후, 새로운 `state.id`(자동 생성, 또는 `inputs["id"]`가 고정된 경우 그 값)를 할당합니다. 새 실행의 `@persist` 기록은 새로운 `state.id` 아래에 저장되며, 원본 플로우의 기록은 보존됩니다. + +```python +from crewai.flow.flow import Flow, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + id: str = "" + counter: int = 0 + +@persist +class CounterFlow(Flow[CounterState]): + @start() + def step(self): + self.state.counter += 1 + print(f"[id={self.state.id}] counter={self.state.counter}") + +# 실행 1: 새 상태, counter 0 -> 1, flow_1.state.id 아래에 저장됨 +flow_1 = CounterFlow() +flow_1.kickoff() + +# 포크: flow_1의 최신 스냅샷에서 하이드레이트하지만, 새 state.id를 사용 +flow_2 = CounterFlow() +flow_2.kickoff(restore_from_state_id=flow_1.state.id) +# flow_2.state.counter는 1(하이드레이트)로 시작하고, step()이 2로 증가시킵니다. +# flow_2.state.id != flow_1.state.id; flow_1의 기록은 변경되지 않습니다. +``` + +제공된 `restore_from_state_id`가 어떤 영속 상태와도 일치하지 않으면, kickoff는 조용히 기본 동작으로 폴백됩니다 — 기존 `inputs["id"]`의 미발견 동작과 동일합니다. `restore_from_state_id`를 `from_checkpoint`와 결합하면 `ValueError`가 발생합니다; 하나의 하이드레이션 소스를 선택하세요. 포크 중 `inputs["id"]`를 고정하면 다른 플로우와 영속 키를 공유하게 됩니다 — 일반적으로 `restore_from_state_id`만 사용하는 것이 좋습니다. + +### 작동 방식 + +1. **고유 상태 식별** + - 각 flow 상태에는 자동으로 고유한 UUID가 할당됩니다. + - 이 ID는 상태 업데이트 및 메소드 호출 시에도 유지됩니다. + - 구조화된 상태(Pydantic BaseModel)와 비구조화된 상태(딕셔너리) 모두를 지원합니다. + +2. **기본 SQLite 백엔드** + - SQLiteFlowPersistence는 기본 저장 백엔드입니다. + - 상태는 자동으로 로컬 SQLite 데이터베이스에 저장됩니다. + - 데이터베이스 작업 실패 시 명확한 메시지를 제공하는 견고한 오류 처리가 제공됩니다. + +3. **오류 처리** + - 데이터베이스 작업에 대한 포괄적인 오류 메시지가 제공됩니다. + - 저장 및 로드 중에 상태가 자동으로 검증됩니다. + - 지속성 작업에 문제가 발생할 경우 명확한 피드백을 제공합니다. + +### 중요한 고려사항 + +- **상태 유형**: 구조화된(Pydantic BaseModel) 상태와 비구조화된(딕셔너리) 상태 모두 지원됩니다 +- **자동 ID**: `id` 필드는 존재하지 않을 경우 자동으로 추가됩니다 +- **상태 복구**: 실패하거나 재시작된 flow는 이전 상태를 자동으로 불러올 수 있습니다 +- **커스텀 구현**: 특수한 저장소 요구 사항을 위해 직접 FlowPersistence 구현을 제공할 수 있습니다 + +### 기술적 이점 + +1. **저수준 접근을 통한 정밀한 제어** + - 고급 사용 사례를 위한 영속성 작업에 대한 직접 접근 + - 메서드 수준의 영속성 데코레이터를 통한 세밀한 제어 + - 내장된 상태 검사 및 디버깅 기능 + - 상태 변경 및 영속성 작업에 대한 완전한 가시성 + +2. **향상된 신뢰성** + - 시스템 장애 또는 재시작 후 자동 상태 복구 + - 데이터 무결성을 위한 트랜잭션 기반 상태 업데이트 + - 명확한 오류 메시지를 제공하는 포괄적인 오류 처리 + - 상태 저장 및 로드 작업 시 강력한 검증 + +3. **확장 가능한 아키텍처** + - FlowPersistence 인터페이스를 통한 사용자 정의 가능한 영속성 백엔드 + - SQLite를 넘어선 특수 저장 솔루션 지원 + - 구조화된(Pydantic) 상태와 비구조화(dict) 상태 모두와 호환 + - 기존 CrewAI 흐름 패턴과의 원활한 통합 + +영속성 시스템의 아키텍처는 기술적 정밀성과 맞춤화 옵션을 강조하여, 개발자가 내장된 신뢰성 기능의 이점을 누리면서 상태 관리에 대한 완전한 제어권을 유지할 수 있게 해줍니다. + +## 흐름 제어 + +### 조건부 로직: `or` + +Flows에서 `or_` 함수는 여러 메서드를 감지하고 지정된 메서드 중 하나에서 출력이 발생하면 리스너 메서드를 트리거합니다. + + + +```python Code +from crewai.flow.flow import Flow, listen, or_, start + +class OrExampleFlow(Flow): + + @start() + def start_method(self): + return "Hello from the start method" + + @listen(start_method) + def second_method(self): + return "Hello from the second method" + + @listen(or_(start_method, second_method)) + def logger(self, result): + print(f"Logger: {result}") + + + +flow = OrExampleFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +```text Output +Logger: Hello from the start method +Logger: Hello from the second method +``` + + + +![Flow Visual image](/images/crewai-flow-4.png) + +이 Flow를 실행하면, `logger` 메서드는 `start_method` 또는 `second_method`의 출력에 의해 트리거됩니다. +`or_` 함수는 여러 메서드를 감지하고 지정된 메서드 중 하나에서 출력이 발생하면 리스너 메서드를 트리거하는 데 사용됩니다. + +### 조건부 로직: `and` + +Flows에서 `and_` 함수는 여러 메서드를 리슨하고, 지정된 모든 메서드가 출력을 발생시킬 때만 리스너 메서드가 트리거되도록 합니다. + + + +```python Code +from crewai.flow.flow import Flow, and_, listen, start + +class AndExampleFlow(Flow): + + @start() + def start_method(self): + self.state["greeting"] = "Hello from the start method" + + @listen(start_method) + def second_method(self): + self.state["joke"] = "What do computers eat? Microchips." + + @listen(and_(start_method, second_method)) + def logger(self): + print("---- Logger ----") + print(self.state) + +flow = AndExampleFlow() +flow.plot() +flow.kickoff() +``` + +```text Output +---- Logger ---- +{'greeting': 'Hello from the start method', 'joke': 'What do computers eat? Microchips.'} +``` + + + +![Flow Visual image](/images/crewai-flow-5.png) + +이 Flow를 실행하면, `logger` 메서드는 `start_method`와 `second_method`가 모두 출력을 발생시켰을 때만 트리거됩니다. +`and_` 함수는 여러 메서드를 리슨하고, 지정된 모든 메서드가 출력을 발생시킬 때만 리스너 메서드를 트리거하는 데 사용됩니다. + +### Router + +Flows의 `@router()` 데코레이터를 사용하면 메서드의 출력값에 따라 조건부 라우팅 로직을 정의할 수 있습니다. +메서드의 출력에 따라 서로 다른 경로를 지정할 수 있어 실행 흐름을 동적으로 제어할 수 있습니다. + + + +```python Code +import random +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + success_flag: bool = False + +class RouterFlow(Flow[ExampleState]): + + @start() + def start_method(self): + print("Starting the structured flow") + random_boolean = random.choice([True, False]) + self.state.success_flag = random_boolean + + @router(start_method) + def second_method(self): + if self.state.success_flag: + return "success" + else: + return "failed" + + @listen("success") + def third_method(self): + print("Third method running") + + @listen("failed") + def fourth_method(self): + print("Fourth method running") + + +flow = RouterFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +```text Output +Starting the structured flow +Third method running +Fourth method running +``` + + + +![Flow Visual image](/images/crewai-flow-6.png) + +위 예제에서 `start_method`는 랜덤 불리언 값을 생성하여 state에 저장합니다. +`second_method`는 `@router()` 데코레이터를 사용해 불리언 값에 따라 조건부 라우팅 로직을 정의합니다. +불리언 값이 `True`이면 메서드는 `"success"`를 반환하고, `False`이면 `"failed"`를 반환합니다. +`third_method`와 `fourth_method`는 `second_method`의 출력값을 기다렸다가 반환된 값에 따라 실행됩니다. + +이 Flow를 실행하면, `start_method`에서 생성된 랜덤 불리언 값에 따라 출력값이 달라집니다. + +### Human in the Loop (인간 피드백) + + +`@human_feedback` 데코레이터는 **CrewAI 버전 1.8.0 이상**이 필요합니다. + + +`@human_feedback` 데코레이터는 인간의 피드백을 수집하기 위해 플로우 실행을 일시 중지하는 human-in-the-loop 워크플로우를 가능하게 합니다. 이는 승인 게이트, 품질 검토, 인간의 판단이 필요한 결정 지점에 유용합니다. + +```python Code +from crewai.flow.flow import Flow, start, listen +from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult + +class ReviewFlow(Flow): + @start() + @human_feedback( + message="이 콘텐츠를 승인하시겠습니까?", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + def generate_content(self): + return "검토할 콘텐츠..." + + @listen("approved") + def on_approval(self, result: HumanFeedbackResult): + print(f"승인됨! 피드백: {result.feedback}") + + @listen("rejected") + def on_rejection(self, result: HumanFeedbackResult): + print(f"거부됨. 이유: {result.feedback}") +``` + +`emit`이 지정되면, 인간의 자유 형식 피드백이 LLM에 의해 해석되어 지정된 outcome 중 하나로 매핑되고, 해당 `@listen` 데코레이터를 트리거합니다. + +라우팅 없이 단순히 피드백만 수집할 수도 있습니다: + +```python Code +@start() +@human_feedback(message="이 출력에 대한 코멘트가 있으신가요?") +def my_method(self): + return "검토할 출력" + +@listen(my_method) +def next_step(self, result: HumanFeedbackResult): + # result.feedback로 피드백에 접근 + # result.output으로 원래 출력에 접근 + pass +``` + +플로우 실행 중 수집된 모든 피드백은 `self.last_human_feedback` (가장 최근) 또는 `self.human_feedback_history` (리스트 형태의 모든 피드백)를 통해 접근할 수 있습니다. + +플로우에서의 인간 피드백에 대한 완전한 가이드는 비동기/논블로킹 피드백과 커스텀 프로바이더(Slack, 웹훅 등)를 포함하여 [Flow에서 인간 피드백](/ko/learn/human-feedback-in-flows)을 참조하세요. + +## 플로우에 에이전트 추가하기 + +에이전트는 플로우에 원활하게 통합할 수 있으며, 단순하고 집중된 작업 실행이 필요할 때 전체 Crew의 경량 대안으로 활용됩니다. 아래는 에이전트를 플로우 내에서 사용하여 시장 조사를 수행하는 예시입니다: + +```python +import asyncio +from typing import Any, Dict, List + +from crewai_tools import SerperDevTool +from pydantic import BaseModel, Field + +from crewai.agent import Agent +from crewai.flow.flow import Flow, listen, start + + +# Define a structured output format +class MarketAnalysis(BaseModel): + key_trends: List[str] = Field(description="List of identified market trends") + market_size: str = Field(description="Estimated market size") + competitors: List[str] = Field(description="Major competitors in the space") + + +# Define flow state +class MarketResearchState(BaseModel): + product: str = "" + analysis: MarketAnalysis | None = None + + +# Create a flow class +class MarketResearchFlow(Flow[MarketResearchState]): + @start() + def initialize_research(self) -> Dict[str, Any]: + print(f"Starting market research for {self.state.product}") + return {"product": self.state.product} + + @listen(initialize_research) + async def analyze_market(self) -> Dict[str, Any]: + # Create an Agent for market research + analyst = Agent( + role="Market Research Analyst", + goal=f"Analyze the market for {self.state.product}", + backstory="You are an experienced market analyst with expertise in " + "identifying market trends and opportunities.", + tools=[SerperDevTool()], + verbose=True, + ) + + # Define the research query + query = f""" + Research the market for {self.state.product}. Include: + 1. Key market trends + 2. Market size + 3. Major competitors + + Format your response according to the specified structure. + """ + + # Execute the analysis with structured output format + result = await analyst.kickoff_async(query, response_format=MarketAnalysis) + if result.pydantic: + print("result", result.pydantic) + else: + print("result", result) + + # Return the analysis to update the state + return {"analysis": result.pydantic} + + @listen(analyze_market) + def present_results(self, analysis) -> None: + print("\nMarket Analysis Results") + print("=====================") + + if isinstance(analysis, dict): + # If we got a dict with 'analysis' key, extract the actual analysis object + market_analysis = analysis.get("analysis") + else: + market_analysis = analysis + + if market_analysis and isinstance(market_analysis, MarketAnalysis): + print("\nKey Market Trends:") + for trend in market_analysis.key_trends: + print(f"- {trend}") + + print(f"\nMarket Size: {market_analysis.market_size}") + + print("\nMajor Competitors:") + for competitor in market_analysis.competitors: + print(f"- {competitor}") + else: + print("No structured analysis data available.") + print("Raw analysis:", analysis) + + +# Usage example +async def run_flow(): + flow = MarketResearchFlow() + flow.plot("MarketResearchFlowPlot") + result = await flow.kickoff_async(inputs={"product": "AI-powered chatbots"}) + return result + + +# Run the flow +if __name__ == "__main__": + asyncio.run(run_flow()) +``` + +![Flow Visual image](/images/crewai-flow-7.png) + +이 예시는 플로우에서 에이전트를 사용할 때의 몇 가지 주요 기능을 보여줍니다: + +1. **구조화된 출력**: Pydantic 모델을 사용하여 예상 출력 형식(`MarketAnalysis`)을 정의함으로써 플로우 전체에서 타입 안정성과 구조화된 데이터를 보장합니다. + +2. **상태 관리**: 플로우 상태(`MarketResearchState`)는 단계 간의 컨텍스트를 유지하고 입력과 출력을 모두 저장합니다. + +3. **도구 통합**: 에이전트는 기능 강화를 위해 `WebsiteSearchTool`과 같은 도구를 사용할 수 있습니다. + +## Flows에 Crews 추가하기 + +CrewAI에서 여러 crews로 flow를 생성하는 것은 간단합니다. + +다음 명령어를 실행하여 여러 crews가 포함된 flow를 생성하는 데 필요한 모든 스캐폴딩이 포함된 새 CrewAI 프로젝트를 생성할 수 있습니다. + +```bash +crewai create flow name_of_flow +``` + +이 명령어는 필요한 폴더 구조를 갖춘 새 CrewAI 프로젝트를 생성합니다. 생성된 프로젝트에는 이미 동작 중인 미리 구축된 crew인 `poem_crew`가 포함되어 있습니다. 시작용 embedded crew는 클래식 Python/YAML 레이아웃을 사용하며, `crewai create crew`로 만든 새 독립 실행형 crew는 JSON-first 레이아웃을 사용합니다. + +### 폴더 구조 + +`crewai create flow name_of_flow` 명령을 실행하면 다음과 유사한 폴더 구조를 볼 수 있습니다: + +| 디렉터리/파일 | 설명 | +| :--------------------- | :----------------------------------------------------------------- | +| `name_of_flow/` | flow의 루트 디렉터리입니다. | +| ├── `crews/` | 특정 crew에 대한 디렉터리를 포함합니다. | +| │ └── `poem_crew/` | "poem_crew"의 설정 및 스크립트가 포함된 디렉터리입니다. | +| │ ├── `config/` | "poem_crew"의 설정 파일 디렉터리입니다. | +| │ │ ├── `agents.yaml` | "poem_crew"의 agent를 정의하는 YAML 파일입니다. | +| │ │ └── `tasks.yaml` | "poem_crew"의 task를 정의하는 YAML 파일입니다. | +| │ ├── `poem_crew.py` | "poem_crew"의 기능을 위한 스크립트입니다. | +| ├── `tools/` | flow에서 사용되는 추가 도구를 위한 디렉터리입니다. | +| │ └── `custom_tool.py` | 사용자 정의 도구 구현 파일입니다. | +| ├── `main.py` | flow를 실행하는 메인 스크립트입니다. | +| ├── `README.md` | 프로젝트 설명 및 안내 문서입니다. | +| ├── `pyproject.toml` | 프로젝트의 종속성 및 설정을 위한 구성 파일입니다. | +| └── `.gitignore` | 버전 관리에서 무시할 파일과 디렉터리를 지정합니다. | + +### 크루 빌드하기 + +`crews` 폴더에서는 여러 개의 크루를 정의할 수 있습니다. 각 크루는 자체 폴더를 가지며, 설정 파일과 크루 정의 파일을 포함합니다. 예를 들어, `poem_crew` 폴더에는 다음과 같은 파일이 있습니다: + +- `config/agents.yaml`: 크루의 agent를 정의합니다. +- `config/tasks.yaml`: 크루의 task를 정의합니다. +- `poem_crew.py`: agent, task, 그리고 크루 자체를 포함한 crew 정의가 들어 있습니다. + +`poem_crew`를 복사, 붙여넣기, 그리고 편집하여 다른 클래식 embedded crew를 생성할 수 있습니다. + +JSON-first embedded crew는 `crew.jsonc`와 `agents/*.jsonc`가 있는 폴더를 사용하세요: + +```text +crews/ +└── research_crew/ + ├── agents/ + │ └── researcher.jsonc + └── crew.jsonc +``` + +그런 다음 Flow 단계에서 로드합니다: + +```python +from pathlib import Path +from crewai.project import load_crew + +crew, default_inputs = load_crew( + Path(__file__).parent / "crews" / "research_crew" / "crew.jsonc" +) +result = crew.kickoff(inputs={**default_inputs, "topic": "AI Agents"}) +``` + +### `main.py`에서 Crew 연결하기 + +`main.py` 파일은 flow를 생성하고 crew들을 서로 연결하는 곳입니다. `Flow` 클래스를 사용하고, `@start`와 `@listen` 데코레이터를 사용하여 실행 흐름을 지정하여 flow를 정의할 수 있습니다. + +다음은 `main.py` 파일에서 `poem_crew`를 연결하는 예제입니다: + +```python Code +#!/usr/bin/env python +from random import randint + +from pydantic import BaseModel +from crewai.flow.flow import Flow, listen, start +from .crews.poem_crew.poem_crew import PoemCrew + +class PoemState(BaseModel): + sentence_count: int = 1 + poem: str = "" + +class PoemFlow(Flow[PoemState]): + + @start() + def generate_sentence_count(self): + print("Generating sentence count") + self.state.sentence_count = randint(1, 5) + + @listen(generate_sentence_count) + def generate_poem(self): + print("Generating poem") + result = PoemCrew().crew().kickoff(inputs={"sentence_count": self.state.sentence_count}) + + print("Poem generated", result.raw) + self.state.poem = result.raw + + @listen(generate_poem) + def save_poem(self): + print("Saving poem") + with open("poem.txt", "w") as f: + f.write(self.state.poem) + +def kickoff(): + poem_flow = PoemFlow() + poem_flow.kickoff() + + +def plot(): + poem_flow = PoemFlow() + poem_flow.plot("PoemFlowPlot") + +if __name__ == "__main__": + kickoff() + plot() +``` + +이 예제에서 `PoemFlow` 클래스는 문장 수를 생성하고, `PoemCrew`를 사용하여 시를 생성한 후, 시를 파일에 저장하는 flow를 정의합니다. 이 flow는 `kickoff()` 메서드를 호출하여 시작됩니다. `plot()` 메서드로 PoemFlowPlot이 생성됩니다. + +![Flow Visual image](/images/crewai-flow-8.png) + +### 플로우 실행하기 + +(선택 사항) 플로우를 실행하기 전에, 다음 명령어를 실행하여 의존성을 설치할 수 있습니다: + +```bash +crewai install +``` + +모든 의존성이 설치되면, 다음 명령어를 실행하여 가상 환경을 활성화해야 합니다: + +```bash +source .venv/bin/activate +``` + +가상 환경을 활성화한 후, 아래 명령어 중 하나를 실행하여 플로우를 실행할 수 있습니다: + +```bash +crewai run +``` + +또는 + +```bash +uv run kickoff +``` + +플로우가 실행되면, 콘솔에서 출력을 확인할 수 있습니다. + +## 플롯 플로우 + +AI 워크플로우를 시각화하면 플로우의 구조와 실행 경로에 대한 중요한 인사이트를 얻을 수 있습니다. CrewAI는 플로우의 인터랙티브 플롯을 생성할 수 있는 강력한 시각화 도구를 제공하여 AI 워크플로우를 보다 쉽게 이해하고 최적화할 수 있도록 도와줍니다. + +### 플롯(Plots)이란 무엇인가요? + +CrewAI에서 플롯(Plots)은 AI 워크플로우의 그래픽 표현입니다. 플롯은 다양한 태스크와 그들의 연결, 그리고 태스크 간 데이터 흐름을 시각적으로 보여줍니다. 이러한 시각화는 작업 순서를 이해하고, 병목 현상을 식별하며, 워크플로우 논리가 기대에 부합하는지 확인하는 데 도움이 됩니다. + +### 플롯 생성 방법 + +CrewAI는 플로우의 플롯을 생성하는 두 가지 편리한 방법을 제공합니다: + +#### 옵션 1: `plot()` 메서드 사용하기 + +flow 인스턴스와 직접 작업하는 경우, flow 객체에서 `plot()` 메서드를 호출하여 플롯을 생성할 수 있습니다. 이 메서드는 flow의 인터랙티브 플롯이 포함된 HTML 파일을 생성합니다. + +```python Code +# Assuming you have a flow instance +flow.plot("my_flow_plot") +``` + +이렇게 하면 현재 디렉토리에 `my_flow_plot.html`이라는 파일이 생성됩니다. 이 파일을 웹 브라우저에서 열어 인터랙티브 플롯을 볼 수 있습니다. + +#### 옵션 2: 커맨드 라인 사용 + +구조화된 CrewAI 프로젝트 내에서 작업 중이라면 커맨드 라인을 사용하여 플롯을 생성할 수 있습니다. 이는 전체 플로우 설정을 시각화하고자 하는 대규모 프로젝트에서 특히 유용합니다. + +```bash +crewai flow plot +``` + +이 명령은 플로우의 플롯이 포함된 HTML 파일을 생성하며, 이는 `plot()` 메서드와 유사합니다. 파일은 프로젝트 디렉터리에 저장되며, 웹 브라우저에서 열어 플로우를 탐색할 수 있습니다. + +### 플롯 이해하기 + +생성된 플롯은 flow 내의 작업을 나타내는 노드와 실행 흐름을 나타내는 방향성이 있는 엣지를 표시합니다. 플롯은 인터랙티브하게 제공되어, 확대/축소를 하거나 노드 위에 마우스를 올려 추가 정보를 볼 수 있습니다. + +flow를 시각화하면 워크플로의 구조를 더욱 명확하게 이해할 수 있어 디버깅, 최적화, 그리고 AI 프로세스를 다른 사람들에게 설명하는 데 도움이 됩니다. + +### 결론 + +플로우를 시각적으로 표현하는 것은 CrewAI의 강력한 기능으로, 복잡한 AI 워크플로우를 설계하고 관리하는 능력을 크게 향상시켜줍니다. `plot()` 메서드나 커맨드 라인 중 어떤 방법을 사용하더라도, 플롯을 생성하면 워크플로우의 시각적 표현을 얻을 수 있어 개발과 발표 모두에 도움이 됩니다. + +## 다음 단계 + +추가적인 flow 예제를 살펴보고 싶으시다면, 저희 examples 레포지토리에서 다양한 추천 예제를 확인하실 수 있습니다. 아래는 각각 고유한 사용 사례를 보여주는 네 가지 구체적인 flow 예제로, 현재 문제 유형에 맞는 예시를 찾는 데 도움이 될 것입니다: + +1. **이메일 자동 응답자 Flow**: 이 예제는 백그라운드 작업이 계속 실행되면서 이메일 응답을 자동화하는 무한 루프를 보여줍니다. 수동 개입 없이 반복적으로 수행해야 하는 작업에 적합한 사용 사례입니다. [예제 보기](https://github.com/crewAIInc/crewAI-examples/tree/main/email_auto_responder_flow) + +2. **리드 점수 Flow**: 이 flow 예제는 human-in-the-loop 피드백을 추가하고 router를 사용하여 다양한 조건 분기를 처리하는 방법을 보여줍니다. 워크플로우에 동적 의사결정과 인간의 관리·감독을 통합하는 방식을 확인할 수 있는 훌륭한 예시입니다. [예제 보기](https://github.com/crewAIInc/crewAI-examples/tree/main/lead-score-flow) + +3. **책 집필 Flow**: 이 예제는 여러 crew를 연속적으로 연결하는 데 탁월하며, 한 crew의 출력 결과가 다른 crew에 의해 사용됩니다. 구체적으로, 한 crew가 전체 책의 개요를 작성하고, 다른 crew가 그 개요를 바탕으로 챕터를 생성합니다. 결국 모든 것이 연결되어 완성된 책이 만들어집니다. 여러 작업 간 조율이 필요한 복잡한 다단계 프로세스에 적합한 flow입니다. [예제 보기](https://github.com/crewAIInc/crewAI-examples/tree/main/write_a_book_with_flows) + +4. **미팅 어시스턴트 Flow**: 이 flow는 하나의 이벤트가 여러 후속 작업을 트리거하도록 브로드캐스트하는 방법을 보여줍니다. 예를 들어, 미팅이 끝난 후 Trello 보드를 업데이트하고 Slack 메시지를 전송하며 결과를 저장할 수 있습니다. 하나의 이벤트로부터 여러 결과를 처리하는 좋은 예시로, 포괄적인 작업 관리 및 알림 시스템에 이상적입니다. [예제 보기](https://github.com/crewAIInc/crewAI-examples/tree/main/meeting_assistant_flow) + +이 예제들을 통해 반복되는 작업 자동화부터 동적 의사결정과 인간 피드백이 포함된 복잡한 다단계 프로세스 관리에 이르기까지 다양한 사용 사례에서 CrewAI Flows를 어떻게 활용할 수 있는지에 대한 통찰력을 얻을 수 있습니다. + +또한, 아래의 CrewAI에서 flows를 사용하는 방법에 대한 YouTube 영상을 확인해보세요! + + + +## 플로우 실행하기 + +플로우를 실행하는 방법에는 두 가지가 있습니다: + +### Flow API 사용하기 + +플로우를 프로그래밍 방식으로 실행하려면, 플로우 클래스의 인스턴스를 생성하고 `kickoff()` 메서드를 호출하면 됩니다: + +```python +flow = ExampleFlow() +result = flow.kickoff() +``` + +### CLI 사용하기 + +버전 0.103.0부터 `crewai run` 명령어를 사용하여 flow를 실행할 수 있습니다: + +```shell +crewai run +``` + +이 명령어는 프로젝트가 pyproject.toml의 `type = "flow"` 설정을 기반으로 flow인지 자동으로 감지하여 해당 방식으로 실행합니다. 명령줄에서 flow를 실행하는 권장 방법입니다. + +레거시 `crewai flow kickoff` 명령어는 deprecated되었습니다. crew와 flow 모두 `crewai run`을 사용하세요. diff --git a/docs/v1.15.13/ko/concepts/knowledge.mdx b/docs/v1.15.13/ko/concepts/knowledge.mdx new file mode 100644 index 0000000000..92f688392e --- /dev/null +++ b/docs/v1.15.13/ko/concepts/knowledge.mdx @@ -0,0 +1,962 @@ +--- +title: Knowledge +description: CrewAI에서 knowledge란 무엇이며 어떻게 사용하는지 알아봅니다. +icon: book +mode: "wide" +--- + +## 개요 + +Knowledge in CrewAI는 AI 에이전트가 작업 중에 외부 정보 소스에 접근하고 이를 활용할 수 있게 해주는 강력한 시스템입니다. +이는 에이전트에게 작업할 때 참고할 수 있는 참조 도서관을 제공하는 것과 같습니다. + + + Knowledge를 사용함으로써 얻는 주요 이점: + - 에이전트에게 도메인 특화 정보를 제공 + - 실제 데이터를 통한 의사 결정 지원 + - 대화 전체의 맥락 유지 + - 응답을 사실 기반 정보에 근거 + + +## 빠른 시작 예제 + + +파일 기반 Knowledge Sources의 경우, 프로젝트의 루트에 `knowledge` 디렉토리를 생성하고 그 안에 파일을 배치해야 합니다. +또한, 소스를 생성할 때는 `knowledge` 디렉토리로부터의 상대 경로를 사용하세요. + + +### 기본 문자열 지식 예제 + +```python Code +from crewai import Agent, Task, Crew, Process, LLM +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create a knowledge source +content = "Users name is John. He is 30 years old and lives in San Francisco." +string_source = StringKnowledgeSource(content=content) + +# Create an LLM with a temperature of 0 to ensure deterministic outputs +llm = LLM(model="gpt-4o-mini", temperature=0) + +# Create an agent with the knowledge store +agent = Agent( + role="About User", + goal="You know everything about the user.", + backstory="You are a master at understanding people and their preferences.", + verbose=True, + allow_delegation=False, + llm=llm, +) + +task = Task( + description="Answer the following questions about the user: {question}", + expected_output="An answer to the question.", + agent=agent, +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True, + process=Process.sequential, + knowledge_sources=[string_source], # Enable knowledge by adding the sources here +) + +result = crew.kickoff(inputs={"question": "What city does John live in and how old is he?"}) +``` + +### 웹 콘텐츠 지식 예시 + + + 다음 예시가 작동하려면 `docling`을 설치해야 합니다: `uv add docling` + + +```python Code +from crewai import LLM, Agent, Crew, Process, Task +from crewai.knowledge.source.crew_docling_source import CrewDoclingSource + +# Create a knowledge source from web content +content_source = CrewDoclingSource( + file_paths=[ + "https://lilianweng.github.io/posts/2024-11-28-reward-hacking", + "https://lilianweng.github.io/posts/2024-07-07-hallucination", + ], +) + +# Create an LLM with a temperature of 0 to ensure deterministic outputs +llm = LLM(model="gpt-4o-mini", temperature=0) + +# Create an agent with the knowledge store +agent = Agent( + role="About papers", + goal="You know everything about the papers.", + backstory="You are a master at understanding papers and their content.", + verbose=True, + allow_delegation=False, + llm=llm, +) + +task = Task( + description="Answer the following questions about the papers: {question}", + expected_output="An answer to the question.", + agent=agent, +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True, + process=Process.sequential, + knowledge_sources=[content_source], +) + +result = crew.kickoff( + inputs={"question": "What is the reward hacking paper about? Be sure to provide sources."} +) +``` + +## 지원되는 Knowledge Sources + +CrewAI는 다양한 유형의 knowledge source를 기본적으로 지원합니다: + + + + - 원시 문자열 + - 텍스트 파일 (.txt) + - PDF 문서 + + + - CSV 파일 + - 엑셀 스프레드시트 + - JSON 문서 + + + +### 텍스트 파일 지식 소스 +```python +from crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource + +text_source = TextFileKnowledgeSource( + file_paths=["document.txt", "another.txt"] +) +``` + +### PDF 지식 소스 +```python +from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource + +pdf_source = PDFKnowledgeSource( + file_paths=["document.pdf", "another.pdf"] +) +``` + +### CSV 지식 소스 +```python +from crewai.knowledge.source.csv_knowledge_source import CSVKnowledgeSource + +csv_source = CSVKnowledgeSource( + file_paths=["data.csv"] +) +``` + +### Excel 지식 소스 +```python +from crewai.knowledge.source.excel_knowledge_source import ExcelKnowledgeSource + +excel_source = ExcelKnowledgeSource( + file_paths=["spreadsheet.xlsx"] +) +``` + +### JSON 지식 소스 +```python +from crewai.knowledge.source.json_knowledge_source import JSONKnowledgeSource + +json_source = JSONKnowledgeSource( + file_paths=["data.json"] +) +``` + + + 반드시 ./knowledge 폴더를 생성해 주세요. 모든 소스 파일(예: .txt, .pdf, .xlsx, .json)은 중앙 집중식 관리를 위해 이 폴더에 보관해야 합니다. + + +## Agent vs Crew Knowledge: 완벽 가이드 + + +**Knowledge 레벨 이해하기**: CrewAI는 agent와 crew 두 가지 레벨의 knowledge를 지원합니다. 이 섹션에서는 각각이 어떻게 동작하는지, 언제 초기화되는지, 그리고 dependency에 대한 일반적인 오해를 명확히 설명합니다. + + +### 지식 초기화가 실제로 작동하는 방식 + +다음은 지식을 사용할 때 실제로 발생하는 일입니다: + +#### 에이전트 수준 지식 (독립적) + +```python +from crewai import Agent, Task, Crew +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Agent with its own knowledge - NO crew knowledge needed +specialist_knowledge = StringKnowledgeSource( + content="Specialized technical information for this agent only" +) + +specialist_agent = Agent( + role="Technical Specialist", + goal="Provide technical expertise", + backstory="Expert in specialized technical domains", + knowledge_sources=[specialist_knowledge] # Agent-specific knowledge +) + +task = Task( + description="Answer technical questions", + agent=specialist_agent, + expected_output="Technical answer" +) + +# No crew-level knowledge required +crew = Crew( + agents=[specialist_agent], + tasks=[task] +) + +result = crew.kickoff() # Agent knowledge works independently +``` + +#### `crew.kickoff()` 중에 일어나는 일 + +`crew.kickoff()`를 호출하면 다음과 같은 순서로 동작합니다: + +```python +# During kickoff +for agent in self.agents: + agent.crew = self # Agent gets reference to crew + agent.set_knowledge(crew_embedder=self.embedder) # Agent knowledge initialized + agent.create_agent_executor() +``` + +#### 스토리지 독립성 + +각 knowledge 수준은 독립적인 스토리지 컬렉션을 사용합니다: + +```python +# Agent knowledge storage +agent_collection_name = agent.role # e.g., "Technical Specialist" + +# Crew knowledge storage +crew_collection_name = "crew" + +# Both stored in same ChromaDB instance but different collections +# Path: ~/.local/share/CrewAI/{project}/knowledge/ +# ├── crew/ # Crew knowledge collection +# ├── Technical Specialist/ # Agent knowledge collection +# └── Another Agent Role/ # Another agent's collection +``` + +### 전체 작동 예제 + +#### 예시 1: Agent-Only Knowledge +```python +from crewai import Agent, Task, Crew +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Agent-specific knowledge +agent_knowledge = StringKnowledgeSource( + content="Agent-specific information that only this agent needs" +) + +agent = Agent( + role="Specialist", + goal="Use specialized knowledge", + backstory="Expert with specific knowledge", + knowledge_sources=[agent_knowledge], + embedder={ # Agent can have its own embedder + "provider": "openai", + "config": {"model": "text-embedding-3-small"} + } +) + +task = Task( + description="Answer using your specialized knowledge", + agent=agent, + expected_output="Answer based on agent knowledge" +) + +# No crew knowledge needed +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() # Works perfectly +``` + +#### 예시 2: 에이전트 및 크루 지식 모두 + +```python +# Crew-wide knowledge (shared by all agents) +crew_knowledge = StringKnowledgeSource( + content="Company policies and general information for all agents" +) + +# Agent-specific knowledge +specialist_knowledge = StringKnowledgeSource( + content="Technical specifications only the specialist needs" +) + +specialist = Agent( + role="Technical Specialist", + goal="Provide technical expertise", + backstory="Technical expert", + knowledge_sources=[specialist_knowledge] # Agent-specific +) + +generalist = Agent( + role="General Assistant", + goal="Provide general assistance", + backstory="General helper" + # No agent-specific knowledge +) + +crew = Crew( + agents=[specialist, generalist], + tasks=[...], + knowledge_sources=[crew_knowledge] # Crew-wide knowledge +) + +# Result: +# - specialist gets: crew_knowledge + specialist_knowledge +# - generalist gets: crew_knowledge only +``` + +#### 예제 3: 서로 다른 지식을 가진 다중 에이전트 +```python +# Different knowledge for different agents +sales_knowledge = StringKnowledgeSource(content="Sales procedures and pricing") +tech_knowledge = StringKnowledgeSource(content="Technical documentation") +support_knowledge = StringKnowledgeSource(content="Support procedures") + +sales_agent = Agent( + role="Sales Representative", + knowledge_sources=[sales_knowledge], + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}} +) + +tech_agent = Agent( + role="Technical Expert", + knowledge_sources=[tech_knowledge], + embedder={"provider": "ollama", "config": {"model": "mxbai-embed-large"}} +) + +support_agent = Agent( + role="Support Specialist", + knowledge_sources=[support_knowledge] + # Will use crew embedder as fallback +) + +crew = Crew( + agents=[sales_agent, tech_agent, support_agent], + tasks=[...], + embedder={ # Fallback embedder for agents without their own + "provider": "google", + "config": {"model": "text-embedding-004"} + } +) + +# Each agent gets only their specific knowledge +# Each can use different embedding providers +``` + + +벡터 데이터베이스에서 도구를 사용한 검색과 달리, 사전에 지식이 탑재된 에이전트는 검색 퍼소나나 태스크가 필요하지 않습니다. +에이전트나 crew가 동작하는 데 필요한 관련 지식 소스만 추가하면 됩니다. + +지식 소스는 에이전트 또는 crew 레벨에 추가할 수 있습니다. +crew 레벨 지식 소스는 **crew 내 모든 에이전트**가 사용하게 됩니다. +에이전트 레벨 지식 소스는 해당 지식이 사전 탑재된 **특정 에이전트**만 사용하게 됩니다. + + +## Knowledge 구성 + +crew 또는 agent에 대해 knowledge 구성을 할 수 있습니다. + +```python Code +from crewai.knowledge.knowledge_config import KnowledgeConfig + +knowledge_config = KnowledgeConfig(results_limit=10, score_threshold=0.5) + +agent = Agent( + ... + knowledge_config=knowledge_config +) +``` + + + `results_limit`: 반환할 관련 문서의 개수입니다. 기본값은 3입니다. + `score_threshold`: 문서가 관련성이 있다고 간주되기 위한 최소 점수입니다. 기본값은 0.35입니다. + + +## 지원되는 Knowledge 매개변수 + + + 저장 및 쿼리할 콘텐츠를 제공하는 knowledge source들의 리스트입니다. PDF, CSV, Excel, JSON, 텍스트 파일 또는 문자열 콘텐츠를 포함할 수 있습니다. + + + knowledge가 저장될 컬렉션의 이름입니다. 서로 다른 knowledge 세트를 식별하는 데 사용됩니다. 제공하지 않을 경우 기본값은 "knowledge"입니다. + + +knowledge가 저장되고 검색되는 방식을 관리하기 위한 커스텀 저장소 구성입니다. 별도로 제공하지 않는 경우 기본 storage가 생성됩니다. + + +## 지식 저장 투명성 + + +**지식 저장 이해하기**: CrewAI는 ChromaDB를 사용하여 벡터 저장소에 지식 소스를 플랫폼별 디렉토리에 자동으로 저장합니다. 이러한 위치와 기본값을 이해하면 프로덕션 배포, 디버깅, 저장소 관리에 도움이 됩니다. + + +### CrewAI가 Knowledge 파일을 저장하는 위치 + +기본적으로 CrewAI는 memory와 동일한 저장 시스템을 사용하여, knowledge를 플랫폼별 디렉터리에 저장합니다. + +#### 플랫폼별 기본 저장 위치 + +**macOS:** +``` +~/Library/Application Support/CrewAI/{project_name}/ +└── knowledge/ # Knowledge ChromaDB files + ├── chroma.sqlite3 # ChromaDB metadata + ├── {collection_id}/ # Vector embeddings + └── knowledge_{collection}/ # Named collections +``` + +**Linux:** +``` +~/.local/share/CrewAI/{project_name}/ +└── knowledge/ + ├── chroma.sqlite3 + ├── {collection_id}/ + └── knowledge_{collection}/ +``` + +**Windows:** +``` +C:\Users\{username}\AppData\Local\CrewAI\{project_name}\ +└── knowledge\ + ├── chroma.sqlite3 + ├── {collection_id}\ + └── knowledge_{collection}\ +``` + +### 지식 저장 위치 찾기 + +CrewAI가 지식 파일을 저장하는 위치를 정확히 확인하려면: + +```python +from crewai.utilities.paths import db_storage_path +import os + +# Get the knowledge storage path +knowledge_path = os.path.join(db_storage_path(), "knowledge") +print(f"Knowledge storage location: {knowledge_path}") + +# List knowledge collections and files +if os.path.exists(knowledge_path): + print("\nKnowledge storage contents:") + for item in os.listdir(knowledge_path): + item_path = os.path.join(knowledge_path, item) + if os.path.isdir(item_path): + print(f"📁 Collection: {item}/") + # Show collection contents + try: + for subitem in os.listdir(item_path): + print(f" └── {subitem}") + except PermissionError: + print(f" └── (permission denied)") + else: + print(f"📄 {item}") +else: + print("No knowledge storage found yet.") +``` + +### 지식 저장 위치 제어 + +#### 옵션 1: 환경 변수 (권장) +```python +import os +from crewai import Crew + +# Set custom storage location for all CrewAI data +os.environ["CREWAI_STORAGE_DIR"] = "./my_project_storage" + +# All knowledge will now be stored in ./my_project_storage/knowledge/ +crew = Crew( + agents=[...], + tasks=[...], + knowledge_sources=[...] +) +``` + +#### 옵션 2: 사용자 지정 Knowledge 저장소 +```python +from crewai.knowledge.storage.knowledge_storage import KnowledgeStorage +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create custom storage with specific embedder +custom_storage = KnowledgeStorage( + embedder={ + "provider": "ollama", + "config": {"model": "mxbai-embed-large"} + }, + collection_name="my_custom_knowledge" +) + +# Use with knowledge sources +knowledge_source = StringKnowledgeSource( + content="Your knowledge content here" +) +knowledge_source.storage = custom_storage +``` + +#### 옵션 3: 프로젝트별 Knowledge 저장소 +```python +import os +from pathlib import Path + +# Store knowledge in project directory +project_root = Path(__file__).parent +knowledge_dir = project_root / "knowledge_storage" + +os.environ["CREWAI_STORAGE_DIR"] = str(knowledge_dir) + +# Now all knowledge will be stored in your project directory +``` + +### 기본 임베딩 제공자 동작 + + +**기본 임베딩 제공자**: CrewAI는 다른 LLM 제공자를 사용할 때도 지식 저장을 위해 기본적으로 OpenAI 임베딩(`text-embedding-3-small`)을 사용합니다. 설정에 맞게 쉽게 이 옵션을 커스터마이즈할 수 있습니다. + + +#### 기본 동작 이해하기 +```python +from crewai import Agent, Crew, LLM +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# When using Claude as your LLM... +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + llm=LLM(provider="anthropic", model="claude-3-sonnet") # Using Claude +) + +# CrewAI will still use OpenAI embeddings by default for knowledge +# This ensures consistency but may not match your LLM provider preference +knowledge_source = StringKnowledgeSource(content="Research data...") + +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source] + # Default: Uses OpenAI embeddings even with Claude LLM +) +``` + +#### 지식 임베딩 공급자 사용자 정의 +```python +# Option 1: Voyage AI 사용 (Claude 사용자에게 Anthropic이 권장) +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source], + embedder={ + "provider": "voyageai", # Claude 사용자에게 권장 + "config": { + "api_key": "your-voyage-api-key", + "model": "voyage-3" # 최고 품질을 원하면 "voyage-3-large" 사용 + } + } +) + +# Option 2: 로컬 임베딩 사용 (외부 API 호출 없음) +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source], + embedder={ + "provider": "ollama", + "config": { + "model": "mxbai-embed-large", + "url": "http://localhost:11434/api/embeddings" + } + } +) + +# Option 3: 에이전트 수준의 임베딩 사용자 정의 +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + knowledge_sources=[knowledge_source], + embedder={ + "provider": "google", + "config": { + "model": "models/text-embedding-004", + "api_key": "your-google-key" + } + } +) +``` + +#### Azure OpenAI 임베딩 구성 + +Azure OpenAI 임베딩을 사용할 때: +1. 먼저 Azure 플랫폼에 임베딩 모델을 배포했는지 확인하세요. +2. 그런 다음 다음과 같은 구성을 사용해야 합니다: + +```python +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + knowledge_sources=[knowledge_source], + embedder={ + "provider": "azure", + "config": { + "api_key": "your-azure-api-key", + "model": "text-embedding-ada-002", # change to the model you are using and is deployed in Azure + "api_base": "https://your-azure-endpoint.openai.azure.com/", + "api_version": "2024-02-01" + } + } +) +``` + +## 고급 기능 + +### 쿼리 리라이팅 + +CrewAI는 지식 검색을 최적화하기 위해 지능형 쿼리 리라이팅 메커니즘을 구현합니다. 에이전트가 지식 소스를 검색해야 할 때, 원시 태스크 프롬프트는 자동으로 더 효과적인 검색 쿼리로 변환됩니다. + +#### 쿼리 재작성 방식 + +1. 에이전트가 knowledge 소스를 사용할 수 있을 때 작업을 실행하면 `_get_knowledge_search_query` 메서드가 트리거됩니다. +2. 에이전트의 LLM을 사용하여 원래 작업 프롬프트를 최적화된 검색 쿼리로 변환합니다. +3. 이 최적화된 쿼리는 knowledge 소스에서 관련 정보를 검색하는 데 사용됩니다. + +#### 쿼리 리라이트(Query Rewriting)의 이점 + + + + 주요 개념에 집중하고 불필요한 내용을 제거함으로써, 쿼리 리라이트는 보다 관련성 높은 정보를 검색할 수 있게 도와줍니다. + + + 리라이트된 쿼리는 벡터 데이터베이스 검색을 위해 더욱 구체적이고 컨텍스트를 인식할 수 있도록 설계되어 있습니다. + + + +#### 예시 + +```python +# Original task prompt +task_prompt = "Answer the following questions about the user's favorite movies: What movie did John watch last week? Format your answer in JSON." + +# Behind the scenes, this might be rewritten as: +rewritten_query = "What movies did John watch last week?" +``` + +재작성된 쿼리는 핵심 정보 요구에 더 집중하며, 출력 형식에 대한 불필요한 지시사항을 제거합니다. + + + 이 메커니즘은 완전히 자동으로 동작하며 사용자가 별도의 설정을 할 필요가 없습니다. agent의 LLM을 사용하여 쿼리 재작성을 수행하므로, 더 강력한 LLM을 사용할 경우 재작성된 쿼리의 품질이 향상될 수 있습니다. + + +### Knowledge 이벤트 + +CrewAI는 knowledge 검색 과정에서 이벤트를 발생시키며, 이벤트 시스템을 사용하여 이를 감지할 수 있습니다. 이러한 이벤트를 통해 에이전트가 knowledge를 어떻게 검색하고 사용하는지 모니터링, 디버깅, 분석할 수 있습니다. + +#### 사용 가능한 Knowledge 이벤트 + +- **KnowledgeRetrievalStartedEvent**: 에이전트가 소스에서 knowledge를 검색하기 시작할 때 발생 +- **KnowledgeRetrievalCompletedEvent**: knowledge 검색이 완료되었을 때 발생하며, 사용된 쿼리와 검색된 콘텐츠를 포함 +- **KnowledgeQueryStartedEvent**: knowledge 소스에 쿼리를 시작할 때 발생 +- **KnowledgeQueryCompletedEvent**: 쿼리가 성공적으로 완료되었을 때 발생 +- **KnowledgeQueryFailedEvent**: knowledge 소스에 대한 쿼리가 실패했을 때 발생 +- **KnowledgeSearchQueryFailedEvent**: 검색 쿼리가 실패했을 때 발생 + +#### 예시: Knowledge Retrieval 모니터링 + +```python +from crewai.events import ( + KnowledgeRetrievalStartedEvent, + KnowledgeRetrievalCompletedEvent, + BaseEventListener, +) + +class KnowledgeMonitorListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(KnowledgeRetrievalStartedEvent) + def on_knowledge_retrieval_started(source, event): + print(f"Agent '{event.agent.role}' started retrieving knowledge") + + @crewai_event_bus.on(KnowledgeRetrievalCompletedEvent) + def on_knowledge_retrieval_completed(source, event): + print(f"Agent '{event.agent.role}' completed knowledge retrieval") + print(f"Query: {event.query}") + print(f"Retrieved {len(event.retrieved_knowledge)} knowledge chunks") + +# Create an instance of your listener +knowledge_monitor = KnowledgeMonitorListener() +``` + +이벤트 사용에 대한 자세한 내용은 [이벤트 리스너](/ko/concepts/event-listener) 문서를 참고하세요. + +### 맞춤형 지식 소스 + +CrewAI를 사용하면 `BaseKnowledgeSource` 클래스를 확장하여 모든 유형의 데이터에 대한 맞춤형 지식 소스를 만들 수 있습니다. 이제 우주 뉴스 기사를 가져오고 처리하는 실용적인 예제를 만들어보겠습니다. + +최근 우주 탐사 동향은 다음과 같습니다. 최신 우주 뉴스 기사들을 기반으로 정리하였습니다: + +1. SpaceX가 2023년 11월 17일 오전에 예정된, 두 번째 Starship/Super Heavy 통합 발사를 위한 최종 규제 승인을 받았습니다. 이는 SpaceX의 우주 탐사 및 우주 식민화에 대한 야심찬 계획에서 중요한 단계입니다. [출처: SpaceNews](https://spacenews.com/starship-cleared-for-nov-17-launch/) + +2. SpaceX는 미국 연방통신위원회(FCC)에 1세대 차세대 Starlink Gen2 위성의 첫 발사를 시작할 계획임을 알렸습니다. 이는 전 세계에 고속 인터넷을 제공하는 Starlink 위성 인터넷 서비스의 주요 업그레이드입니다. [출처: Teslarati](https://www.teslarati.com/spacex-first-starlink-gen2-satellite-launch-2022/) + +3. AI 스타트업 Synthetaic이 시리즈 B 펀딩에서 1,500만 달러를 유치했습니다. 이 회사는 인공 지능을 사용하여 우주 및 공중 센서에서 데이터를 분석하며, 이는 우주 탐사와 위성 기술에 큰 응용 가능성이 있습니다. [출처: SpaceNews](https://spacenews.com/ai-startup-synthetaic-raises-15-million-in-series-b-funding/) + +4. 미 우주군(Space Force)은 미국 인도-태평양 사령부(Indo-Pacific Command) 내에 부대를 공식적으로 창설하여 인도-태평양 지역에 항구적인 존재감을 확보하였습니다. 이는 우주 안보 및 지정학에 중대한 영향을 미칠 수 있습니다. [출처: SpaceNews](https://spacenews.com/space-force-establishes-permanent-presence-in-indo-pacific-region/) + +5. 우주 추적 및 데이터 분석 기업 Slingshot Aerospace는 저지구 궤도(LEO) 커버리지를 확대하기 위해 지상 광학 망원경 네트워크를 확장하고 있습니다. 이는 저지구 궤도의 위성 및 우주 잔해 추적과 분석 능력을 향상시킬 수 있습니다. [출처: SpaceNews](https://spacenews.com/slingshots-space-tracking-network-to-extend-coverage-of-low-earth-orbit/) + +6. 중국 국가자연과학기금위원회는 연구자들이 초대형 우주선 조립을 연구하기 위한 5개년 프로젝트를 발표했습니다. 이는 우주선 기술과 우주 탐사 역량의 비약적인 발전을 가져올 수 있습니다. [출처: SpaceNews](https://spacenews.com/china-researching-challenges-of-kilometer-scale-ultra-large-spacecraft/) + +7. 스탠포드 대학교의 AEroSpace Autonomy Research 센터(CAESAR)는 우주선 자율성에 초점을 맞추고 있습니다. 센터는 2024년 5월 22일에 업계, 학계, 정부 간 협력을 촉진하기 위한 시작 행사를 개최하였습니다. 이는 자율 우주선 기술의 발전에 중대한 기여를 할 수 있습니다. [출처: SpaceNews](https://spacenews.com/stanford-center-focuses-on-spacecraft-autonomy/) +``` + + + +## 디버깅 및 문제 해결 + +### 지식 문제 디버깅 + +#### 에이전트 지식 초기화 확인 +```python +from crewai import Agent, Crew, Task +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +knowledge_source = StringKnowledgeSource(content="Test knowledge") + +agent = Agent( + role="Test Agent", + goal="Test knowledge", + backstory="Testing", + knowledge_sources=[knowledge_source] +) + +crew = Crew(agents=[agent], tasks=[Task(...)]) + +# Before kickoff - knowledge not initialized +print(f"Before kickoff - Agent knowledge: {getattr(agent, 'knowledge', None)}") + +crew.kickoff() + +# After kickoff - knowledge initialized +print(f"After kickoff - Agent knowledge: {agent.knowledge}") +print(f"Agent knowledge collection: {agent.knowledge.storage.collection_name}") +print(f"Number of sources: {len(agent.knowledge.sources)}") +``` + +#### Knowledge 저장 위치 확인 + +```python +import os +from crewai.utilities.paths import db_storage_path + +# Check storage structure +storage_path = db_storage_path() +knowledge_path = os.path.join(storage_path, "knowledge") + +if os.path.exists(knowledge_path): + print("Knowledge collections found:") + for collection in os.listdir(knowledge_path): + collection_path = os.path.join(knowledge_path, collection) + if os.path.isdir(collection_path): + print(f" - {collection}/") + # Show collection contents + for item in os.listdir(collection_path): + print(f" └── {item}") +``` + +#### 테스트 지식 검색 +```python +# Test agent knowledge retrieval +if hasattr(agent, 'knowledge') and agent.knowledge: + test_query = ["test query"] + results = agent.knowledge.query(test_query) + print(f"Agent knowledge results: {len(results)} documents found") + + # Test crew knowledge retrieval (if exists) + if hasattr(crew, 'knowledge') and crew.knowledge: + crew_results = crew.query_knowledge(test_query) + print(f"Crew knowledge results: {len(crew_results)} documents found") +``` + +#### 지식 컬렉션 검사하기 +```python +import chromadb +from crewai.utilities.paths import db_storage_path +import os + +# Connect to CrewAI's knowledge ChromaDB +knowledge_path = os.path.join(db_storage_path(), "knowledge") + +if os.path.exists(knowledge_path): + client = chromadb.PersistentClient(path=knowledge_path) + collections = client.list_collections() + + print("Knowledge Collections:") + for collection in collections: + print(f" - {collection.name}: {collection.count()} documents") + + # Sample a few documents to verify content + if collection.count() > 0: + sample = collection.peek(limit=2) + print(f" Sample content: {sample['documents'][0][:100]}...") +else: + print("No knowledge storage found") +``` + +#### 지식 처리 확인 +```python +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create a test knowledge source +test_source = StringKnowledgeSource( + content="Test knowledge content for debugging", + chunk_size=100, # Small chunks for testing + chunk_overlap=20 +) + +# Check chunking behavior +print(f"Original content length: {len(test_source.content)}") +print(f"Chunk size: {test_source.chunk_size}") +print(f"Chunk overlap: {test_source.chunk_overlap}") + +# Process and inspect chunks +test_source.add() +print(f"Number of chunks created: {len(test_source.chunks)}") +for i, chunk in enumerate(test_source.chunks[:3]): # Show first 3 chunks + print(f"Chunk {i+1}: {chunk[:50]}...") +``` + +### 일반적인 Knowledge Storage 문제 + +**"파일을 찾을 수 없음" 오류:** +```python +# Ensure files are in the correct location +from crewai.utilities.constants import KNOWLEDGE_DIRECTORY +import os + +knowledge_dir = KNOWLEDGE_DIRECTORY # Usually "knowledge" +file_path = os.path.join(knowledge_dir, "your_file.pdf") + +if not os.path.exists(file_path): + print(f"File not found: {file_path}") + print(f"Current working directory: {os.getcwd()}") + print(f"Expected knowledge directory: {os.path.abspath(knowledge_dir)}") +``` + +**"Embedding dimension mismatch" 오류:** +```python +# This happens when switching embedding providers +# Reset knowledge storage to clear old embeddings +crew.reset_memories(command_type='knowledge') + +# Or use consistent embedding providers +crew = Crew( + agents=[...], + tasks=[...], + knowledge_sources=[...], + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}} +) +``` + +**"ChromaDB permission denied" 오류:** +```bash +# Fix storage permissions +chmod -R 755 ~/.local/share/CrewAI/ +``` + +**Knowledge가 여러 번 실행 시 유지되지 않음:** +```python +# Verify storage location consistency +import os +from crewai.utilities.paths import db_storage_path + +print("CREWAI_STORAGE_DIR:", os.getenv("CREWAI_STORAGE_DIR")) +print("Computed storage path:", db_storage_path()) +print("Knowledge path:", os.path.join(db_storage_path(), "knowledge")) +``` + +### 지식 초기화 명령어 + +```python +# Reset only agent-specific knowledge +crew.reset_memories(command_type='agent_knowledge') + +# Reset both crew and agent knowledge +crew.reset_memories(command_type='knowledge') + +# CLI commands +# crewai reset-memories --agent-knowledge # Agent knowledge only +# crewai reset-memories --knowledge # All knowledge +``` + +### 지식 초기화 + +CrewAI에 저장된 지식을 초기화해야 하는 경우, `crewai reset-memories` 명령어를 `--knowledge` 옵션과 함께 사용할 수 있습니다. + +```bash Command +crewai reset-memories --knowledge +``` + +이 기능은 지식 소스를 업데이트했고, 에이전트들이 최신 정보를 사용하도록 보장하고 싶을 때 유용합니다. + +## 베스트 프랙티스 + + + + - 콘텐츠 유형에 맞는 적절한 청크 크기를 유지하세요 + - 컨텍스트 보존을 위해 콘텐츠 중복을 고려하세요 + - 관련 정보를 별도의 지식 소스로 체계화하세요 + + + + - 콘텐츠의 복잡성에 따라 청크 크기를 조정하세요 + - 적절한 임베딩 모델을 설정하세요 + - 더 빠른 처리를 위해 로컬 임베딩 프로바이더 사용을 고려하세요 + + + + - CrewAI에서 제공하는 일반적인 파일 구조에서는 kickoff가 트리거될 때마다 knowledge 소스가 임베딩됩니다. + - knowledge 소스가 크면, 매번 동일한 데이터가 임베딩되어 비효율성과 지연이 발생합니다. + - 이를 해결하려면 knowledge_sources 파라미터 대신 knowledge 파라미터를 직접 초기화하세요. + - 전체 아이디어를 얻으려면 이 이슈를 참고하세요 [Github Issue](https://github.com/crewAIInc/crewAI/issues/2755) + + + + - 역할별 정보에는 agent 레벨의 knowledge를 사용하세요 + - 모든 agent가 필요로 하는 공유 정보에는 crew 레벨의 knowledge를 사용하세요 + - 서로 다른 임베딩 전략이 필요하다면 agent 레벨에서 embedder를 설정하세요 + - agent 역할을 설명적으로 유지하여 일관된 콜렉션 이름을 사용하세요 + - kickoff 후 agent.knowledge를 확인하여 knowledge 초기화를 테스트하세요 + - 지식이 저장되는 위치를 모니터링하여 storage 위치를 파악하세요 + - 올바른 명령 유형을 사용하여 적절하게 knowledge를 초기화(리셋)하세요 + + + + - 프로덕션에서는 `CREWAI_STORAGE_DIR`를 지정된 위치로 설정하세요 + - LLM 구성과 맞도록 임베딩 프로바이더를 명확히 선택하고, API 키 충돌을 방지하세요 + - 문서가 추가될수록 knowledge storage 용량을 모니터링하세요 + - 도메인 또는 목적에 따라 knowledge 소스를 콜렉션 이름으로 체계화하세요 + - 지식 디렉터리를 백업 및 배포 전략에 포함시키세요 + - knowledge 파일과 storage 디렉터리에 적절한 파일 권한을 부여하세요 + - API 키와 민감한 설정에는 환경 변수를 사용하세요 + + \ No newline at end of file diff --git a/docs/v1.15.13/ko/concepts/llms.mdx b/docs/v1.15.13/ko/concepts/llms.mdx new file mode 100644 index 0000000000..760377ac12 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/llms.mdx @@ -0,0 +1,1008 @@ +--- +title: 'LLMs' +description: 'CrewAI 프로젝트에서 대형 언어 모델(LLM)을 구성하고 사용하는 방법에 대한 종합 안내서' +icon: 'microchip-ai' +mode: "wide" +--- + +## 개요 + +CrewAI는 LiteLLM을 통해 다양한 LLM 제공업체와 통합되어, 특정 사용 사례에 맞는 올바른 모델을 선택할 수 있는 유연성을 제공합니다. 이 가이드는 CrewAI 프로젝트에서 다양한 LLM 제공업체를 구성하고 사용하는 방법을 이해하는 데 도움이 될 것입니다. + +## LLM이란 무엇인가요? + +Large Language Models(LLM)는 CrewAI 에이전트의 핵심 지능입니다. 에이전트가 문맥을 이해하고, 결정을 내리며, 인간과 유사한 응답을 생성할 수 있도록 합니다. 알아두어야 할 내용은 다음과 같습니다: + + + + Large Language Models는 방대한 양의 텍스트 데이터로 학습된 AI 시스템입니다. CrewAI 에이전트의 지능을 구동하여, 인간과 유사한 텍스트를 이해하고 생성할 수 있도록 합니다. + + + 컨텍스트 윈도우는 LLM이 한 번에 처리할 수 있는 텍스트 양을 결정합니다. 더 큰 윈도우(예: 128K 토큰)는 더 많은 문맥을 다룰 수 있지만, 비용과 속도 면에서 더 부담이 될 수 있습니다. + + + Temperature는 일부 모델이 지원하는 샘플링 제어 옵션입니다. 값이 낮을수록 일반적으로 샘플링이 더 집중되고, 값이 높을수록 변동성이 커집니다. 일부 최신 추론 모델은 이 파라미터를 무시하거나 더 이상 권장하지 않거나 거부하므로, 설정하기 전에 선택한 모델의 문서를 확인하세요. + + + 각 LLM 제공자(예: OpenAI, Anthropic, Google)는 다양한 기능, 가격, 특성을 가진 모델을 제공합니다. 정확성, 속도, 비용 등 요구 사항에 따라 선택하세요. + + + +## LLM 설정하기 + +CrewAI 코드 내에는 사용할 모델을 지정할 수 있는 여러 위치가 있습니다. 모델을 지정한 후에는 사용하는 각 모델 제공자에 대한 설정(예: API 키)을 제공해야 합니다. 각 제공자에 맞는 [제공자 설정 예제](#provider-configuration-examples) 섹션을 참고하세요. + + + + 가장 간단하게 시작할 수 있는 방법입니다. `.env` 파일이나 앱 코드에서 환경 변수로 직접 모델을 설정할 수 있습니다. `crewai create`를 사용해 프로젝트를 부트스트랩했다면 이미 설정되어 있을 수 있습니다. + + ```bash .env + MODEL=provider/model-id # e.g. openai/gpt-5.6-terra + + # 반드시 여기에서 API 키도 설정하세요. 아래 제공자 + # 섹션을 참고하세요. + ``` + + + API 키를 절대 버전 관리 시스템에 커밋하지 마세요. 환경 파일(.env)이나 시스템의 비밀 관리 기능을 사용하세요. + + + + 에이전트 구성을 정의하는 YAML 파일을 만드세요. 이 방법은 버전 관리와 팀 협업에 적합합니다: + + ```yaml agents.yaml {6} + researcher: + role: Research Specialist + goal: Conduct comprehensive research and analysis + backstory: A dedicated research professional with years of experience + verbose: true + llm: provider/model-id # e.g. anthropic/claude-sonnet-4-6 + # (아래 제공자 구성 예제 참고) + ``` + + + YAML 구성의 장점: + - 에이전트 설정을 버전 관리할 수 있습니다. + - 다양한 모델 간 전환이 쉽습니다. + - 팀원들과 구성을 공유할 수 있습니다. + - 모델 선택과 목적을 문서화할 수 있습니다. + + + + 최대한 유연하게 LLM을 Python 코드에서 직접 구성할 수 있습니다: + + ```python {4,8} + from crewai import LLM + + # 기본 설정 + llm = LLM(model="provider/model-id") # e.g. gemini/gemini-3.6-flash + + # 자세한 파라미터로 고급 설정 + llm = LLM( + model="provider/model-id", + timeout=120, + max_tokens=4000, + response_format={"type": "json"}, # 구조화된 출력용 + ) + ``` + + + 파라미터 설명: + - `timeout`: 응답 대기 최대 시간 + - `max_tokens`: 응답 길이 제한 + - `response_format`: 출력 구조 지정 + + `temperature`, `top_p` 같은 샘플링 제어, 페널티 파라미터, 토큰 제한 파라미터 이름, 추론 제어는 모델별로 다릅니다. 선택한 제공자와 모델이 지원하는 경우에만 추가하세요. 아래 제공자 예시와 해당 제공자의 모델 문서를 참고하세요. + + + + + + CrewAI는 OpenAI, Anthropic, Google (Gemini API), Azure, AWS Bedrock, Snowflake Cortex에 대해 네이티브 SDK 통합을 제공합니다 — 제공자별 extras(예: `uv add "crewai[openai]"`) 외에 추가 설치가 필요하지 않습니다. + + 그 외 모든 제공자는 **LiteLLM**을 통해 지원됩니다. 이를 사용하려면 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + +## 공급자 구성 예시 + +CrewAI는 고유한 기능, 인증 방법, 모델 역량을 제공하는 다양한 LLM 공급자를 지원합니다. +이 섹션에서는 프로젝트의 요구에 가장 적합한 LLM을 선택, 구성, 최적화하는 데 도움이 되는 자세한 예시를 제공합니다. + + + 모델 가용성은 자주 변경되며 계정, 리전, 클라우드 플랫폼에 따라 달라질 수 있습니다. 아래 예시는 작성 시점에 제공되는 모델을 사용하지만 전체 지원 목록은 아닙니다. 배포하기 전에 연결된 제공자 모델 카탈로그에서 모델 ID와 수명 주기 상태를 확인하세요. + + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + + ```toml Code + # Required + OPENAI_API_KEY=sk-... + + # Optional + OPENAI_API_BASE= + OPENAI_ORGANIZATION= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + from crewai import LLM + + llm = LLM( + model="openai/gpt-5.6-terra", + reasoning_effort="medium", + max_completion_tokens=4000 + ) + ``` + + OpenAI는 정기적으로 모델을 추가하고 이전 스냅샷을 폐기합니다. 현재 모델 ID, 컨텍스트 윈도우, 엔드포인트 호환성, 수명 주기 정보는 [OpenAI 모델 카탈로그](https://developers.openai.com/api/docs/models)를 확인하세요. + + **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(제로 데이터 보존) 준수를 위한 암호화된 추론 항목 추적 + + + 새 프로젝트, 특히 추론 모델(o1, o3, o4)을 사용하거나 [파일](/ko/concepts/files)에 대한 네이티브 멀티모달 지원이 필요한 경우 Responses API를 사용하세요. + + + + + Meta의 Llama API는 Meta의 대형 언어 모델 패밀리 접근을 제공합니다. + API는 [Meta Llama API](https://llama.developer.meta.com?utm_source=partner-crewai&utm_medium=website)에서 사용할 수 있습니다. + `.env` 파일에 다음 환경 변수를 설정하십시오: + + ```toml Code + # Meta Llama API Key Configuration + LLAMA_API_KEY=LLM|your_api_key_here + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + from crewai import LLM + + # Meta Llama LLM 초기화 + llm = LLM( + model="meta_llama/Llama-4-Scout-17B-16E-Instruct-FP8", + temperature=0.8, + stop=["END"], + seed=42 + ) + ``` + + 현재 모델 제품군, 모달리티, 컨텍스트 지침은 [Meta Llama 모델 개요](https://ai.meta.com/llama/get-started/)를 확인하세요. + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + CrewAI는 OpenAI 호환 Chat Completions 엔드포인트를 통해 Snowflake Cortex REST API와 네이티브로 통합됩니다. `snowflake/...` 모델은 LiteLLM fallback 없이 사용됩니다. CrewAI에서 Snowflake Cortex는 현재 Chat Completions만 지원하므로 기본 `api` 모드를 사용하고 `api="responses"`를 설정하지 마세요. + + ```toml Code + # Required + SNOWFLAKE_PAT= + SNOWFLAKE_ACCOUNT_URL=https://.snowflakecomputing.com + + # Alternative account configuration + SNOWFLAKE_ACCOUNT= + ``` + + **기본 사용법:** + ```python Code + from crewai import LLM + + llm = LLM( + model="snowflake/openai-gpt-4.1", + temperature=0.7, + max_completion_tokens=1024, + ) + ``` + + **Cortex의 Claude 모델:** + ```python Code + from crewai import LLM + + llm = LLM( + model="snowflake/claude-sonnet-4-5", + max_completion_tokens=1024, + stream=True, + ) + ``` + + **지원 환경 변수:** + - `SNOWFLAKE_PAT`, `SNOWFLAKE_TOKEN`, 또는 `SNOWFLAKE_JWT`: Bearer 자격 증명으로 사용할 토큰 + - `SNOWFLAKE_ACCOUNT_URL`: 전체 Snowflake 계정 URL + - `SNOWFLAKE_ACCOUNT`, `SNOWFLAKE_ACCOUNT_ID`, 또는 `SNOWFLAKE_ACCOUNT_IDENTIFIER`: 계정 URL을 만들 계정 식별자 + + Snowflake REST 요청은 사용자의 기본 Snowflake role을 사용합니다. 해당 role에 `SNOWFLAKE.CORTEX_USER` 또는 `SNOWFLAKE.CORTEX_REST_API_USER`가 있는지 확인하세요. Cortex REST Chat Completions 엔드포인트에는 database, schema, warehouse, 명시적 role 파라미터가 필요하지 않습니다. + + **기능:** + - `model="snowflake/"`을 통한 네이티브 provider 선택 + - Streaming 및 non-streaming Chat Completions만 지원; `api="responses"`는 지원되지 않음 + - 토큰 사용량 추적 + - Snowflake 호스팅 OpenAI 및 Claude 모델의 함수 호출 + - Snowflake Claude 모델에서 유효하지 않은 마지막 assistant prefill 자동 제거 + + + + ```toml Code + # Required + ANTHROPIC_API_KEY=sk-ant-... + + # Optional + ANTHROPIC_API_BASE= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="anthropic/claude-sonnet-4-6", + max_tokens=4096 + ) + ``` + + **토큰 사용량 및 프롬프트 캐싱:** + + Anthropic은 청구된 입력을 별도 카운터로 보고합니다 — `input_tokens`(캐시되지 않은 입력), `cache_read_input_tokens`, `cache_creation_input_tokens`. CrewAI는 세 값을 모두 `prompt_tokens`(및 제공자 응답의 네이티브 `input_tokens`)에 포함시켜 캐시된 워크로드에서 `total_tokens`가 전체 청구 사용량을 반영하도록 합니다. + + `cached_prompt_tokens`는 캐시 읽기 부분을 breakdown으로만 기록합니다. 이미 `prompt_tokens`에 포함되어 있으므로 `total_tokens`에 다시 더하면 안 됩니다. `cache_creation_tokens`도 캐시 쓰기를 같은 방식으로 기록합니다. + + ```python Code + usage = llm.get_token_usage_summary() + # total_tokens == prompt_tokens + completion_tokens + # prompt_tokens includes cache read + cache write for Anthropic + ``` + + `crew.usage_metrics` 및 `flow.usage_metrics`에 사용되는 제공자 중립 계약은 + Flows 개념 문서의 **UsageMetrics field semantics** 섹션을 참조하세요. + + 현재 모델 ID와 기능은 Anthropic의 [모델 개요](https://platform.claude.com/docs/en/about-claude/models/overview)를 확인하고, 프로덕션에서 모델을 고정하기 전에 [모델 지원 중단 표](https://platform.claude.com/docs/en/about-claude/model-deprecations)를 검토하세요. + + + + `.env` 파일에 API 키를 설정하십시오. 키가 필요하거나 기존 키를 찾으려면 [AI Studio](https://aistudio.google.com/apikey)를 확인하세요. + + ```toml .env + # Gemini API 사용 시 (다음 중 하나) + GOOGLE_API_KEY= + GEMINI_API_KEY= + + # Vertex AI Express 모드 사용 시 (API 키 인증) + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_API_KEY= + + # Vertex AI 서비스 계정 사용 시 + GOOGLE_CLOUD_PROJECT= + GOOGLE_CLOUD_LOCATION= # 기본값: us-central1 + ``` + + **기본 사용법:** + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash", + ) + ``` + + **Vertex AI Express 모드 (API 키 인증):** + + Vertex AI Express 모드를 사용하면 서비스 계정 자격 증명 대신 간단한 API 키 인증으로 Vertex AI를 사용할 수 있습니다. Vertex AI를 시작하는 가장 빠른 방법입니다. + + Express 모드를 활성화하려면 `.env` 파일에 두 환경 변수를 모두 설정하세요: + ```toml .env + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_API_KEY= + ``` + + 그런 다음 평소처럼 LLM을 사용하세요: + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash" + ) + ``` + + + 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)를 참조하세요. + + + Google은 현재 Gemini ID, 기능, 수명 주기 단계를 [Gemini 모델 카탈로그](https://ai.google.dev/gemini-api/docs/models)에 게시합니다. 안정 또는 preview 모델을 선택하기 전에 [지원 중단 일정](https://ai.google.dev/gemini-api/docs/deprecations)을 확인하세요. Gemini API는 [Gemma 모델](https://ai.google.dev/gemma/docs)도 호스팅합니다. + + + + [애플리케이션 기본 사용자 인증 정보](https://cloud.google.com/docs/authentication/provide-credentials-adc)로 인증한 다음, Vertex AI를 사용하도록 네이티브 Gemini 제공업체를 구성하세요: + ```toml .env + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_CLOUD_PROJECT= + GOOGLE_CLOUD_LOCATION= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash" + ) + ``` + + 사용 가능한 Vertex AI 모델과 리전은 [Vertex AI 모델 정보](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models)를 확인하세요. + + **참고:** 이 경로는 CrewAI의 네이티브 Gemini 통합을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add "crewai[google-genai]" + ``` + + + + ```toml Code + # Required + AZURE_API_KEY= + AZURE_API_BASE= + AZURE_API_VERSION= + + # Optional + AZURE_AD_TOKEN= + AZURE_API_TYPE= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="azure/gpt-4", + api_version="2023-05-15" + ) + ``` + + + + ```toml Code + AWS_ACCESS_KEY_ID= + AWS_SECRET_ACCESS_KEY= + AWS_DEFAULT_REGION= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="bedrock/us.anthropic.claude-sonnet-4-6" + ) + ``` + + Amazon Bedrock을 사용하기 전에, 환경에 boto3가 설치되어 있는지 확인하십시오. + + [Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html)은 대표적인 AI 회사들의 여러 파운데이션 모델에 통합 API를 통해 접근할 수 있는 매니지드 서비스로, 안전하고 책임감 있는 AI 응용프로그램 개발을 가능하게 해줍니다. + + + + + + ```toml Code + AWS_ACCESS_KEY_ID= + AWS_SECRET_ACCESS_KEY= + AWS_DEFAULT_REGION= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="sagemaker/" + ) + ``` + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + MISTRAL_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="mistral/mistral-large-latest", + temperature=0.7 + ) + ``` + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + NVIDIA_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="nvidia_nim/nvidia/nvidia-nemotron-3-ultra-550b-a55b", + temperature=0.7 + ) + ``` + + NVIDIA NIM의 호스팅 카탈로그는 자주 변경됩니다. 현재 endpoint를 선택하고 모델 ID, 모달리티, 컨텍스트 제한을 확인하려면 [NVIDIA NIM 모델 카탈로그](https://build.nvidia.com/models)를 사용하세요. + + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + + NVIDIA NIM을 이용하면 Windows 기기에서 WSL2(Windows Subsystem for Linux)를 통해 강력한 LLM을 로컬로 실행할 수 있습니다. + 이 방식은 Nvidia GPU를 활용하여 프라이빗하고, 안전하며, 비용 효율적인 AI 추론을 클라우드 서비스에 의존하지 않고 구현할 수 있습니다. + 데이터 프라이버시, 오프라인 기능이 필요한 개발, 테스트, 또는 프로덕션 환경에 최적입니다. + + 로컬 NVIDIA NIM 모델 설치 단계별 가이드는 다음과 같습니다: + + 1. [NVIDIA 홈페이지](https://docs.nvidia.com/nim/wsl2/latest/getting-started.html)의 설치 안내를 따르세요. + + 2. 로컬 모델을 설치합니다. Llama 3.1-8b는 [여기](https://build.nvidia.com/meta/llama-3_1-8b-instruct/deploy) 안내를 참조하세요. + + 3. crewai 로컬 모델을 구성하세요: + + ```python Code + from crewai.llm import LLM + + local_nvidia_nim_llm = LLM( + model="openai/meta/llama-3.1-8b-instruct", # it's an openai-api compatible model + base_url="http://localhost:8000/v1", + api_key="", # api_key is required, but you can use any text + ) + + # 그런 다음 crew에서 사용할 수 있습니다: + + @CrewBase + class MyCrew(): + # ... + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], # type: ignore[index] + llm=local_nvidia_nim_llm + ) + + # ... + ``` + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + + ```toml Code + GROQ_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="groq/qwen/qwen3.6-27b", + temperature=0.7 + ) + ``` + + Groq는 production 모델과 preview 모델을 구분하며 모델 ID를 정기적으로 폐기합니다. 프로덕션 모델을 선택하기 전에 [Groq 모델 카탈로그](https://console.groq.com/docs/models)와 [지원 중단 페이지](https://console.groq.com/docs/deprecations)를 확인하세요. + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + # Required + WATSONX_URL= + WATSONX_APIKEY= + WATSONX_PROJECT_ID= + + # Optional + WATSONX_TOKEN= + WATSONX_DEPLOYMENT_SPACE_ID= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="watsonx/meta-llama/llama-3-1-70b-instruct", + base_url="https://api.watsonx.ai/v1" + ) + ``` + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + 1. Ollama 설치: [ollama.ai](https://ollama.ai/) + 2. 모델 실행: `ollama run llama3` + 3. 구성: + + ```python Code + llm = LLM( + model="ollama/llama3:70b", + base_url="http://localhost:11434" + ) + ``` + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + FIREWORKS_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="fireworks_ai/accounts/fireworks/models/llama-v3-70b-instruct", + temperature=0.7 + ) + ``` + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + PERPLEXITY_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="perplexity/sonar-pro" + ) + ``` + + 현재 모델 ID와 지원 중단 공지는 [Perplexity 모델 카탈로그](https://docs.perplexity.ai/getting-started/models)와 [changelog](https://docs.perplexity.ai/docs/resources/changelog)를 확인하세요. + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + HF_TOKEN= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct" + ) + ``` + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + + ```toml Code + SAMBANOVA_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="sambanova/Meta-Llama-3.3-70B-Instruct", + temperature=0.7 + ) + ``` + + SambaNova Cloud의 호스팅 모델은 CrewAI와 별도로 변경될 수 있습니다. 배포 전에 [models endpoint](https://docs.sambanova.ai/docs/api-reference/models/get-environments-available-model-list-metadata)를 조회하고 [지원 중단 가이드](https://docs.sambanova.ai/docs/en/models/deprecations)를 확인하세요. + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + # Required + CEREBRAS_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="cerebras/gpt-oss-120b", + temperature=0.7, + max_tokens=8192 + ) + ``` + + + Cerebras 특징: + - 빠른 추론 속도 + - 경쟁력 있는 가격 + - 속도와 품질의 우수한 밸런스 + - 긴 컨텍스트 윈도우 지원 + + + 현재 공개 endpoint ID는 [Cerebras 모델 카탈로그](https://inference-docs.cerebras.ai/models/overview)와 [지원 중단 공지](https://inference-docs.cerebras.ai/support/deprecation)를 확인하세요. + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + OPENROUTER_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="openrouter/deepseek/deepseek-r1", + base_url="https://openrouter.ai/api/v1", + api_key=OPENROUTER_API_KEY + ) + ``` + + + Open Router 모델: + - openrouter/deepseek/deepseek-r1 + - openrouter/deepseek/deepseek-chat + + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + + `.env` 파일에 다음 환경 변수를 설정하십시오: + ```toml Code + NEBIUS_API_KEY= + ``` + + CrewAI 프로젝트에서의 예시 사용법: + ```python Code + llm = LLM( + model="nebius/Qwen/Qwen3-30B-A3B" + ) + ``` + + + Nebius AI Studio 특징: + - 대규모 오픈소스 모델 보유 + - 높은 속도 제한 + - 경쟁력 있는 가격 + - 속도와 품질의 우수한 밸런스 + + + **참고:** 이 제공자는 LiteLLM을 사용합니다. 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + + + +## 스트리밍 응답 + +CrewAI는 LLM의 스트리밍 응답을 지원하여, 애플리케이션이 출력물을 생성되는 즉시 실시간으로 수신하고 처리할 수 있습니다. + + + + LLM을 초기화할 때 `stream` 파라미터를 `True`로 설정하여 스트리밍을 활성화합니다: + + ```python + from crewai import LLM + + # 스트리밍이 활성화된 LLM 생성 + llm = LLM( + model="openai/gpt-5.6-terra", + stream=True # 스트리밍 활성화 + ) + ``` + + 스트리밍이 활성화되면, 응답이 생성되는 대로 청크 단위로 전달되어 보다 반응성 있는 사용자 경험을 만듭니다. + + + + CrewAI는 스트리밍 중 수신되는 각 청크에 대해 이벤트를 발생시킵니다: + + ```python + from crewai.events import ( + LLMStreamChunkEvent + ) + from crewai.events import BaseEventListener + + class MyCustomListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(LLMStreamChunkEvent) + def on_llm_stream_chunk(self, event: LLMStreamChunkEvent): + # 각 청크가 도착할 때마다 처리 + print(f"Received chunk: {event.chunk}") + + my_listener = MyCustomListener() + ``` + + + [자세한 내용은 여기를 클릭하세요](/ko/concepts/event-listener#event-listeners) + + + + + CrewAI의 모든 LLM 이벤트에는 에이전트 및 태스크 정보가 포함되어 있어, 특정 에이전트나 태스크별로 LLM 상호작용을 추적하고 필터링할 수 있습니다: + + ```python + from crewai import LLM, Agent, Task, Crew + from crewai.events import LLMStreamChunkEvent + from crewai.events import BaseEventListener + + class MyCustomListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(LLMStreamChunkEvent) + def on_llm_stream_chunk(source, event): + if researcher.id == event.agent_id: + print("\n==============\n Got event:", event, "\n==============\n") + + + my_listener = MyCustomListener() + + llm = LLM(model="openai/gpt-5.6-terra", stream=True) + + researcher = Agent( + role="About User", + goal="You know everything about the user.", + backstory="""You are a master at understanding people and their preferences.""", + llm=llm, + ) + + search = Task( + description="Answer the following questions about the user: {question}", + expected_output="An answer to the question.", + agent=researcher, + ) + + crew = Crew(agents=[researcher], tasks=[search]) + + result = crew.kickoff( + inputs={"question": "..."} + ) + ``` + + + 이 기능은 다음과 같은 경우에 특히 유용합니다: + - 특정 에이전트 동작을 디버깅할 때 + - 태스크 유형별 LLM 사용 기록을 남길 때 + - 어떤 에이전트가 어떤 유형의 LLM 호출을 하는지 감사할 때 + - 특정 태스크의 성능을 모니터링할 때 + + + + +## 구조화된 LLM 호출 + +CrewAI는 Pydantic 모델을 사용하여 `response_format`을 정의함으로써 LLM 호출에서 구조화된 응답을 지원합니다. 이를 통해 프레임워크가 출력을 자동으로 파싱하고 검증할 수 있어, 수동 후처리 없이도 응답을 애플리케이션에 쉽게 통합할 수 있습니다. + +구조화된 출력 지원은 제공업체와 모델에 따라 다릅니다. 프로덕션에서 구조화된 응답에 의존하기 전에 선택한 모델을 테스트하세요. + +예를 들어, 예상되는 응답 구조를 나타내는 Pydantic 모델을 정의하고 LLM을 인스턴스화할 때 `response_format`으로 전달할 수 있습니다. 이 모델은 LLM 출력을 구조화된 Python 객체로 변환하는 데 사용됩니다. + +```python Code +from crewai import LLM + +class Dog(BaseModel): + name: str + age: int + breed: str + + +llm = LLM(model="openai/gpt-5.6-terra", response_format=Dog) + +response = llm.call( + "Analyze the following messages and return the name, age, and breed. " + "Meet Kona! She is 3 years old and is a black german shepherd." +) +print(response) + +# Output: +# Dog(name='Kona', age=3, breed='black german shepherd') +``` + +## 고급 기능 및 최적화 + +LLM 설정을 최대한 활용하는 방법을 알아보세요: + + + + CrewAI는 스마트한 컨텍스트 관리 기능을 제공합니다: + + ```python + from crewai import LLM + + # CrewAI는 자동으로 다음을 처리합니다: + # 1. 토큰 계산 및 추적 + # 2. 필요시 콘텐츠 요약 + # 3. 큰 컨텍스트에 대한 작업 분할 + + llm = LLM( + model="openai/gpt-5.6-terra", + max_completion_tokens=4000, # 응답 길이 제한 + ) + ``` + + + 컨텍스트 관리 모범 사례: + 1. 적절한 컨텍스트 윈도우를 가진 모델 선택 + 2. 가능하면 긴 입력값을 사전 처리 + 3. 큰 문서에는 청킹(chunking) 사용 + 4. 비용 최적화를 위해 토큰 사용량 모니터링 + + + + + + + 작업에 맞는 컨텍스트 윈도우를 선택하세요: + - 작은 작업 (최대 4K 토큰): 표준 모델 + - 중간 작업 (4K~32K 사이): 확장 모델 + - 큰 작업 (32K 이상): 대형 컨텍스트 모델 + + ```python + # 모델을 적절한 설정으로 구성 + llm = LLM( + model="openai/gpt-5.6-terra", + reasoning_effort="medium", + max_completion_tokens=4096, + timeout=300 + ) + ``` + + 선택한 모델이 지원하는 제어 옵션을 사용하세요. 제공자에 따라 `temperature`, reasoning 또는 thinking 수준, 혹은 원하는 스타일과 변동성을 정의하는 프롬프트 지침을 사용할 수 있습니다. + + + + + 1. 토큰 사용량 모니터링 + 2. 속도 제한(rate limiting) 구현 + 3. 가능하면 캐싱 사용 + 4. 적절한 max_tokens 제한 설정 + + + + + 비용 및 성능을 최적화하기 위해 토큰 사용량을 정기적으로 모니터링하고 필요에 따라 설정을 조정하세요. + + + + + CrewAI는 내부적으로 LLM 호출에 Litellm을 사용하며, 이를 통해 특정 사용 사례에 필요하지 않은 추가 파라미터를 제거할 수 있습니다. 이를 통해 코드가 간소화되며 LLM 구성의 복잡성을 줄일 수 있습니다. + 예를 들어, stop 파라미터를 보낼 필요가 없다면 LLM 호출에서 제외할 수 있습니다: + + ```python + from crewai import LLM + import os + + os.environ["OPENAI_API_KEY"] = "" + + o3_llm = LLM( + model="o3", + drop_params=True, + additional_drop_params=["stop"] + ) + ``` + + + +## 일반적인 문제 및 해결 방법 + + + + + 대부분의 인증 문제는 API 키 형식과 환경 변수 이름을 확인하여 해결할 수 있습니다. + + + ```bash + # OpenAI + OPENAI_API_KEY=sk-... + + # Anthropic + ANTHROPIC_API_KEY=sk-ant-... + ``` + + + + 항상 모델 이름에 provider 접두사를 포함하세요. + + + ```python + # 올바른 예시 + llm = LLM(model="openai/gpt-4") + + # 잘못된 예시 + llm = LLM(model="gpt-4") + ``` + + + + 대규모 작업에는 더 큰 컨텍스트 모델을 사용하세요. + + + ```python + # 대용량 컨텍스트 모델 + llm = LLM(model="openai/gpt-4o") # 128K tokens + ``` + + diff --git a/docs/v1.15.13/ko/concepts/memory.mdx b/docs/v1.15.13/ko/concepts/memory.mdx new file mode 100644 index 0000000000..ea4463eea7 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/memory.mdx @@ -0,0 +1,878 @@ +--- +title: 메모리 +description: CrewAI의 통합 메모리 시스템을 활용하여 에이전트 역량을 강화합니다. +icon: database +mode: "wide" +--- + +## 개요 + +CrewAI는 **통합 메모리 시스템**을 제공합니다 -- 단기, 장기, 엔터티, 외부 메모리 유형을 하나의 지능형 API인 단일 `Memory` 클래스로 대체합니다. 메모리는 저장 시 LLM을 사용하여 콘텐츠를 분석하고(범위, 카테고리, 중요도 추론) 의미 유사도, 최신성, 중요도를 혼합한 복합 점수로 적응형 깊이 recall을 지원합니다. + +메모리를 네 가지 방법으로 사용할 수 있습니다: **독립 실행**(스크립트, 노트북), **Crew와 함께**, **에이전트와 함께**, 또는 **Flow 내부에서**. + +## 빠른 시작 + +```python +from crewai import Memory + +memory = Memory() + +# 저장 -- LLM이 scope, categories, importance를 추론 +memory.remember("We decided to use PostgreSQL for the user database.") + +# 검색 -- 복합 점수(의미 + 최신성 + 중요도)로 결과 순위 매기기 +matches = memory.recall("What database did we choose?") +for m in matches: + print(f"[{m.score:.2f}] {m.record.content}") + +# 빠르게 변하는 프로젝트를 위한 점수 조정 +memory = Memory(recency_weight=0.5, recency_half_life_days=7) + +# 삭제 +memory.forget(scope="/project/old") + +# 자동 구성된 scope 트리 탐색 +print(memory.tree()) +print(memory.info("/")) +``` + +## 메모리를 사용하는 네 가지 방법 + +### 독립 실행 + +스크립트, 노트북, CLI 도구 또는 독립 지식 베이스로 메모리를 사용합니다 -- 에이전트나 crew가 필요하지 않습니다. + +```python +from crewai import Memory + +memory = Memory() + +# 지식 구축 +memory.remember("The API rate limit is 1000 requests per minute.") +memory.remember("Our staging environment uses port 8080.") +memory.remember("The team agreed to use feature flags for all new releases.") + +# 나중에 필요한 것을 recall +matches = memory.recall("What are our API limits?", limit=5) +for m in matches: + print(f"[{m.score:.2f}] {m.record.content}") + +# 긴 텍스트에서 원자적 사실 추출 +raw = """Meeting notes: We decided to migrate from MySQL to PostgreSQL +next quarter. The budget is $50k. Sarah will lead the migration.""" + +facts = memory.extract_memories(raw) +# ["Migration from MySQL to PostgreSQL planned for next quarter", +# "Database migration budget is $50k", +# "Sarah will lead the database migration"] + +for fact in facts: + memory.remember(fact) +``` + +### Crew와 함께 사용 + +기본 설정은 `memory=True`를 전달하고, 사용자 정의 동작은 설정된 `Memory` 인스턴스를 전달합니다. + +```python +from crewai import Crew, Agent, Task, Process, Memory + +# 옵션 1: 기본 메모리 +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + memory=True, + verbose=True, +) + +# 옵션 2: 조정된 점수가 있는 사용자 정의 메모리 +memory = Memory( + recency_weight=0.4, + semantic_weight=0.4, + importance_weight=0.2, + recency_half_life_days=14, +) +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + memory=memory, +) +``` + +`memory=True`일 때 crew는 기본 `Memory()`를 생성하고 crew의 `embedder` 설정을 자동으로 전달합니다. crew의 모든 에이전트는 자체 메모리가 없는 한 crew의 메모리를 공유합니다. + +각 작업 후 crew는 자동으로 작업 출력에서 개별 사실을 추출하여 저장합니다. 각 작업 전에 에이전트는 메모리에서 관련 컨텍스트를 recall하여 작업 프롬프트에 주입합니다. + +### 에이전트와 함께 사용 + +에이전트는 crew의 공유 메모리(기본값)를 사용하거나 비공개 컨텍스트를 위한 범위 지정 뷰를 받을 수 있습니다. + +```python +from crewai import Agent, Memory + +memory = Memory() + +# 연구원은 비공개 scope를 받음 -- /agent/researcher만 볼 수 있음 +researcher = Agent( + role="Researcher", + goal="Find and analyze information", + backstory="Expert researcher with attention to detail", + memory=memory.scope("/agent/researcher"), +) + +# 작성자는 crew 공유 메모리 사용 (에이전트 수준 메모리 미설정) +writer = Agent( + role="Writer", + goal="Produce clear, well-structured content", + backstory="Experienced technical writer", + # memory 미설정 -- crew에 메모리가 활성화되면 crew._memory 사용 +) +``` + +이 패턴은 연구원에게 비공개 발견을 제공하면서 작성자는 crew 공유 메모리에서 읽습니다. + +### Flow와 함께 사용 + +모든 Flow에는 내장 메모리가 있습니다. 모든 flow 메서드 내부에서 `self.remember()`, `self.recall()`, `self.extract_memories()`를 사용하세요. + +```python +from crewai.flow.flow import Flow, listen, start + +class ResearchFlow(Flow): + @start() + def gather_data(self): + findings = "PostgreSQL handles 10k concurrent connections. MySQL caps at 5k." + self.remember(findings, scope="/research/databases") + return findings + + @listen(gather_data) + def write_report(self, findings): + # 컨텍스트를 제공하기 위해 과거 연구 recall + past = self.recall("database performance benchmarks") + context = "\n".join(f"- {m.record.content}" for m in past) + return f"Report:\nNew findings: {findings}\nPrevious context:\n{context}" +``` + +Flow에서의 메모리에 대한 자세한 내용은 [Flows 문서](/concepts/flows)를 참조하세요. + + +## 계층적 범위(Scopes) + +### 범위란 무엇인가 + +메모리는 파일 시스템과 유사한 계층적 scope 트리로 구성됩니다. 각 scope는 `/`, `/project/alpha` 또는 `/agent/researcher/findings`와 같은 경로입니다. + +``` +/ + /company + /company/engineering + /company/product + /project + /project/alpha + /project/beta + /agent + /agent/researcher + /agent/writer +``` + +범위는 **컨텍스트 의존적 메모리**를 제공합니다 -- 범위 내에서 recall하면 해당 트리 분기만 검색하여 정밀도와 성능을 모두 향상시킵니다. + +### 범위 추론 작동 방식 + +`remember()` 호출 시 scope를 지정하지 않으면 LLM이 콘텐츠와 기존 scope 트리를 분석한 후 최적의 배치를 제안합니다. 적합한 기존 scope가 없으면 새로 생성합니다. 시간이 지남에 따라 scope 트리는 콘텐츠 자체에서 유기적으로 성장합니다 -- 미리 스키마를 설계할 필요가 없습니다. + +```python +memory = Memory() + +# LLM이 콘텐츠에서 scope 추론 +memory.remember("We chose PostgreSQL for the user database.") +# -> /project/decisions 또는 /engineering/database 아래에 배치될 수 있음 + +# scope를 명시적으로 지정할 수도 있음 +memory.remember("Sprint velocity is 42 points", scope="/team/metrics") +``` + +### 범위 트리 시각화 + +```python +print(memory.tree()) +# / (15 records) +# /project (8 records) +# /project/alpha (5 records) +# /project/beta (3 records) +# /agent (7 records) +# /agent/researcher (4 records) +# /agent/writer (3 records) + +print(memory.info("/project/alpha")) +# ScopeInfo(path='/project/alpha', record_count=5, +# categories=['architecture', 'database'], +# oldest_record=datetime(...), newest_record=datetime(...), +# child_scopes=[]) +``` + +### MemoryScope: 하위 트리 뷰 + +`MemoryScope`는 모든 연산을 트리의 한 분기로 제한합니다. 이를 사용하는 에이전트나 코드는 해당 하위 트리 내에서만 보고 쓸 수 있습니다. + +```python +memory = Memory() + +# 특정 에이전트를 위한 scope 생성 +agent_memory = memory.scope("/agent/researcher") + +# 모든 것이 /agent/researcher 기준으로 상대적 +agent_memory.remember("Found three relevant papers on LLM memory.") +# -> /agent/researcher 아래에 저장 + +agent_memory.recall("relevant papers") +# -> /agent/researcher 아래에서만 검색 + +# subscope로 더 좁히기 +project_memory = agent_memory.subscope("project-alpha") +# -> /agent/researcher/project-alpha +``` + +### 범위 설계 모범 사례 + +- **평평하게 시작하고 LLM이 구성하게 하세요.** 범위 계층 구조를 미리 과도하게 설계하지 마세요. `memory.remember(content)`로 시작하고 콘텐츠가 축적됨에 따라 LLM의 scope 추론이 구조를 만들게 하세요. + +- **`/{엔터티_유형}/{식별자}` 패턴을 사용하세요.** `/project/alpha`, `/agent/researcher`, `/company/engineering`, `/customer/acme-corp` 같은 패턴에서 자연스러운 계층 구조가 나타납니다. + +- **데이터 유형이 아닌 관심사별로 scope를 지정하세요.** `/decisions/project/alpha` 대신 `/project/alpha/decisions`를 사용하세요. 이렇게 하면 관련 콘텐츠가 함께 유지됩니다. + +- **깊이를 얕게 유지하세요 (2-3 수준).** 깊이 중첩된 scope는 너무 희소해집니다. `/project/alpha/architecture`는 좋지만 `/project/alpha/architecture/decisions/databases/postgresql`은 너무 깊습니다. + +- **알 때는 명시적 scope를, 모를 때는 LLM 추론을 사용하세요.** 알려진 프로젝트 결정을 저장할 때는 `scope="/project/alpha/decisions"`를 전달하세요. 자유 형식 에이전트 출력을 저장할 때는 scope를 생략하고 LLM이 결정하게 하세요. + +### 사용 사례 예시 + +**다중 프로젝트 팀:** +```python +memory = Memory() +# 각 프로젝트가 자체 분기를 가짐 +memory.remember("Using microservices architecture", scope="/project/alpha/architecture") +memory.remember("GraphQL API for client apps", scope="/project/beta/api") + +# 모든 프로젝트에서 recall +memory.recall("API design decisions") + +# 특정 프로젝트 내에서만 +memory.recall("API design", scope="/project/beta") +``` + +**공유 지식과 에이전트별 비공개 컨텍스트:** +```python +memory = Memory() + +# 연구원은 비공개 발견을 가짐 +researcher_memory = memory.scope("/agent/researcher") + +# 작성자는 자체 scope와 공유 회사 지식에서 읽을 수 있음 +writer_view = memory.slice( + scopes=["/agent/writer", "/company/knowledge"], + read_only=True, +) +``` + +**고객 지원 (고객별 컨텍스트):** +```python +memory = Memory() + +# 각 고객이 격리된 컨텍스트를 가짐 +memory.remember("Prefers email communication", scope="/customer/acme-corp") +memory.remember("On enterprise plan, 50 seats", scope="/customer/acme-corp") + +# 공유 제품 문서는 모든 에이전트가 접근 가능 +memory.remember("Rate limit is 1000 req/min on enterprise plan", scope="/product/docs") +``` + + +## 메모리 슬라이스 + +### 슬라이스란 무엇인가 + +`MemorySlice`는 여러 개의 분리된 scope에 대한 뷰입니다. 하나의 하위 트리로 제한하는 scope와 달리, 슬라이스는 여러 분기에서 동시에 recall할 수 있게 합니다. + +### 슬라이스 vs 범위 사용 시기 + +- **범위(Scope)**: 에이전트나 코드 블록을 단일 하위 트리로 제한해야 할 때 사용. 예: `/agent/researcher`만 보는 에이전트. +- **슬라이스(Slice)**: 여러 분기의 컨텍스트를 결합해야 할 때 사용. 예: 자체 scope와 공유 회사 지식에서 읽는 에이전트. + +### 읽기 전용 슬라이스 + +가장 일반적인 패턴: 에이전트에게 여러 분기에 대한 읽기 액세스를 제공하되 공유 영역에 쓰지 못하게 합니다. + +```python +memory = Memory() + +# 에이전트는 자체 scope와 회사 지식에서 recall 가능, +# 하지만 회사 지식에 쓸 수 없음 +agent_view = memory.slice( + scopes=["/agent/researcher", "/company/knowledge"], + read_only=True, +) + +matches = agent_view.recall("company security policies", limit=5) +# /agent/researcher와 /company/knowledge 모두에서 검색, 결과 병합 및 순위 매기기 + +agent_view.remember("new finding") # PermissionError 발생 (읽기 전용) +``` + +### 읽기/쓰기 슬라이스 + +읽기 전용이 비활성화되면 포함된 scope 중 어디에든 쓸 수 있지만, 어떤 scope인지 명시적으로 지정해야 합니다. + +```python +view = memory.slice(scopes=["/team/alpha", "/team/beta"], read_only=False) + +# 쓸 때 scope를 반드시 지정 +view.remember("Cross-team decision", scope="/team/alpha", categories=["decisions"]) +``` + + +## 복합 점수(Composite Scoring) + +Recall 결과는 세 가지 신호의 가중 조합으로 순위가 매겨집니다: + +``` +composite = semantic_weight * similarity + recency_weight * decay + importance_weight * importance +``` + +여기서: +- **similarity** = 벡터 인덱스에서 `1 / (1 + distance)` (0에서 1) +- **decay** = `0.5^(age_days / half_life_days)` -- 지수 감쇠 (오늘은 1.0, 반감기에서 0.5) +- **importance** = 레코드의 중요도 점수 (0에서 1), 인코딩 시 설정 + +`Memory` 생성자에서 직접 설정합니다: + +```python +# 스프린트 회고: 최근 메모리 선호, 짧은 반감기 +memory = Memory( + recency_weight=0.5, + semantic_weight=0.3, + importance_weight=0.2, + recency_half_life_days=7, +) + +# 아키텍처 지식 베이스: 중요한 메모리 선호, 긴 반감기 +memory = Memory( + recency_weight=0.1, + semantic_weight=0.5, + importance_weight=0.4, + recency_half_life_days=180, +) +``` + +각 `MemoryMatch`에는 결과가 해당 위치에 순위된 이유를 볼 수 있는 `match_reasons` 목록이 포함됩니다 (예: `["semantic", "recency", "importance"]`). + + +## LLM 분석 레이어 + +메모리는 LLM을 세 가지 방식으로 사용합니다: + +1. **저장 시** -- scope, categories, importance를 생략하면 LLM이 콘텐츠를 분석하여 scope, categories, importance, 메타데이터(엔터티, 날짜, 주제)를 제안합니다. +2. **recall 시** -- deep/auto recall의 경우 LLM이 쿼리(키워드, 시간 힌트, 제안 scope, 복잡도)를 분석하여 검색을 안내합니다. +3. **메모리 추출** -- `extract_memories(content)`는 원시 텍스트(예: 작업 출력)를 개별 메모리 문장으로 나눕니다. 에이전트는 각 문장에 `remember()`를 호출하기 전에 이를 사용하여 하나의 큰 블록 대신 원자적 사실이 저장되도록 합니다. + +모든 분석은 LLM 실패 시 우아하게 저하됩니다 -- [오류 시 동작](#오류-시-동작)을 참조하세요. + + +## 메모리 통합 + +새 콘텐츠를 저장할 때 인코딩 파이프라인은 자동으로 스토리지에서 유사한 기존 레코드를 확인합니다. 유사도가 `consolidation_threshold`(기본값 0.85) 이상이면 LLM이 처리 방법을 결정합니다: + +- **keep** -- 기존 레코드가 여전히 정확하고 중복이 아닙니다. +- **update** -- 기존 레코드를 새 정보로 업데이트해야 합니다 (LLM이 병합된 콘텐츠를 제공). +- **delete** -- 기존 레코드가 오래되었거나, 대체되었거나, 모순됩니다. +- **insert_new** -- 새 콘텐츠를 별도의 레코드로 삽입해야 하는지 여부. + +이를 통해 중복이 축적되는 것을 방지합니다. 예를 들어, "CrewAI ensures reliable operation"을 세 번 저장하면 통합이 중복을 인식하고 하나의 레코드만 유지합니다. + +### 배치 내 중복 제거 + +`remember_many()`를 사용할 때 동일 배치 내의 항목은 스토리지에 도달하기 전에 서로 비교됩니다. 두 항목의 코사인 유사도가 `batch_dedup_threshold`(기본값 0.98) 이상이면 나중 항목이 자동으로 삭제됩니다. 이는 LLM 호출 없이 순수 벡터 연산으로 단일 배치 내의 정확하거나 거의 정확한 중복을 잡아냅니다. + +```python +# 2개의 레코드만 저장됨 (세 번째는 첫 번째의 거의 중복) +memory.remember_many([ + "CrewAI supports complex workflows.", + "Python is a great language.", + "CrewAI supports complex workflows.", # 배치 내 중복 제거로 삭제 +]) +``` + + +## 비차단 저장 + +`remember_many()`는 **비차단**입니다 -- 인코딩 파이프라인을 백그라운드 스레드에 제출하고 즉시 반환합니다. 이는 메모리가 저장되는 동안 에이전트가 다음 작업을 계속할 수 있음을 의미합니다. + +```python +# 즉시 반환 -- 저장은 백그라운드에서 발생 +memory.remember_many(["Fact A.", "Fact B.", "Fact C."]) + +# recall()은 검색 전에 보류 중인 저장을 자동으로 대기 +matches = memory.recall("facts") # 3개 레코드 모두 확인 가능 +``` + +### 읽기 배리어 + +모든 `recall()` 호출은 검색 전에 자동으로 `drain_writes()`를 호출하여 쿼리가 항상 최신 저장된 레코드를 볼 수 있도록 합니다. 이는 투명하게 작동하므로 별도로 신경 쓸 필요가 없습니다. + +### Crew 종료 + +crew가 완료되면 `kickoff()`는 `finally` 블록에서 보류 중인 모든 메모리 저장을 드레인하므로, 백그라운드 저장이 진행 중인 상태에서 crew가 완료되더라도 저장이 손실되지 않습니다. + +### 독립 실행 사용 + +crew 수명 주기가 없는 스크립트나 노트북에서는 `drain_writes()` 또는 `close()`를 명시적으로 호출하세요: + +```python +memory = Memory() +memory.remember_many(["Fact A.", "Fact B."]) + +# 옵션 1: 보류 중인 저장 대기 +memory.drain_writes() + +# 옵션 2: 드레인 후 백그라운드 풀 종료 +memory.close() +``` + + +## 출처 및 개인정보 + +모든 메모리 레코드는 출처 추적을 위한 `source` 태그와 접근 제어를 위한 `private` 플래그를 가질 수 있습니다. + +### 출처 추적 + +`source` 매개변수는 메모리의 출처를 식별합니다: + +```python +# 메모리에 출처 태그 지정 +memory.remember("User prefers dark mode", source="user:alice") +memory.remember("System config updated", source="admin") +memory.remember("Agent found a bug", source="agent:debugger") + +# 특정 출처의 메모리만 recall +matches = memory.recall("user preferences", source="user:alice") +``` + +### 비공개 메모리 + +비공개 메모리는 `source`가 일치할 때만 recall에서 볼 수 있습니다: + +```python +# 비공개 메모리 저장 +memory.remember("Alice's API key is sk-...", source="user:alice", private=True) + +# 이 recall은 비공개 메모리를 볼 수 있음 (source 일치) +matches = memory.recall("API key", source="user:alice") + +# 이 recall은 볼 수 없음 (다른 source) +matches = memory.recall("API key", source="user:bob") + +# 관리자 액세스: source에 관계없이 모든 비공개 레코드 보기 +matches = memory.recall("API key", include_private=True) +``` + +이는 서로 다른 사용자의 메모리가 격리되어야 하는 다중 사용자 또는 엔터프라이즈 배포에서 특히 유용합니다. + + +## RecallFlow (딥 Recall) + +`recall()`은 두 가지 깊이를 지원합니다: + +- **`depth="shallow"`** -- 복합 점수를 사용한 직접 벡터 검색. 빠름 (~200ms), LLM 호출 없음. +- **`depth="deep"` (기본값)** -- 다단계 RecallFlow 실행: 쿼리 분석, scope 선택, 병렬 벡터 검색, 신뢰도 기반 라우팅, 신뢰도가 낮을 때 선택적 재귀 탐색. + +**스마트 LLM 건너뛰기**: `query_analysis_threshold`(기본값 200자)보다 짧은 쿼리는 deep 모드에서도 LLM 쿼리 분석을 완전히 건너뜁니다. "What database do we use?"와 같은 짧은 쿼리는 이미 좋은 검색 구문이므로 LLM 분석이 큰 가치를 더하지 않습니다. 이를 통해 일반적인 짧은 쿼리에서 recall당 ~1-3초를 절약합니다. 긴 쿼리(예: 전체 작업 설명)만 대상 하위 쿼리로의 LLM 분석을 거칩니다. + +```python +# Shallow: 순수 벡터 검색, LLM 없음 +matches = memory.recall("What did we decide?", limit=10, depth="shallow") + +# Deep (기본값): 긴 쿼리에 대한 LLM 분석을 포함한 지능형 검색 +matches = memory.recall( + "Summarize all architecture decisions from this quarter", + limit=10, + depth="deep", +) +``` + +RecallFlow 라우터를 제어하는 신뢰도 임계값은 설정 가능합니다: + +```python +memory = Memory( + confidence_threshold_high=0.9, # 매우 확신할 때만 합성 + confidence_threshold_low=0.4, # 더 적극적으로 깊이 탐색 + exploration_budget=2, # 최대 2라운드 탐색 허용 + query_analysis_threshold=200, # 이보다 짧은 쿼리는 LLM 건너뛰기 +) +``` + + +## Embedder 설정 + +메모리는 의미 검색을 위해 텍스트를 벡터로 변환하는 임베딩 모델이 필요합니다. 세 가지 방법으로 설정할 수 있습니다. + +### Memory에 직접 전달 + +```python +from crewai import Memory + +# 설정 dict로 +memory = Memory(embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-small"}}) + +# 사전 구축된 callable로 +from crewai.rag.embeddings.factory import build_embedder +embedder = build_embedder({"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}) +memory = Memory(embedder=embedder) +``` + +### Crew Embedder 설정으로 + +`memory=True` 사용 시 crew의 `embedder` 설정이 전달됩니다: + +```python +from crewai import Crew + +crew = Crew( + agents=[...], + tasks=[...], + memory=True, + embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-small"}}, +) +``` + +### 제공자 예시 + + + +```python +memory = Memory(embedder={ + "provider": "openai", + "config": { + "model_name": "text-embedding-3-small", + # "api_key": "sk-...", # 또는 OPENAI_API_KEY 환경 변수 설정 + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "ollama", + "config": { + "model_name": "mxbai-embed-large", + "url": "http://localhost:11434/api/embeddings", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "azure", + "config": { + "deployment_id": "your-embedding-deployment", + "api_key": "your-azure-api-key", + "api_base": "https://your-resource.openai.azure.com", + "api_version": "2024-02-01", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "google-generativeai", + "config": { + "model_name": "gemini-embedding-001", + # "api_key": "...", # 또는 GOOGLE_API_KEY 환경 변수 설정 + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "google-vertex", + "config": { + "model_name": "gemini-embedding-001", + "project_id": "your-gcp-project-id", + "location": "us-central1", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "cohere", + "config": { + "model_name": "embed-english-v3.0", + # "api_key": "...", # 또는 COHERE_API_KEY 환경 변수 설정 + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "voyageai", + "config": { + "model": "voyage-3", + # "api_key": "...", # 또는 VOYAGE_API_KEY 환경 변수 설정 + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "amazon-bedrock", + "config": { + "model_name": "amazon.titan-embed-text-v1", + # 기본 AWS 자격 증명 사용 (boto3 세션) + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "huggingface", + "config": { + "model_name": "sentence-transformers/all-MiniLM-L6-v2", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "jina", + "config": { + "model_name": "jina-embeddings-v2-base-en", + # "api_key": "...", # 또는 JINA_API_KEY 환경 변수 설정 + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "watsonx", + "config": { + "model_id": "ibm/slate-30m-english-rtrvr", + "api_key": "your-watsonx-api-key", + "project_id": "your-project-id", + "url": "https://us-south.ml.cloud.ibm.com", + }, +}) +``` + + + +```python +# 문자열 목록을 받아 벡터 목록을 반환하는 callable 전달 +def my_embedder(texts: list[str]) -> list[list[float]]: + # 임베딩 로직 + return [[0.1, 0.2, ...] for _ in texts] + +memory = Memory(embedder=my_embedder) +``` + + + +### 제공자 참조 + +| 제공자 | 키 | 일반적인 모델 | 참고 | +| :--- | :--- | :--- | :--- | +| OpenAI | `openai` | `text-embedding-3-small` | 기본값. `OPENAI_API_KEY` 설정. | +| Ollama | `ollama` | `mxbai-embed-large` | 로컬, API 키 불필요. | +| Azure OpenAI | `azure` | `text-embedding-ada-002` | `deployment_id` 필요. | +| Google AI | `google-generativeai` | `gemini-embedding-001` | `GOOGLE_API_KEY` 설정. | +| Google Vertex | `google-vertex` | `gemini-embedding-001` | `project_id` 필요. | +| Cohere | `cohere` | `embed-english-v3.0` | 강력한 다국어 지원. | +| VoyageAI | `voyageai` | `voyage-3` | 검색에 최적화. | +| AWS Bedrock | `amazon-bedrock` | `amazon.titan-embed-text-v1` | boto3 자격 증명 사용. | +| Hugging Face | `huggingface` | `all-MiniLM-L6-v2` | 로컬 sentence-transformers. | +| Jina | `jina` | `jina-embeddings-v2-base-en` | `JINA_API_KEY` 설정. | +| IBM WatsonX | `watsonx` | `ibm/slate-30m-english-rtrvr` | `project_id` 필요. | +| Sentence Transformer | `sentence-transformer` | `all-MiniLM-L6-v2` | 로컬, API 키 불필요. | +| Custom | `custom` | -- | `embedding_callable` 필요. | + + +## LLM 설정 + +메모리는 저장 분석(scope, categories, importance 추론), 통합 결정, 딥 recall 쿼리 분석에 LLM을 사용합니다. 사용할 모델을 설정할 수 있습니다. + +```python +from crewai import Memory, LLM + +# 기본값: gpt-4o-mini +memory = Memory() + +# 다른 OpenAI 모델 사용 +memory = Memory(llm="gpt-4o") + +# Anthropic 사용 +memory = Memory(llm="anthropic/claude-3-haiku-20240307") + +# 완전한 로컬/비공개 분석을 위해 Ollama 사용 +memory = Memory(llm="ollama/llama3.2") + +# Google Gemini 사용 +memory = Memory(llm="gemini/gemini-2.0-flash") + +# 사용자 정의 설정이 있는 사전 구성된 LLM 인스턴스 전달 +llm = LLM(model="gpt-4o", temperature=0) +memory = Memory(llm=llm) +``` + +LLM은 **지연 초기화**됩니다 -- 처음 필요할 때만 생성됩니다. 즉, API 키가 설정되지 않아도 `Memory()` 생성 시에는 실패하지 않습니다. 오류는 LLM이 실제로 호출될 때만 발생합니다(예: 명시적 scope/categories 없이 저장할 때 또는 딥 recall 중). + +완전한 오프라인/비공개 운영을 위해 LLM과 embedder 모두에 로컬 모델을 사용하세요: + +```python +memory = Memory( + llm="ollama/llama3.2", + embedder={"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}, +) +``` + + +## 스토리지 백엔드 + +- **기본값**: LanceDB, `./.crewai/memory` 아래에 저장 (또는 환경 변수가 설정된 경우 `$CREWAI_STORAGE_DIR/memory`, 또는 `storage="path/to/dir"`로 전달한 경로). +- **사용자 정의 백엔드**: `StorageBackend` 프로토콜을 구현하고(`crewai.memory.storage.backend` 참조) `Memory(storage=your_backend)`에 인스턴스를 전달합니다. + + +## 탐색(Discovery) + +scope 계층 구조, 카테고리, 레코드를 검사합니다: + +```python +memory.tree() # scope 및 레코드 수의 포맷된 트리 +memory.tree("/project", max_depth=2) # 하위 트리 뷰 +memory.info("/project") # ScopeInfo: record_count, categories, oldest/newest +memory.list_scopes("/") # 직계 자식 scope +memory.list_categories() # 카테고리 이름 및 개수 +memory.list_records(scope="/project/alpha", limit=20) # scope의 레코드, 최신순 +``` + + +## 오류 시 동작 + +분석 중 LLM이 실패하면(네트워크 오류, 속도 제한, 잘못된 응답) 메모리는 우아하게 저하됩니다: + +- **저장 분석** -- 경고가 로깅되고 메모리는 기본 scope `/`, 빈 categories, importance `0.5`로 저장됩니다. +- **메모리 추출** -- 전체 콘텐츠가 단일 메모리로 저장되어 누락되지 않습니다. +- **쿼리 분석** -- recall은 단순 scope 선택 및 벡터 검색으로 폴백하여 결과를 계속 반환합니다. + +이러한 분석 실패에서는 예외가 발생하지 않으며, 스토리지 또는 embedder 실패만 예외를 발생시킵니다. + + +## 개인정보 참고 + +메모리 콘텐츠는 분석을 위해 설정된 LLM으로 전송됩니다(저장 시 scope/categories/importance, 쿼리 분석 및 선택적 딥 recall). 민감한 데이터의 경우 로컬 LLM(예: Ollama)을 사용하거나 제공자가 규정 요구 사항을 충족하는지 확인하세요. + + +## 메모리 이벤트 + +모든 메모리 연산은 `source_type="unified_memory"`로 이벤트를 발생시킵니다. 시간, 오류, 콘텐츠를 수신할 수 있습니다. + +| 이벤트 | 설명 | 주요 속성 | +| :---- | :---------- | :------------- | +| **MemoryQueryStartedEvent** | 쿼리 시작 | `query`, `limit` | +| **MemoryQueryCompletedEvent** | 쿼리 성공 | `query`, `results`, `query_time_ms` | +| **MemoryQueryFailedEvent** | 쿼리 실패 | `query`, `error` | +| **MemorySaveStartedEvent** | 저장 시작 | `value`, `metadata` | +| **MemorySaveCompletedEvent** | 저장 성공 | `value`, `save_time_ms` | +| **MemorySaveFailedEvent** | 저장 실패 | `value`, `error` | +| **MemoryRetrievalStartedEvent** | 에이전트 검색 시작 | `task_id` | +| **MemoryRetrievalCompletedEvent** | 에이전트 검색 완료 | `task_id`, `memory_content`, `retrieval_time_ms` | + +예: 쿼리 시간 모니터링: + +```python +from crewai.events import BaseEventListener, MemoryQueryCompletedEvent + +class MemoryMonitor(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(MemoryQueryCompletedEvent) + def on_done(source, event): + if getattr(event, "source_type", None) == "unified_memory": + print(f"Query '{event.query}' completed in {event.query_time_ms:.0f}ms") +``` + + +## 문제 해결 + +**메모리가 유지되지 않나요?** +- 저장 경로에 쓰기 권한이 있는지 확인하세요(기본값 `./.crewai/memory`). 다른 디렉터리를 사용하려면 `storage="./your_path"`를 전달하거나 `CREWAI_STORAGE_DIR` 환경 변수를 설정하세요. +- crew 사용 시 `memory=True` 또는 `memory=Memory(...)`가 설정되었는지 확인하세요. + +**recall이 느린가요?** +- 일상적인 에이전트 컨텍스트에는 `depth="shallow"`를 사용하세요. 복잡한 쿼리에만 `depth="deep"`을 사용하세요. +- 더 많은 쿼리에서 LLM 분석을 건너뛰려면 `query_analysis_threshold`를 높이세요. + +**로그에 LLM 분석 오류가 있나요?** +- 메모리는 안전한 기본값으로 계속 저장/recall합니다. 전체 LLM 분석을 원하면 API 키, 속도 제한, 모델 가용성을 확인하세요. + +**로그에 백그라운드 저장 오류가 있나요?** +- 메모리 저장은 백그라운드 스레드에서 실행됩니다. 오류는 `MemorySaveFailedEvent`로 발생하지만 에이전트를 중단시키지 않습니다. 근본 원인(보통 LLM 또는 embedder 연결 문제)은 로그를 확인하세요. + +**동시 쓰기 충돌이 있나요?** +- LanceDB 연산은 공유 잠금으로 직렬화되며 충돌 시 자동으로 재시도됩니다. 이는 동일 데이터베이스를 가리키는 여러 `Memory` 인스턴스(예: 에이전트 메모리 + crew 메모리)를 처리합니다. 별도의 조치가 필요하지 않습니다. + +**터미널에서 메모리 탐색:** +```bash +crewai memory # TUI 브라우저 열기 +crewai memory --storage-path ./my_memory # 특정 디렉터리 지정 +``` + +**메모리 초기화(예: 테스트용):** +```python +crew.reset_memories(command_type="memory") # 통합 메모리 초기화 +# 또는 Memory 인스턴스에서: +memory.reset() # 모든 scope +memory.reset(scope="/project/old") # 해당 하위 트리만 +``` + + +## 설정 참조 + +모든 설정은 `Memory(...)`에 키워드 인수로 전달됩니다. 모든 매개변수에는 합리적인 기본값이 있습니다. + +| 매개변수 | 기본값 | 설명 | +| :--- | :--- | :--- | +| `llm` | `"gpt-4o-mini"` | 분석용 LLM (모델 이름 또는 `BaseLLM` 인스턴스). | +| `storage` | `"lancedb"` | 스토리지 백엔드 (`"lancedb"`, 경로 문자열 또는 `StorageBackend` 인스턴스). | +| `embedder` | `None` (OpenAI 기본값) | Embedder (설정 dict, callable 또는 `None`으로 기본 OpenAI). | +| `recency_weight` | `0.3` | 복합 점수에서 최신성 가중치. | +| `semantic_weight` | `0.5` | 복합 점수에서 의미 유사도 가중치. | +| `importance_weight` | `0.2` | 복합 점수에서 중요도 가중치. | +| `recency_half_life_days` | `30` | 최신성 점수가 절반으로 줄어드는 일수(지수 감쇠). | +| `consolidation_threshold` | `0.85` | 저장 시 통합이 트리거되는 유사도. `1.0`으로 설정하면 비활성화. | +| `consolidation_limit` | `5` | 통합 중 비교할 기존 레코드 최대 수. | +| `default_importance` | `0.5` | 미제공 시 및 LLM 분석이 생략될 때 할당되는 중요도. | +| `batch_dedup_threshold` | `0.98` | `remember_many()` 배치 내 거의 중복 삭제를 위한 코사인 유사도. | +| `confidence_threshold_high` | `0.8` | recall 신뢰도가 이 값 이상이면 결과를 직접 반환. | +| `confidence_threshold_low` | `0.5` | recall 신뢰도가 이 값 미만이면 더 깊은 탐색 트리거. | +| `complex_query_threshold` | `0.7` | 복잡한 쿼리의 경우 이 신뢰도 미만에서 더 깊이 탐색. | +| `exploration_budget` | `1` | 딥 recall 중 LLM 기반 탐색 라운드 수. | +| `query_analysis_threshold` | `200` | 이 길이(문자 수)보다 짧은 쿼리는 딥 recall 중 LLM 분석을 건너뜀. | diff --git a/docs/v1.15.13/ko/concepts/planning.mdx b/docs/v1.15.13/ko/concepts/planning.mdx new file mode 100644 index 0000000000..2d3dccda65 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/planning.mdx @@ -0,0 +1,153 @@ +--- +title: 계획 +description: CrewAI Crew에 계획을 추가하고 성능을 향상시키는 방법을 알아보세요. +icon: ruler-combined +mode: "wide" +--- + +## 개요 + +CrewAI의 planning 기능을 통해 crew에 계획 수립 기능을 추가할 수 있습니다. 해당 기능을 활성화하면, 각 Crew 반복 전에 모든 Crew 정보가 AgentPlanner로 전송되어 작업이 단계별로 계획되며, 이 계획이 각 작업 설명에 추가됩니다. + +### Planning 기능 사용하기 + +Planning 기능을 시작하는 것은 매우 간단합니다. 필요한 유일한 단계는 Crew에 `planning=True`를 추가하는 것입니다: + + +```python Code +from crewai import Crew, Agent, Task, Process + +# Assemble your crew with planning capabilities +my_crew = Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + planning=True, +) +``` + + +이 시점부터 crew는 planning이 활성화되며, 각 반복 전에 작업이 계획됩니다. + + +Planning이 활성화되면, crewAI는 planning을 위해 기본 LLM으로 `gpt-4o-mini`를 사용합니다. 이 기능은 유효한 OpenAI API 키가 필요합니다. 에이전트가 서로 다른 LLM을 사용할 수도 있기 때문에, OpenAI API 키가 설정되어 있지 않거나 LLM API 호출과 관련된 예상치 못한 동작이 발생할 경우 혼란을 일으킬 수 있습니다. + + +#### LLM 계획하기 + +이제 작업을 계획할 때 사용할 LLM을 정의할 수 있습니다. + +기본 사례 예제를 실행하면 아래와 같은 출력이 나타나는데, 이는 AgentPlanner의 출력으로, 에이전트 작업에 추가할 단계별 논리를 생성합니다. + + +```python Code +from crewai import Crew, Agent, Task, Process + +# Assemble your crew with planning capabilities and custom LLM +my_crew = Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + planning=True, + planning_llm="gpt-4o" +) + +# Run the crew +my_crew.kickoff() +``` + +```markdown Result +[2024-07-15 16:49:11][INFO]: Planning the crew execution +**작업 실행을 위한 단계별 계획** + +**작업 번호 1: AI LLM에 대해 철저히 조사하기** + +**에이전트:** AI LLMs 시니어 데이터 리서처 + +**에이전트 목표:** AI LLM의 최신 개발 동향 파악 + +**작업 예상 결과:** AI LLM에 대한 가장 관련성 높은 정보 10가지가 포함된 리스트 + +**작업 도구:** 명시되지 않음 + +**에이전트 도구:** 명시되지 않음 + +**단계별 계획:** + +1. **조사 범위 정의:** + + - 아키텍처의 발전, 사용 사례, 윤리적 고려사항, 성능 측정 기준 등 AI LLM의 특정 영역을 결정합니다. + +2. **신뢰할 수 있는 출처 식별:** + + - 학술지, 산업 리포트, 컨퍼런스(예: NeurIPS, ACL), AI 연구소(예: OpenAI, Google AI), 온라인 데이터베이스(예: IEEE Xplore, arXiv) 등 AI 연구를 위한 평판 좋은 출처를 나열합니다. + +3. **데이터 수집:** + + - 2024년 및 2025년 초에 발표된 최신 논문, 기사, 리포트를 검색합니다. + - "Large Language Models 2025", "AI LLM advancements", "AI ethics 2025"와 같은 키워드를 사용합니다. + +4. **발견 사항 분석:** + + - 각 출처에서 핵심 내용을 읽고 요약합니다. + - 지난 1년간 소개된 새로운 기술, 모델, 애플리케이션 등을 강조합니다. + +5. **정보 정리:** + + - 정보를 관련 주제별로 분류합니다(예: 새로운 아키텍처, 윤리적 영향, 실세계 적용 등). + - 각 핵심 포인트는 간결하면서도 정보가 풍부하도록 합니다. + +6. **리스트 작성:** + + - 가장 관련성 높은 10가지 정보를 불릿 포인트로 정리합니다. + - 리스트가 명확하고 적절한지 검토합니다. + +**예상 결과:** + +AI LLM에 대한 가장 관련성 높은 정보 10가지를 담은 불릿 포인트 리스트. + +--- + +**작업 번호 2: 받은 컨텍스트를 검토하고 각 주제를 리포트의 전체 섹션으로 확장하기** + +**에이전트:** AI LLMs 리포팅 애널리스트 + +**에이전트 목표:** AI LLM 데이터 분석 및 연구 결과를 기반으로 상세 리포트를 작성 + +**작업 예상 결과:** 주요 주제별로 각 섹션이 포함된 완전한 리포트 (마크다운 형식, '```' 없이) + +**작업 도구:** 명시되지 않음 + +**에이전트 도구:** 명시되지 않음 + +**단계별 계획:** + +1. **불릿 포인트 검토:** + - AI LLMs 시니어 데이터 리서처가 제공한 10가지 불릿 포인트 리스트를 꼼꼼히 읽습니다. + +2. **리포트 개요 작성:** + - 각 불릿 포인트를 주요 섹션 제목으로 삼아 개요를 만듭니다. + - 각 주요 제목 아래 하위 섹션을 기획하여 해당 주제의 다양한 측면을 다룹니다. + +3. **추가 세부 사항 조사:** + - 각 불릿 포인트별로, 더 자세한 정보를 수집하기 위해 필요 시 추가 조사를 진행합니다. + - 각 섹션을 뒷받침할 사례 연구, 예시, 통계자료 등을 찾습니다. + +4. **상세 섹션 작성:** + - 각 불릿 포인트를 포괄적인 섹션으로 확장합니다. + - 각 섹션에는 도입, 상세 설명, 예시, 결론이 포함되어야 합니다. + - 제목, 부제목, 리스트, 강조 등 마크다운 포맷을 사용합니다. + +5. **검토 및 편집:** + - 리포트의 명확성, 일관성, 정확성을 위해 교정합니다. + - 리포트가 각 섹션에서 논리적으로 자연스럽게 흐르는지 확인합니다. + - 마크다운 기준에 맞게 포맷을 맞춥니다. + +6. **리포트 최종화:** + - 모든 섹션이 확장되고 상세하게 작성되어 완전한 리포트가 되었는지 확인합니다. + - 포맷을 다시 확인하고 필요한 경우 수정합니다. + +**예상 결과:** +주요 주제별로 각 섹션이 포함된 완전한 리포트 (마크다운 형식, '```' 없이). +``` + \ No newline at end of file diff --git a/docs/v1.15.13/ko/concepts/processes.mdx b/docs/v1.15.13/ko/concepts/processes.mdx new file mode 100644 index 0000000000..d6b52f018d --- /dev/null +++ b/docs/v1.15.13/ko/concepts/processes.mdx @@ -0,0 +1,66 @@ +--- +title: 프로세스 +description: CrewAI에서 프로세스를 통한 워크플로우 관리에 대한 상세 가이드와 최신 구현 세부 사항. +icon: bars-staggered +mode: "wide" +--- + +## 개요 + + + 프로세스는 에이전트에 의해 작업이 실행되도록 조정하며, 이는 인간 팀에서의 프로젝트 관리와 유사합니다. + 이러한 프로세스는 작업이 미리 정의된 전략에 따라 효율적으로 분배되고 실행되도록 보장합니다. + + +## 프로세스 구현 + +- **순차적(Sequential)**: 작업을 순차적으로 실행하여 작업이 질서 있게 진행되도록 보장합니다. +- **계층적(Hierarchical)**: 작업을 관리 계층 구조로 조직하며, 작업은 체계적인 명령 체계를 기반으로 위임 및 실행됩니다. 계층적 프로세스를 활성화하려면 매니저 언어 모델(`manager_llm`) 또는 커스텀 매니저 에이전트(`manager_agent`)를 crew에서 지정해야 하며, 이를 통해 매니저가 작업을 생성하고 관리할 수 있도록 지원합니다. + +## 팀워크에서 프로세스의 역할 +프로세스는 개별 에이전트가 통합된 단위로 작동할 수 있도록 하여, 공통된 목표를 효율적이고 일관성 있게 달성하도록 노력하는 과정을 간소화합니다. + +## 프로세스를 Crew에 할당하기 +프로세스를 crew에 할당하려면, crew 생성 시 프로세스 유형을 지정하여 실행 전략을 설정합니다. 계층적 프로세스의 경우, 매니저 에이전트에 대해 `manager_llm` 또는 `manager_agent`를 반드시 정의해야 합니다. + +```python +from crewai import Crew, Process + +# Example: Creating a crew with a sequential process +crew = Crew( + agents=my_agents, + tasks=my_tasks, + process=Process.sequential +) + +# Example: Creating a crew with a hierarchical process +# Ensure to provide a manager_llm or manager_agent +crew = Crew( + agents=my_agents, + tasks=my_tasks, + process=Process.hierarchical, + manager_llm="gpt-4o" + # or + # manager_agent=my_manager_agent +) +``` +**참고:** `Crew` 객체를 생성하기 전에 반드시 `my_agents`와 `my_tasks`가 정의되어 있어야 하며, 계층적 프로세스의 경우 `manager_llm` 또는 `manager_agent` 중 하나도 필요합니다. + +## 순차적 프로세스 + +이 방법은 동적인 팀 워크플로우를 반영하며, 작업을 신중하고 체계적으로 진행합니다. 작업 수행은 작업 목록에 정의된 순서를 따르며, 한 작업의 출력이 다음 작업의 컨텍스트로 사용됩니다. + +작업 컨텍스트를 사용자 지정하려면, `Task` 클래스의 `context` 매개변수를 사용하여 이후 작업에 컨텍스트로 사용될 출력을 지정하세요. + +## 계층적 프로세스 + +기업의 계층 구조를 모방하는 CrewAI는 사용자 지정 관리자 에이전트를 지정하거나 자동으로 생성할 수 있으며, 이때 관리자 언어 모델(`manager_llm`)의 지정을 요구합니다. 이 에이전트는 계획 수립, 위임, 검증 등 작업 실행을 감독합니다. 작업은 미리 할당되지 않으며, 관리자가 에이전트의 역량에 따라 작업을 분배하고, 산출물을 검토하며, 작업 완료 여부를 평가합니다. + +## Process 클래스: 상세 개요 + +`Process` 클래스는 열거형(`Enum`)으로 구현되어 타입 안전성을 보장하며, 프로세스 값을 정의된 타입(`sequential`, `hierarchical`)으로 제한합니다. + +## 결론 + +CrewAI 내의 프로세스를 통해 촉진되는 구조화된 협업은 에이전트 간 체계적인 팀워크를 가능하게 하는 데 매우 중요합니다. +이 문서는 최신 기능과 향상 사항을 반영하도록 업데이트되었으며, 사용자가 가장 최신이고 포괄적인 정보를 이용할 수 있도록 보장합니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/concepts/production-architecture.mdx b/docs/v1.15.13/ko/concepts/production-architecture.mdx new file mode 100644 index 0000000000..d089a18032 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/production-architecture.mdx @@ -0,0 +1,162 @@ +--- +title: 프로덕션 아키텍처 +description: CrewAI로 프로덕션 수준의 AI 애플리케이션을 구축하기 위한 모범 사례 +icon: server +mode: "wide" +--- + +# Flow 우선 사고방식 (Flow-First Mindset) + +CrewAI로 프로덕션 AI 애플리케이션을 구축할 때는 **Flow로 시작하는 것을 권장합니다**. + +개별 Crews나 Agents를 실행하는 것도 가능하지만, 이를 Flow로 감싸면 견고하고 확장 가능한 애플리케이션에 필요한 구조를 제공합니다. + +## 왜 Flows인가? + +1. **상태 관리 (State Management)**: Flows는 애플리케이션의 여러 단계에 걸쳐 상태를 관리하는 내장된 방법을 제공합니다. 이는 Crews 간에 데이터를 전달하고, 컨텍스트를 유지하며, 사용자 입력을 처리하는 데 중요합니다. +2. **제어 (Control)**: Flows를 사용하면 루프, 조건문, 분기 로직을 포함한 정확한 실행 경로를 정의할 수 있습니다. 이는 예외 상황을 처리하고 애플리케이션이 예측 가능하게 동작하도록 보장하는 데 필수적입니다. +3. **관측 가능성 (Observability)**: Flows는 실행을 추적하고, 문제를 디버깅하며, 성능을 모니터링하기 쉽게 만드는 명확한 구조를 제공합니다. 자세한 통찰력을 얻으려면 [CrewAI Tracing](/ko/observability/tracing)을 사용하는 것이 좋습니다. `crewai login`을 실행하여 무료 관측 가능성 기능을 활성화하세요. + +## 아키텍처 + +일반적인 프로덕션 CrewAI 애플리케이션은 다음과 같습니다: + +```mermaid +graph TD + Start((시작)) --> Flow[Flow 오케스트레이터] + Flow --> State{상태 관리} + State --> Step1[1단계: 데이터 수집] + Step1 --> Crew1[연구 Crew] + Crew1 --> State + State --> Step2{조건 확인} + Step2 -- "유효함" --> Step3[3단계: 실행] + Step3 --> Crew2[액션 Crew] + Step2 -- "유효하지 않음" --> End((종료)) + Crew2 --> End +``` + +### 1. Flow 클래스 +`Flow` 클래스는 진입점입니다. 상태 스키마와 로직을 실행하는 메서드를 정의합니다. + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class AppState(BaseModel): + user_input: str = "" + research_results: str = "" + final_report: str = "" + +class ProductionFlow(Flow[AppState]): + @start() + def gather_input(self): + # ... 입력 받는 로직 ... + pass + + @listen(gather_input) + def run_research_crew(self): + # ... Crew 트리거 ... + pass +``` + +### 2. 상태 관리 (State Management) +Pydantic 모델을 사용하여 상태를 정의하세요. 이는 타입 안전성을 보장하고 각 단계에서 어떤 데이터를 사용할 수 있는지 명확하게 합니다. + +- **최소한으로 유지**: 단계 간에 유지해야 할 것만 저장하세요. +- **구조화된 데이터 사용**: 가능하면 비구조화된 딕셔너리는 피하세요. + +### 3. 작업 단위로서의 Crews +복잡한 작업은 Crews에게 위임하세요. Crew는 특정 목표(예: "주제 연구", "블로그 게시물 작성")에 집중해야 합니다. + +- **Crews를 과도하게 설계하지 마세요**: 집중력을 유지하세요. +- **상태를 명시적으로 전달하세요**: Flow 상태에서 필요한 데이터를 Crew 입력으로 전달하세요. + +```python + @listen(gather_input) + def run_research_crew(self): + crew = ResearchCrew() + result = crew.kickoff(inputs={"topic": self.state.user_input}) + self.state.research_results = result.raw +``` + +## Control Primitives + +CrewAI의 Control Primitives를 활용하여 Crew에 견고함과 제어력을 더하세요. + +### 1. Task Guardrails +[Task Guardrails](/ko/concepts/tasks#task-guardrails)를 사용하여 작업 결과가 수락되기 전에 유효성을 검사하세요. 이를 통해 agent가 고품질 결과를 생성하도록 보장할 수 있습니다. + +```python +def validate_content(result: TaskOutput) -> Tuple[bool, Any]: + if len(result.raw) < 100: + return (False, "Content is too short. Please expand.") + return (True, result.raw) + +task = Task( + ..., + guardrail=validate_content +) +``` + +### 2. 구조화된 출력 (Structured Outputs) +작업 간에 데이터를 전달하거나 애플리케이션으로 전달할 때는 항상 구조화된 출력(`output_pydantic` 또는 `output_json`)을 사용하세요. 이는 파싱 오류를 방지하고 타입 안전성을 보장합니다. + +```python +class ResearchResult(BaseModel): + summary: str + sources: List[str] + +task = Task( + ..., + output_pydantic=ResearchResult +) +``` + +### 3. LLM Hooks +[LLM Hooks](/ko/learn/llm-hooks)를 사용하여 LLM으로 전송되기 전에 메시지를 검사하거나 수정하고, 응답을 정리(sanitize)하세요. + +```python +@before_llm_call +def log_request(context): + print(f"Agent {context.agent.role} is calling the LLM...") +``` + +## 배포 패턴 + +Flow를 배포할 때 다음을 고려하세요: + +### CrewAI Enterprise +Flow를 배포하는 가장 쉬운 방법은 CrewAI Enterprise를 사용하는 것입니다. 인프라, 인증 및 모니터링을 대신 처리합니다. + +시작하려면 [배포 가이드](https://docs-platform.crewai.com/platform/ko/guides/deploy-to-amp)를 확인하세요. + +```bash +crewai deploy create +``` + +### 비동기 실행 (Async Execution) +장기 실행 작업의 경우 `kickoff_async`를 사용하여 API 차단을 방지하세요. + +### 지속성 (Persistence) +`@persist` 데코레이터를 사용하여 Flow의 상태를 데이터베이스에 저장하세요. 이를 통해 프로세스가 중단되거나 사람의 입력을 기다려야 할 때 실행을 재개할 수 있습니다. + +```python +@persist +class ProductionFlow(Flow[AppState]): + # ... +``` + +기본적으로, `@persist`는 `kickoff(inputs={"id": })`가 제공될 때 플로우를 재개하여 동일한 `flow_uuid` 기록을 확장합니다. 영속된 플로우를 새 계보로 **포크**하려면 — 이전 실행에서 상태를 하이드레이트하지만 새로운 `state.id` 아래에 기록 — `restore_from_state_id`를 전달하세요: + +```python +flow.kickoff(restore_from_state_id="") +``` + +새 실행은 새로운 `state.id`(자동 생성, 또는 `inputs["id"]`가 고정된 경우 그 값)를 받아 `@persist` 기록이 원본의 기록을 확장하지 않도록 합니다. `from_checkpoint`와 결합하면 `ValueError`가 발생합니다; 하나의 하이드레이션 소스를 선택하세요. + +## 요약 + +- **Flow로 시작하세요.** +- **명확한 State를 정의하세요.** +- **복잡한 작업에는 Crews를 사용하세요.** +- **API와 지속성을 갖추어 배포하세요.** diff --git a/docs/v1.15.13/ko/concepts/reasoning.mdx b/docs/v1.15.13/ko/concepts/reasoning.mdx new file mode 100644 index 0000000000..2a9cd9e1c7 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/reasoning.mdx @@ -0,0 +1,148 @@ +--- +title: Reasoning +description: "에이전트 reasoning을 활성화하고 사용하는 방법을 배워 작업 실행을 향상하세요." +icon: brain +mode: "wide" +--- + +## 개요 + +Agent reasoning은 에이전트가 작업을 수행하기 전에 해당 작업을 반성하고 계획을 수립할 수 있도록 해주는 기능입니다. 이를 통해 에이전트는 작업에 더 체계적으로 접근할 수 있으며, 할당된 업무를 수행할 준비가 되었는지 확인할 수 있습니다. + +## 사용 방법 + +에이전트에 reasoning을 활성화하려면 에이전트를 생성할 때 `reasoning=True`로 설정하면 됩니다. + +```python +from crewai import Agent + +agent = Agent( + role="Data Analyst", + goal="Analyze complex datasets and provide insights", + backstory="You are an experienced data analyst with expertise in finding patterns in complex data.", + reasoning=True, # Enable reasoning + max_reasoning_attempts=3 # Optional: Set a maximum number of reasoning attempts +) +``` + +## 작동 방식 + +reasoning이 활성화되면, 작업을 실행하기 전에 에이전트는 다음을 수행합니다: + +1. 작업을 반영하고 상세한 계획을 수립합니다. +2. 작업을 실행할 준비가 되었는지 평가합니다. +3. 준비가 완료되거나 max_reasoning_attempts에 도달할 때까지 필요에 따라 계획을 다듬습니다. +4. reasoning 계획을 실행 전에 작업 설명에 삽입합니다. + +이 프로세스는 에이전트가 복잡한 작업을 관리하기 쉬운 단계로 분해하고, 시작하기 전에 잠재적인 문제를 식별하는 데 도움을 줍니다. + +## 구성 옵션 + + + reasoning 활성화 또는 비활성화 + + + + 실행을 진행하기 전에 계획을 개선할 최대 시도 횟수입니다. None(기본값)인 경우, agent는 준비될 때까지 계속해서 개선을 시도합니다. + + +## 예제 + +다음은 전체 예제입니다: + +```python +from crewai import Agent, Task, Crew + +# Create an agent with reasoning enabled +analyst = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + backstory="You are an expert data analyst.", + reasoning=True, + max_reasoning_attempts=3 # Optional: Set a limit on reasoning attempts +) + +# Create a task +analysis_task = Task( + description="Analyze the provided sales data and identify key trends.", + expected_output="A report highlighting the top 3 sales trends.", + agent=analyst +) + +# Create a crew and run the task +crew = Crew(agents=[analyst], tasks=[analysis_task]) +result = crew.kickoff() + +print(result) +``` + +## 오류 처리 + +reasoning 프로세스는 견고하게 설계되어 있으며, 오류 처리가 내장되어 있습니다. reasoning 중에 오류가 발생하면, 에이전트는 reasoning 계획 없이 작업을 계속 실행합니다. 이는 reasoning 프로세스가 실패하더라도 작업이 계속 실행될 수 있도록 보장합니다. + +코드에서 발생할 수 있는 오류를 처리하는 방법은 다음과 같습니다: + +```python +from crewai import Agent, Task +import logging + +# reasoning 오류를 캡처하기 위해 로깅을 설정합니다 +logging.basicConfig(level=logging.INFO) + +# reasoning이 활성화된 에이전트를 생성합니다 +agent = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + reasoning=True, + max_reasoning_attempts=3 +) + +# 작업을 생성합니다 +task = Task( + description="Analyze the provided sales data and identify key trends.", + expected_output="A report highlighting the top 3 sales trends.", + agent=agent +) + +# 작업 실행 +# reasoning 중 오류가 발생해도 로그에 기록되며 실행은 계속됩니다 +result = agent.execute_task(task) +``` + +## 예시 Reasoning 출력 + +다음은 데이터 분석 작업을 위한 reasoning 계획의 예시입니다: + +``` +Task: Analyze the provided sales data and identify key trends. + +Reasoning Plan: +I'll analyze the sales data to identify the top 3 trends. + +1. Understanding of the task: + I need to analyze sales data to identify key trends that would be valuable for business decision-making. + +2. Key steps I'll take: + - First, I'll examine the data structure to understand what fields are available + - Then I'll perform exploratory data analysis to identify patterns + - Next, I'll analyze sales by time periods to identify temporal trends + - I'll also analyze sales by product categories and customer segments + - Finally, I'll identify the top 3 most significant trends + +3. Approach to challenges: + - If the data has missing values, I'll decide whether to fill or filter them + - If the data has outliers, I'll investigate whether they're valid data points or errors + - If trends aren't immediately obvious, I'll apply statistical methods to uncover patterns + +4. Use of available tools: + - I'll use data analysis tools to explore and visualize the data + - I'll use statistical tools to identify significant patterns + - I'll use knowledge retrieval to access relevant information about sales analysis + +5. Expected outcome: + A concise report highlighting the top 3 sales trends with supporting evidence from the data. + +READY: I am ready to execute the task. +``` + +이 reasoning 계획은 agent가 작업에 접근하는 방식을 체계적으로 구성하고, 발생할 수 있는 잠재적 문제를 고려하며, 기대되는 결과를 제공하도록 돕습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/concepts/skills.mdx b/docs/v1.15.13/ko/concepts/skills.mdx new file mode 100644 index 0000000000..1bf4e881fe --- /dev/null +++ b/docs/v1.15.13/ko/concepts/skills.mdx @@ -0,0 +1,373 @@ +--- +title: 스킬 +description: 에이전트 프롬프트에 도메인 전문성과 지침을 주입하는 파일 시스템 기반 스킬 패키지. +icon: bolt +mode: "wide" +--- + +## 개요 + +스킬은 에이전트에게 **도메인별 지침, 가이드라인 및 참조 자료**를 제공하는 자체 포함 디렉터리입니다. 각 스킬은 YAML 프론트매터와 마크다운 본문이 포함된 `SKILL.md` 파일로 정의됩니다. + +활성화되면 스킬의 지침이 에이전트의 작업 프롬프트에 직접 주입됩니다 — 코드 변경 없이 에이전트에게 전문성을 부여합니다. + + +**스킬은 도구가 아닙니다.** 이것이 가장 흔한 혼동 포인트입니다. + +- **스킬**은 에이전트의 프롬프트에 *지침과 컨텍스트*를 주입합니다. 에이전트에게 문제에 대해 *어떻게 생각할지*를 알려줍니다. +- **도구**는 에이전트에게 행동을 취할 수 있는 *호출 가능한 함수*를 제공합니다 (검색, 파일 읽기, API 호출). + +흔히 **둘 다** 필요합니다: 전문성을 위한 스킬과 행동을 위한 도구. 이들은 독립적으로 구성되며 서로 보완합니다. + + +--- + +## 빠른 시작 + +### 1. CLI로 스킬 생성 + +CLI는 스킬을 생성하는 공식 지원 방식입니다 — 디렉터리 레이아웃과 유효한 `SKILL.md`를 자동으로 스캐폴딩해 줍니다: + +```shell Terminal +crewai skill create code-review +``` + +크루 프로젝트 내부(`pyproject.toml`이 있는 곳)에서는 `./skills/code-review/`가 생성되고, 프로젝트 외부에서는 현재 디렉터리에 `./code-review/`가 생성됩니다 (`--no-project`로 이 동작을 강제할 수 있습니다): + +``` +skills/ +└── code-review/ + ├── SKILL.md # 필수 — 지침 (미리 채워진 템플릿) + ├── references/ # 선택 — 참조 문서 + ├── scripts/ # 선택 — 실행 가능한 스크립트 + └── assets/ # 선택 — 정적 파일 +``` + +### 2. SKILL.md 작성 + +```markdown +--- +name: code-review +description: Guidelines for conducting thorough code reviews with focus on security and performance. +metadata: + author: your-team + version: "1.0" +--- + +## 코드 리뷰 가이드라인 + +코드를 리뷰할 때 이 체크리스트를 따르세요: + +1. **보안**: 인젝션 취약점, 인증 우회, 데이터 노출 확인 +2. **성능**: N+1 쿼리, 불필요한 할당, 블로킹 호출 확인 +3. **가독성**: 명확한 네이밍, 적절한 주석, 일관된 스타일 보장 +4. **테스트**: 새로운 기능에 대한 적절한 테스트 커버리지 확인 + +### 심각도 수준 +- **크리티컬**: 보안 취약점, 데이터 손실 위험 → 머지 차단 +- **메이저**: 성능 문제, 로직 오류 → 변경 요청 +- **마이너**: 스타일 문제, 네이밍 제안 → 코멘트와 함께 승인 +``` + +### 3. 에이전트에 연결 + +```python +from crewai import Agent +from crewai_tools import GithubSearchTool, FileReadTool + +reviewer = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["./skills"], # 리뷰 가이드라인 주입 + tools=[GithubSearchTool(), FileReadTool()], # 에이전트가 코드를 읽을 수 있게 함 +) +``` + +이제 에이전트는 **전문성** (스킬에서)과 **기능** (도구에서) 모두를 갖추게 됩니다. + +--- + +## 스킬 + 도구: 함께 작동하기 + +스킬과 도구가 어떻게 보완하는지 보여주는 일반적인 패턴입니다: + +### 패턴 1: 스킬만 (도메인 전문성, 액션 불필요) + +에이전트가 특정 지침이 필요하지만 외부 서비스를 호출할 필요가 없을 때 사용: + +```python +agent = Agent( + role="Technical Writer", + goal="Write clear API documentation", + backstory="Expert technical writer", + skills=["./skills/api-docs-style"], # 작성 가이드라인 및 템플릿 + # 도구 불필요 — 에이전트가 제공된 컨텍스트를 기반으로 작성 +) +``` + +### 패턴 2: 도구만 (액션, 특별한 전문성 불필요) + +에이전트가 행동을 취해야 하지만 도메인별 지침이 필요 없을 때 사용: + +```python +from crewai_tools import SerperDevTool, ScrapeWebsiteTool + +agent = Agent( + role="Web Researcher", + goal="Find information about a topic", + backstory="Skilled at finding information online", + tools=[SerperDevTool(), ScrapeWebsiteTool()], # 검색 및 스크래핑 가능 + # 스킬 불필요 — 일반 연구에는 특별한 가이드라인이 필요 없음 +) +``` + +### 패턴 3: 스킬 + 도구 (전문성 AND 액션) + +가장 일반적인 실제 패턴. 스킬은 작업에 *어떻게* 접근할지를 제공하고, 도구는 에이전트가 *무엇을* 할 수 있는지를 제공합니다: + +```python +from crewai_tools import SerperDevTool, FileReadTool, CodeInterpreterTool + +analyst = Agent( + role="Security Analyst", + goal="Audit infrastructure for vulnerabilities", + backstory="Expert in cloud security and compliance", + skills=["./skills/security-audit"], # 감사 방법론 및 체크리스트 + tools=[ + SerperDevTool(), # 알려진 취약점 조사 + FileReadTool(), # 설정 파일 읽기 + CodeInterpreterTool(), # 분석 스크립트 실행 + ], +) +``` + +### 패턴 4: 스킬 + MCP + +스킬은 도구와 마찬가지로 MCP 서버와 함께 작동합니다: + +```python +agent = Agent( + role="Data Analyst", + goal="Analyze customer data and generate reports", + backstory="Expert data analyst with strong statistical background", + skills=["./skills/data-analysis"], # 분석 방법론 + mcps=["https://data-warehouse.example.com/sse"], # 원격 데이터 접근 +) +``` + +### 패턴 5: 스킬 + 앱 + +스킬은 에이전트가 플랫폼 통합을 사용하는 방법을 안내할 수 있습니다: + +```python +agent = Agent( + role="Customer Support Agent", + goal="Respond to customer inquiries professionally", + backstory="Experienced support representative", + skills=["./skills/support-playbook"], # 응답 템플릿 및 에스컬레이션 규칙 + apps=["gmail", "zendesk"], # 이메일 전송 및 티켓 업데이트 가능 +) +``` + +--- + +## 스킬 생성, 게시 및 설치 + +스킬은 CLI로 관리되는 전체 라이프사이클을 갖습니다: **`crewai skill create`로 생성하고, `crewai skill publish`로 게시하세요** — 디렉터리를 직접 만드는 방식도 로컬 실험에는 사용할 수 있지만, CLI가 의도된 워크플로우이며 스킬 레이아웃과 프론트매터를 유효하게 유지해 줍니다. + +### 생성 + +```shell Terminal +crewai skill create my-skill +``` + +디렉터리를 스캐폴딩하고 (크루 프로젝트 내부에서는 `./skills/`에 생성) 템플릿 `SKILL.md`와 함께 빈 `scripts/`, `references/`, `assets/` 디렉터리를 만듭니다. `SKILL.md`를 편집하여 지침을 정의하세요. + +### 게시 + +스킬 디렉터리 내부(`SKILL.md`가 있는 곳)에서 실행하세요: + +```shell Terminal +cd skills/my-skill +crewai skill publish +``` + +게시 시 `SKILL.md` 프론트매터에서 `name`, `description`, `metadata.version`을 읽어 스킬을 CrewAI 레지스트리로 푸시합니다. **게시된 스킬은 항상 조직 범위로 제한됩니다** — 도구와 마찬가지로 게시한 조직의 멤버만 스킬을 보고 설치할 수 있으며, 공개 가시성은 없습니다. 유용한 플래그: + +| 플래그 | 효과 | +| :--- | :--- | +| `--org ` | 특정 조직으로 게시합니다 (설정을 재정의). | +| `--force` | git 상태 검증을 건너뜁니다 (커밋되지 않은 변경 사항 등). | + +### 설치 + +게시된 스킬을 `@org/name` 참조로 설치합니다: + +```shell Terminal +crewai skill install @acme/code-review +``` + +크루 프로젝트 내부에서는 스킬이 `./skills/{name}/`에 설치되고, 프로젝트 외부에서는 공유 캐시인 `~/.crewai/skills/{org}/{name}/`에 저장됩니다. + +에이전트는 레지스트리 스킬을 직접 참조할 수도 있습니다 — 런타임에 로컬 캐시(또는 프로젝트 `skills/` 디렉터리)에서 해석됩니다: + +```python +agent = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["@acme/code-review"], # registry ref, resolved locally +) +``` + +### 목록 조회 + +```shell Terminal +crewai skill list +``` + +프로젝트 `./skills/` 디렉터리와 전역 캐시 양쪽에 설치된 스킬을 버전 및 경로와 함께 보여줍니다. + +--- + +## 크루 레벨 스킬 + +스킬을 크루에 설정하여 **모든 에이전트**에 적용할 수 있습니다: + +```python +from crewai import Crew + +crew = Crew( + agents=[researcher, writer, reviewer], + tasks=[research_task, write_task, review_task], + skills=["./skills"], # 모든 에이전트가 이 스킬을 받음 +) +``` + +에이전트 레벨 스킬이 우선합니다 — 동일한 스킬이 양쪽 레벨에서 발견되면 에이전트의 버전이 사용됩니다. + +--- + +## SKILL.md 형식 + +```markdown +--- +name: my-skill +description: 이 스킬이 무엇을 하고 언제 사용하는지에 대한 간단한 설명. +license: Apache-2.0 # 선택 +compatibility: crewai>=0.1.0 # 선택 +metadata: # 선택 + author: your-name + version: "1.0" +allowed-tools: web-search file-read # 선택, 실험적 +--- + +에이전트를 위한 지침이 여기에 들어갑니다. 이 마크다운 본문은 +스킬이 활성화되면 에이전트의 프롬프트에 주입됩니다. +``` + +### 프론트매터 필드 + +| 필드 | 필수 | 설명 | +| :-------------- | :----- | :----------------------------------------------------------------------- | +| `name` | 예 | 1–64자. 소문자 영숫자와 하이픈. 디렉터리 이름과 일치 필수. | +| `description` | 예 | 1–1024자. 스킬이 무엇을 하고 언제 사용하는지 설명. | +| `license` | 아니오 | 라이선스 이름 또는 번들된 라이선스 파일 참조. | +| `compatibility` | 아니오 | 최대 500자. 환경 요구 사항 (제품, 패키지, 네트워크). | +| `metadata` | 아니오 | 임의의 문자열 키-값 매핑. | +| `allowed-tools` | 아니오 | 공백으로 구분된 사전 승인 도구 목록. 실험적. | + +--- + +## 디렉터리 구조 + +``` +my-skill/ +├── SKILL.md # 필수 — 프론트매터 + 지침 +├── scripts/ # 선택 — 실행 가능한 스크립트 +├── references/ # 선택 — 참조 문서 +└── assets/ # 선택 — 정적 파일 (설정, 데이터) +``` + +디렉터리 이름은 `SKILL.md`의 `name` 필드와 일치해야 합니다. `scripts/`, `references/`, `assets/` 디렉터리는 파일을 직접 참조해야 하는 에이전트를 위해 스킬의 `path`에서 사용할 수 있습니다. + +--- + +## 사전 로드된 스킬 + +더 세밀한 제어를 위해 프로그래밍 방식으로 스킬을 검색하고 활성화할 수 있습니다: + +```python +from pathlib import Path +from crewai.skills import discover_skills, activate_skill + +# 디렉터리의 모든 스킬 검색 +skills = discover_skills(Path("./skills")) + +# 활성화 (전체 SKILL.md 본문 로드) +activated = [activate_skill(s) for s in skills] + +# 에이전트에 전달 +agent = Agent( + role="Researcher", + goal="Find relevant information", + backstory="An expert researcher.", + skills=activated, +) +``` + +--- + +## 스킬 로드 방식 + +스킬은 **점진적 공개**를 사용합니다 — 각 단계에서 필요한 것만 로드합니다: + +| 단계 | 로드되는 내용 | 시점 | +| :------- | :------------------------------------ | :------------------ | +| 검색 | 이름, 설명, 프론트매터 필드 | `discover_skills()` | +| 활성화 | 전체 SKILL.md 본문 텍스트 | `activate_skill()` | + +일반적인 에이전트 실행 중(`skills=["./skills"]`로 디렉터리 경로 전달 시) 스킬은 자동으로 검색되고 활성화됩니다. 점진적 로딩은 프로그래밍 API를 사용할 때만 관련됩니다. + +--- + +## 스킬 vs 지식 + +스킬과 지식 모두 에이전트의 프롬프트를 수정하지만, 서로 다른 목적을 가지고 있습니다: + +| 측면 | 스킬 | 지식 | +| :--- | :--- | :--- | +| **제공하는 것** | 지침, 절차, 가이드라인 | 사실, 데이터, 정보 | +| **저장 방식** | 마크다운 파일 (SKILL.md) | 벡터 스토어에 임베딩 (ChromaDB) | +| **검색 방식** | 전체 본문이 프롬프트에 주입 | 시맨틱 검색으로 관련 청크 찾기 | +| **적합한 용도** | 방법론, 체크리스트, 스타일 가이드 | 회사 문서, 제품 정보, 참조 데이터 | +| **설정 방법** | `skills=["./skills"]` | `knowledge_sources=[source]` | + +**경험 법칙:** 에이전트가 *프로세스*를 따라야 하면 스킬을 사용하세요. 에이전트가 *데이터*를 참조해야 하면 지식을 사용하세요. + +--- + +## 자주 묻는 질문 + + + + 사용 사례에 따라 다릅니다. 스킬과 도구는 **독립적**입니다 — 둘 중 하나, 둘 다, 또는 아무것도 사용하지 않을 수 있습니다. + + - **스킬만**: 에이전트가 전문성은 필요하지만 외부 액션이 필요 없을 때 (예: 스타일 가이드라인으로 작성) + - **도구만**: 에이전트가 액션은 필요하지만 특별한 방법론이 필요 없을 때 (예: 간단한 웹 검색) + - **둘 다**: 에이전트가 전문성 AND 액션이 필요할 때 (예: 특정 체크리스트로 보안 감사 AND 코드 스캔 기능) + + + + **아니요.** SKILL.md의 `allowed-tools` 필드는 실험적 메타데이터일 뿐 — 도구를 프로비저닝하거나 주입하지 않습니다. 항상 `tools=[]`, `mcps=[]` 또는 `apps=[]`를 통해 별도로 도구를 설정해야 합니다. + + + + 에이전트 레벨 스킬이 우선합니다. 스킬은 이름으로 중복 제거됩니다 — 에이전트의 스킬이 먼저 처리되므로, 같은 스킬 이름이 양쪽 레벨에 나타나면 에이전트의 버전이 사용됩니다. + + + + 50,000자에서 소프트 경고가 있지만 하드 리밋은 없습니다. 최상의 결과를 위해 스킬을 집중적이고 간결하게 유지하세요 — 너무 큰 프롬프트 주입은 에이전트의 주의를 분산시킬 수 있습니다. + + diff --git a/docs/v1.15.13/ko/concepts/tasks.mdx b/docs/v1.15.13/ko/concepts/tasks.mdx new file mode 100644 index 0000000000..e0ce3f8f13 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/tasks.mdx @@ -0,0 +1,938 @@ +--- +title: 작업 +description: CrewAI 프레임워크 내에서 작업을 관리하고 생성하는 방법에 대한 자세한 안내서입니다. +icon: list-check +mode: "wide" +--- + +## 개요 + +CrewAI 프레임워크에서 `Task`는 `Agent`가 완료하는 구체적인 과제입니다. + +Task는 실행을 위한 모든 세부 정보를 제공합니다. 여기에는 설명, 책임 Agent, 필요한 도구 등이 포함되어 다양한 작업 복잡성을 지원합니다. + +CrewAI 내의 Task는 협업이 가능하며, 여러 Agent가 함께 작업해야 할 수도 있습니다. 이는 Task 속성을 통해 관리되며, Crew의 프로세스를 통해 조율되어 팀워크와 효율성을 향상시킵니다. + + +CrewAI 엔터프라이즈에는 복잡한 Task 생성과 연결을 단순화하는 Crew Studio의 비주얼 Task 빌더가 포함되어 있습니다. Task 흐름을 시각적으로 설계하고, 코드를 작성하지 않고도 실시간으로 테스트해 볼 수 있습니다. + +![Task Builder Screenshot](/images/enterprise/crew-studio-interface.png) + +비주얼 Task 빌더의 주요 기능: +- 드래그 앤 드롭 방식의 Task 생성 +- 시각적 Task 종속성과 흐름 관리 +- 실시간 테스트 및 검증 +- 손쉬운 공유 및 협업 + + +### 작업 실행 흐름 + +작업은 두 가지 방법으로 실행될 수 있습니다: +- **순차적**: 작업이 정의된 순서대로 실행됩니다 +- **계층적**: 작업이 역할과 전문성에 따라 에이전트에게 할당됩니다 + +실행 흐름은 crew를 생성할 때 정의됩니다: +```python Code +crew = Crew( + agents=[agent1, agent2], + tasks=[task1, task2], + process=Process.sequential # or Process.hierarchical +) +``` + +## 태스크 속성 + +| 속성 | 매개변수 | 타입 | 설명 | +| :------------------------------- | :-------------------- | :------------------------------- | :------------------------------------------------------------------------------------------------------------ | +| **설명** | `description` | `str` | 태스크가 다루는 내용을 명확하고 간결하게 설명합니다. | +| **예상 출력** | `expected_output` | `str` | 태스크가 완료된 모습에 대한 구체적인 설명입니다. | +| **이름** _(선택 사항)_ | `name` | `Optional[str]` | 태스크의 이름 식별자입니다. | +| **에이전트** _(선택 사항)_ | `agent` | `Optional[BaseAgent]` | 태스크 실행을 담당하는 에이전트입니다. | +| **도구** _(선택 사항)_ | `tools` | `List[BaseTool]` | 이 태스크를 위해 에이전트가 사용할 수 있는 도구/리소스 목록입니다. | +| **컨텍스트** _(선택 사항)_ | `context` | `Optional[List["Task"]]` | 이 태스크의 컨텍스트로 사용될 다른 태스크의 출력입니다. | +| **비동기 실행** _(선택 사항)_ | `async_execution` | `Optional[bool]` | 태스크를 비동기적으로 실행할지 여부입니다. 기본값은 False입니다. | +| **사용자 입력** _(선택 사항)_ | `human_input` | `Optional[bool]` | 태스크의 최종 답안을 에이전트가 제출한 뒤 사람이 검토할지 여부입니다. 기본값은 False입니다. | +| **마크다운** _(선택 사항)_ | `markdown` | `Optional[bool]` | 태스크가 에이전트에게 최종 답안을 마크다운으로 포매팅해서 반환하도록 지시할지 여부입니다. 기본값은 False입니다. | +| **설정** _(선택 사항)_ | `config` | `Optional[Dict[str, Any]]` | 태스크별 설정 파라미터입니다. | +| **출력 파일** _(선택 사항)_ | `output_file` | `Optional[str]` | 태스크 결과를 저장할 파일 경로입니다. | +| **디렉터리 생성** _(선택 사항)_ | `create_directory` | `Optional[bool]` | output_file의 디렉터리가 존재하지 않을 경우 생성할지 여부입니다. 기본값은 True입니다. | +| **출력 JSON** _(선택 사항)_ | `output_json` | `Optional[Type[BaseModel]]` | JSON 출력을 구조화하기 위한 Pydantic 모델입니다. | +| **Pydantic 출력** _(선택 사항)_ | `output_pydantic` | `Optional[Type[BaseModel]]` | 태스크 출력용 Pydantic 모델입니다. | +| **콜백** _(선택 사항)_ | `callback` | `Optional[Any]` | 태스크 완료 후 실행할 함수/객체입니다. | +| **가드레일** _(선택 사항)_ | `guardrail` | `Optional[Callable]` | 다음 태스크로 진행하기 전에 태스크 출력을 검증하는 함수입니다. | +| **가드레일 최대 재시도** _(선택 사항)_ | `guardrail_max_retries` | `Optional[int]` | 가드레일 검증 실패 시 최대 재시도 횟수입니다. 기본값은 3입니다. | + +## 작업 생성하기 + +CrewAI에서 작업을 생성하는 일반적인 방법은 **JSONC 프로젝트 구성(새 crew 권장)** 또는 **코드에서 직접 정의**입니다. + +### JSONC 구성 (권장) + +`crewai create crew `으로 만든 새 프로젝트는 `crew.jsonc`에 태스크를 정의합니다. + +```jsonc crew.jsonc +{ + "name": "Research Crew", + "agents": ["researcher", "reporting_analyst"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research about {topic}.", + "expected_output": "A list of the most relevant information about {topic}.", + "agent": "researcher" + }, + { + "name": "reporting_task", + "description": "Review the research and expand it into a detailed report.", + "expected_output": "A polished markdown report.", + "agent": "reporting_analyst", + "context": ["research_task"], + "markdown": true, + "output_file": "report.md" + } + ], + "inputs": { + "topic": "AI Agents" + } +} +``` + +각 태스크에는 `description`과 `expected_output`이 필요합니다. `agent` 값은 `agents`에 나열된 에이전트 이름과 일치해야 합니다. `context`는 이전 태스크 이름만 참조할 수 있으며, 이후 태스크 참조는 거부됩니다. + +### 클래식 YAML 구성 + +`crewai create crew --classic`으로 만든 클래식 프로젝트는 `config/tasks.yaml`과 `crew.py`의 `@CrewBase` 클래스를 사용합니다. + +YAML 구성은 기존 Python/YAML 프로젝트와 `@CrewBase` 클래스에서 태스크를 정의하려는 팀을 위해 계속 지원됩니다. + +클래식 프로젝트를 만든 후, `src//config/tasks.yaml` 파일로 이동하여 템플릿을 작업 요구 사항에 맞게 수정하세요. + + +YAML 파일 내 변수(예: `{topic}`)는 크루를 실행할 때 입력값에서 가져온 값으로 대체됩니다: +```python Code +crew.kickoff(inputs={'topic': 'AI Agents'}) +``` + + +아래는 YAML을 사용하여 작업을 구성하는 방법의 예시입니다: + +```yaml tasks.yaml +research_task: + description: > + Conduct a thorough research about {topic} + Make sure you find any interesting and relevant information given + the current year is 2025. + expected_output: > + A list with 10 bullet points of the most relevant information about {topic} + agent: researcher + +reporting_task: + description: > + Review the context you got and expand each topic into a full section for a report. + Make sure the report is detailed and contains any and all relevant information. + expected_output: > + A fully fledge reports with the mains topics, each with a full section of information. + Formatted as markdown without '```' + agent: reporting_analyst + markdown: true + output_file: report.md +``` + +이 YAML 구성을 코드에서 사용하려면 `CrewBase`를 상속받는 크루 클래스를 생성하세요: + +```python crew.py +# src//crew.py + +from crewai import Agent, Crew, Process, Task +from crewai.project import CrewBase, agent, crew, task +from crewai_tools import SerperDevTool + +@CrewBase +class LatestAiDevelopmentCrew(): + """LatestAiDevelopment crew""" + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], # type: ignore[index] + verbose=True, + tools=[SerperDevTool()] + ) + + @agent + def reporting_analyst(self) -> Agent: + return Agent( + config=self.agents_config['reporting_analyst'], # type: ignore[index] + verbose=True + ) + + @task + def research_task(self) -> Task: + return Task( + config=self.tasks_config['research_task'] # type: ignore[index] + ) + + @task + def reporting_task(self) -> Task: + return Task( + config=self.tasks_config['reporting_task'] # type: ignore[index] + ) + + @crew + def crew(self) -> Crew: + return Crew( + agents=[ + self.researcher(), + self.reporting_analyst() + ], + tasks=[ + self.research_task(), + self.reporting_task() + ], + process=Process.sequential + ) +``` + + +YAML 파일(`agents.yaml` 및 `tasks.yaml`)에서 사용하는 이름은 Python 코드의 메서드 이름과 일치해야 합니다. + + +### 코드에서 직접 태스크 정의 (대안) + +또는 YAML 구성 없이 코드에서 직접 태스크를 정의할 수 있습니다: + +```python task.py +from crewai import Task + +research_task = Task( + description=""" + Conduct a thorough research about AI Agents. + Make sure you find any interesting and relevant information given + the current year is 2025. + """, + expected_output=""" + A list with 10 bullet points of the most relevant information about AI Agents + """, + agent=researcher +) + +reporting_task = Task( + description=""" + Review the context you got and expand each topic into a full section for a report. + Make sure the report is detailed and contains any and all relevant information. + """, + expected_output=""" + A fully fledge reports with the mains topics, each with a full section of information. + """, + agent=reporting_analyst, + markdown=True, # Enable markdown formatting for the final output + output_file="report.md" +) +``` + + + `agent`를 직접 지정하여 할당하거나, 역할·가용성 등에 따라 `hierarchical` CrewAI 프로세스가 자동으로 결정하도록 둘 수 있습니다. + + +## 작업 결과 + +작업 결과를 이해하는 것은 효과적인 AI 워크플로우를 구축하는 데 매우 중요합니다. CrewAI는 여러 출력 형식을 지원하는 `TaskOutput` 클래스를 통해 작업 결과를 구조적으로 처리할 수 있는 방식을 제공합니다. 이 클래스는 작업 간에 출력값을 쉽게 전달할 수 있도록 지원합니다. + +CrewAI 프레임워크에서 작업의 출력은 `TaskOutput` 클래스에 캡슐화되어 있습니다. 이 클래스는 작업의 결과를 구조적으로 접근할 수 있도록 해주며, raw 출력, JSON, Pydantic 모델 등 다양한 형식을 지원합니다. + +기본적으로 `TaskOutput`에는 `raw` 출력만 포함됩니다. 원래의 `Task` 객체가 각각 `output_pydantic` 또는 `output_json`으로 구성된 경우에만 `TaskOutput`에 `pydantic` 또는 `json_dict` 출력이 포함됩니다. + +### 작업 출력 속성 + +| 속성 | 파라미터 | 타입 | 설명 | +| :---------------- | :----------------- | :------------------------- | :---------------------------------------------------------------------------------------------------- | +| **설명** | `description` | `str` | 작업에 대한 설명입니다. | +| **요약** | `summary` | `Optional[str]` | 설명의 처음 10단어에서 자동 생성된 작업의 요약입니다. | +| **Raw** | `raw` | `str` | 작업의 원시 출력값입니다. 출력의 기본 형식입니다. | +| **Pydantic** | `pydantic` | `Optional[BaseModel]` | 작업의 구조화된 출력을 나타내는 Pydantic 모델 객체입니다. | +| **JSON Dict** | `json_dict` | `Optional[Dict[str, Any]]` | 작업의 JSON 출력을 나타내는 딕셔너리입니다. | +| **Agent** | `agent` | `str` | 작업을 실행한 agent입니다. | +| **Output Format** | `output_format` | `OutputFormat` | 작업 출력의 형식입니다. RAW, JSON, Pydantic 옵션이 있으며, 기본값은 RAW입니다. | + +### 태스크 메서드 및 프로퍼티 + +| Method/Property | 설명 | +| :-------------- | :------------------------------------------------------------------------------------------------- | +| **json** | 출력 포맷이 JSON일 경우 태스크 출력의 JSON 문자열 표현을 반환합니다. | +| **to_dict** | JSON 및 Pydantic 출력을 딕셔너리로 변환합니다. | +| **str** | 태스크 출력의 문자열 표현을 반환하며, Pydantic을 우선으로 하고 그 다음은 JSON, 그 다음은 raw를 사용합니다. | + +### 작업 출력 액세스 + +작업이 실행된 후에는 `Task` 객체의 `output` 속성을 통해 그 출력을 액세스할 수 있습니다. `TaskOutput` 클래스는 이 출력을 다양한 방식으로 상호작용하고 표시할 수 있는 기능을 제공합니다. + +#### 예시 + +```python Code +# Example task +task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +# Execute the crew +crew = Crew( + agents=[research_agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() + +# Accessing the task output +task_output = task.output + +print(f"Task Description: {task_output.description}") +print(f"Task Summary: {task_output.summary}") +print(f"Raw Output: {task_output.raw}") +if task_output.json_dict: + print(f"JSON Output: {json.dumps(task_output.json_dict, indent=2)}") +if task_output.pydantic: + print(f"Pydantic Output: {task_output.pydantic}") +``` + +## 마크다운 출력 포매팅 + +`markdown` 매개변수는 작업 출력에 대해 자동 마크다운 포매팅을 활성화합니다. 이 값을 `True`로 설정하면, 작업은 에이전트에게 최종 답변을 올바른 마크다운 문법으로 포매팅하도록 지시합니다. + +### 마크다운(Markdown) 포매팅 사용하기 + +```python Code +# Example task with markdown formatting enabled +formatted_task = Task( + description="Create a comprehensive report on AI trends", + expected_output="A well-structured report with headers, sections, and bullet points", + agent=reporter_agent, + markdown=True # Enable automatic markdown formatting +) +``` + +`markdown=True`일 때, 에이전트는 다음과 같이 출력을 포매팅하라는 추가 지시를 받게 됩니다: +- 헤더에는 `#` 사용 +- 볼드체는 `**텍스트**` 사용 +- 이탤릭체는 `*텍스트*` 사용 +- 불릿 포인트에는 `-` 또는 `*` 사용 +- 인라인 코드는 `` `코드` `` 사용 +- 코드 블록은 ``` ```언어 ``` 사용 + +### 마크다운을 활용한 YAML 구성 + +```yaml tasks.yaml +analysis_task: + description: > + Analyze the market data and create a detailed report + expected_output: > + A comprehensive analysis with charts and key findings + agent: analyst + markdown: true # Enable markdown formatting + output_file: analysis.md +``` + +### 마크다운 출력의 이점 + +- **일관된 포맷팅**: 모든 출력이 올바른 마크다운 규칙을 따르도록 보장합니다 +- **향상된 가독성**: 헤더, 목록, 강조 등으로 구조화된 콘텐츠 +- **문서화에 적합**: 출력을 문서 시스템에서 바로 사용할 수 있습니다 +- **크로스 플랫폼 호환성**: 마크다운은 보편적으로 지원됩니다 + + +마크다운 포맷팅 지침은 `markdown=True`일 때 작업 프롬프트에 자동으로 추가되므로, 작업 설명에 포맷팅 요구사항을 따로 명시할 필요가 없습니다. + + +## 작업 종속성 및 컨텍스트 + +작업은 `context` 속성을 사용하여 다른 작업의 출력에 의존할 수 있습니다. 예를 들어: + +```python Code +research_task = Task( + description="Research the latest developments in AI", + expected_output="A list of recent AI developments", + agent=researcher +) + +analysis_task = Task( + description="Analyze the research findings and identify key trends", + expected_output="Analysis report of AI trends", + agent=analyst, + context=[research_task] # This task will wait for research_task to complete +) +``` + +## 작업 가드레일 + +작업 가드레일은 작업 출력물을 다음 작업에 전달하기 전에 유효성을 검사하고 변환할 수 있는 방식을 제공합니다. 이 기능은 데이터 품질을 보장하고 에이전트의 출력이 특정 기준을 충족하지 않을 때 피드백을 제공하는 데 도움이 됩니다. + +가드레일은 사용자 지정 유효성 검사 로직을 포함하는 Python 함수로 구현되며, 유효성 검사 프로세스를 완전히 제어할 수 있어 신뢰할 수 있고 결정적인 결과를 보장합니다. + +### 함수 기반 가드레일 + +함수 기반 가드레일을 태스크에 추가하려면 `guardrail` 파라미터를 통해 검증 함수를 제공하세요: + +```python Code +from typing import Tuple, Union, Dict, Any +from crewai import TaskOutput + +def validate_blog_content(result: TaskOutput) -> Tuple[bool, Any]: + """Validate blog content meets requirements.""" + try: + # Check word count + word_count = len(result.split()) + if word_count > 200: + return (False, "Blog content exceeds 200 words") + + # Additional validation logic here + return (True, result.strip()) + except Exception as e: + return (False, "Unexpected error during validation") + +blog_task = Task( + description="Write a blog post about AI", + expected_output="A blog post under 200 words", + agent=blog_agent, + guardrail=validate_blog_content # Add the guardrail function +) +``` + +### Guardrail 함수 요구사항 + +1. **함수 시그니처**: + - 정확히 하나의 매개변수(태스크 출력)를 받아야 함 + - `(bool, Any)` 형태의 튜플을 반환해야 함 + - 타입 힌트는 권장하지만 필수는 아님 + +2. **반환 값**: + - 성공 시: `(bool, Any)` 형태의 튜플을 반환. 예: `(True, validated_result)` + - 실패 시: `(bool, str)` 형태의 튜플을 반환. 예: `(False, "Error message explain the failure")` + +### 오류 처리 모범 사례 + +1. **구조화된 오류 응답**: +```python Code +from crewai import TaskOutput, LLMGuardrail + +def validate_with_context(result: TaskOutput) -> Tuple[bool, Any]: + try: + # Main validation logic + validated_data = perform_validation(result) + return (True, validated_data) + except ValidationError as e: + return (False, f"VALIDATION_ERROR: {str(e)}") + except Exception as e: + return (False, str(e)) +``` + +2. **오류 범주**: + - 구체적인 오류 코드 사용 + - 관련 컨텍스트 포함 + - 실행 가능한 피드백 제공 + +3. **검증 체인**: +```python Code +from typing import Any, Dict, List, Tuple, Union +from crewai import TaskOutput + +def complex_validation(result: TaskOutput) -> Tuple[bool, Any]: + """Chain multiple validation steps.""" + # Step 1: Basic validation + if not result: + return (False, "Empty result") + + # Step 2: Content validation + try: + validated = validate_content(result) + if not validated: + return (False, "Invalid content") + + # Step 3: Format validation + formatted = format_output(validated) + return (True, formatted) + except Exception as e: + return (False, str(e)) +``` + +### 가드레일 결과 처리 + +가드레일이 `(False, error)`를 반환할 때: +1. 에러가 에이전트에게 다시 전달됩니다 +2. 에이전트가 문제를 수정하려고 시도합니다 +3. 다음 중 하나가 될 때까지 이 과정이 반복됩니다: + - 가드레일이 `(True, result)`를 반환함 + - 최대 재시도 횟수에 도달함 + +재시도 처리가 포함된 예시: +```python Code +from typing import Optional, Tuple, Union +from crewai import TaskOutput, Task + +def validate_json_output(result: TaskOutput) -> Tuple[bool, Any]: + """Validate and parse JSON output.""" + try: + # Try to parse as JSON + data = json.loads(result) + return (True, data) + except json.JSONDecodeError as e: + return (False, "Invalid JSON format") + +task = Task( + description="Generate a JSON report", + expected_output="A valid JSON object", + agent=analyst, + guardrail=validate_json_output, + guardrail_max_retries=3 # 재시도 횟수 제한 +) +``` + +## 작업에서 구조화된 일관된 출력 얻기 + + +또한 crew의 마지막 작업의 출력이 실제 crew 자체의 최종 출력이 된다는 점도 중요합니다. + + +### `output_pydantic` 사용하기 +`output_pydantic` 속성을 사용하면 작업 출력이 준수해야 할 Pydantic 모델을 정의할 수 있습니다. 이를 통해 출력이 구조화될 뿐만 아니라 Pydantic 모델에 따라 유효성 검증도 보장할 수 있습니다. + +다음은 output_pydantic을 사용하는 방법을 보여주는 예제입니다. + +```python Code +import json + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + + +class Blog(BaseModel): + title: str + content: str + + +blog_agent = Agent( + role="Blog Content Generator Agent", + goal="Generate a blog title and content", + backstory="""You are an expert content creator, skilled in crafting engaging and informative blog posts.""", + verbose=False, + allow_delegation=False, + llm="gpt-4o", +) + +task1 = Task( + description="""Create a blog title and content on a given topic. Make sure the content is under 200 words.""", + expected_output="A compelling blog title and well-written content.", + agent=blog_agent, + output_pydantic=Blog, +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[blog_agent], + tasks=[task1], + verbose=True, + process=Process.sequential, +) + +result = crew.kickoff() + +# Option 1: Accessing Properties Using Dictionary-Style Indexing +print("Accessing Properties - Option 1") +title = result["title"] +content = result["content"] +print("Title:", title) +print("Content:", content) + +# Option 2: Accessing Properties Directly from the Pydantic Model +print("Accessing Properties - Option 2") +title = result.pydantic.title +content = result.pydantic.content +print("Title:", title) +print("Content:", content) + +# Option 3: Accessing Properties Using the to_dict() Method +print("Accessing Properties - Option 3") +output_dict = result.to_dict() +title = output_dict["title"] +content = output_dict["content"] +print("Title:", title) +print("Content:", content) + +# Option 4: Printing the Entire Blog Object +print("Accessing Properties - Option 5") +print("Blog:", result) + +``` +이 예제에서: +* title과 content 필드를 가진 Pydantic 모델 Blog가 정의되어 있습니다. +* 작업 task1은 output_pydantic 속성을 사용하여 출력이 Blog 모델을 준수해야 함을 명시합니다. +* crew를 실행한 후, 위와 같이 다양한 방법으로 구조화된 출력을 확인할 수 있습니다. + +#### 출력 접근 방법 설명 +1. 딕셔너리 스타일 인덱싱: `result["field_name"]`을 사용하여 필드를 직접 접근할 수 있습니다. 이는 CrewOutput 클래스가 `__getitem__` 메서드를 구현하고 있기 때문에 가능합니다. +2. Pydantic 모델에서 직접 접근: `result.pydantic` 객체에서 속성에 직접 접근할 수 있습니다. +3. to_dict() 메서드 사용: 출력을 딕셔너리로 변환한 후 필드에 접근합니다. +4. 전체 객체 출력: 단순히 result 객체를 출력하여 구조화된 출력을 확인할 수 있습니다. + +### `output_json` 사용하기 +`output_json` 속성을 사용하면 예상되는 출력을 JSON 형식으로 정의할 수 있습니다. 이를 통해 태스크의 출력이 쉽게 파싱되고, 애플리케이션에서 사용할 수 있는 유효한 JSON 구조임을 보장합니다. + +다음은 `output_json` 사용 방법을 보여주는 예시입니다: + +```python Code +import json + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + + +# Define the Pydantic model for the blog +class Blog(BaseModel): + title: str + content: str + + +# Define the agent +blog_agent = Agent( + role="Blog Content Generator Agent", + goal="Generate a blog title and content", + backstory="""You are an expert content creator, skilled in crafting engaging and informative blog posts.""", + verbose=False, + allow_delegation=False, + llm="gpt-4o", +) + +# Define the task with output_json set to the Blog model +task1 = Task( + description="""Create a blog title and content on a given topic. Make sure the content is under 200 words.""", + expected_output="A JSON object with 'title' and 'content' fields.", + agent=blog_agent, + output_json=Blog, +) + +# Instantiate the crew with a sequential process +crew = Crew( + agents=[blog_agent], + tasks=[task1], + verbose=True, + process=Process.sequential, +) + +# Kickoff the crew to execute the task +result = crew.kickoff() + +# Option 1: Accessing Properties Using Dictionary-Style Indexing +print("Accessing Properties - Option 1") +title = result["title"] +content = result["content"] +print("Title:", title) +print("Content:", content) + +# Option 2: Printing the Entire Blog Object +print("Accessing Properties - Option 2") +print("Blog:", result) +``` + +이 예시에서: +* Pydantic 모델인 Blog가 title과 content 필드로 정의되어 있으며, 이는 JSON 출력의 구조를 명시하는 데 사용됩니다. +* 태스크 task1은 output_json 속성을 사용하여 Blog 모델에 부합하는 JSON 출력을 기대함을 나타냅니다. +* crew를 실행한 후, 두 가지 방식으로 구조화된 JSON 출력을 접근할 수 있습니다. + +#### 출력 접근 방법 설명 + +1. 딕셔너리 스타일 인덱싱을 사용하여 속성 접근하기: result["field_name"]과 같이 필드를 직접 접근할 수 있습니다. 이는 CrewOutput 클래스가 __getitem__ 메서드를 구현하고 있어 출력을 딕셔너리처럼 사용할 수 있기 때문입니다. 이 방법에서는 result에서 title과 content를 가져옵니다. +2. 전체 블로그 객체 출력하기: result를 출력하면 CrewOutput 객체의 문자열 표현을 얻을 수 있습니다. __str__ 메서드가 JSON 출력을 반환하도록 구현되어 있기 때문에, 전체 출력을 Blog 객체를 나타내는 형식이 잘 갖추어진 문자열로 볼 수 있습니다. + +--- + +output_pydantic 또는 output_json을 사용하면, 작업의 출력이 일관되고 구조화된 형식으로 생성되므로 애플리케이션 내 또는 여러 작업 간에 데이터를 더 쉽게 처리하고 활용할 수 있습니다. + +## 도구와 작업 통합 + +향상된 작업 성능과 에이전트 상호작용을 위해 [CrewAI Toolkit](https://github.com/joaomdmoura/crewai-tools) 및 [LangChain Tools](https://python.langchain.com/docs/integrations/tools)의 도구를 활용하세요. + +## 도구와 함께 Task 생성하기 + +```python Code +import os +os.environ["OPENAI_API_KEY"] = "Your Key" +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key + +from crewai import Agent, Task, Crew +from crewai_tools import SerperDevTool + +research_agent = Agent( + role='Researcher', + goal='Find and summarize the latest AI news', + backstory="""You're a researcher at a large company. + You're responsible for analyzing data and providing insights + to the business.""", + verbose=True +) + +# to perform a semantic search for a specified query from a text's content across the internet +search_tool = SerperDevTool() + +task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +crew = Crew( + agents=[research_agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() +print(result) +``` + +이 예시는 특정 도구와 함께 사용되는 task가 맞춤형 task 실행을 위해 에이전트의 기본 도구 세트를 어떻게 재정의할 수 있는지 보여줍니다. + +## 다른 작업 참조하기 + +CrewAI에서는 한 작업의 출력이 자동으로 다음 작업으로 전달되지만, 특정 작업(여러 개 포함)의 출력을 다른 작업의 컨텍스트로 명확하게 지정할 수도 있습니다. + +이는 한 작업이 바로 뒤에 수행되지 않는 다른 작업의 출력에 의존해야 할 때 유용합니다. 이는 작업의 `context` 속성을 통해 수행됩니다: + +```python Code +# ... + +research_ai_task = Task( + description="Research the latest developments in AI", + expected_output="A list of recent AI developments", + async_execution=True, + agent=research_agent, + tools=[search_tool] +) + +research_ops_task = Task( + description="Research the latest developments in AI Ops", + expected_output="A list of recent AI Ops developments", + async_execution=True, + agent=research_agent, + tools=[search_tool] +) + +write_blog_task = Task( + description="Write a full blog post about the importance of AI and its latest news", + expected_output="Full blog post that is 4 paragraphs long", + agent=writer_agent, + context=[research_ai_task, research_ops_task] +) + +#... +``` + +## 비동기 실행 + +작업을 비동기로 실행되도록 정의할 수 있습니다. 이는 crew가 해당 작업이 완료될 때까지 기다리지 않고 다음 작업을 계속 진행한다는 것을 의미합니다. 시간이 오래 걸리는 작업이거나, 이후 작업 수행에 필수적이지 않은 작업에 유용합니다. + +이후 작업에서 비동기 작업의 출력이 완료될 때까지 기다리도록 하려면, `context` 속성을 사용할 수 있습니다. + +```python Code +#... + +list_ideas = Task( + description="List of 5 interesting ideas to explore for an article about AI.", + expected_output="Bullet point list of 5 ideas for an article.", + agent=researcher, + async_execution=True # Will be executed asynchronously +) + +list_important_history = Task( + description="Research the history of AI and give me the 5 most important events.", + expected_output="Bullet point list of 5 important events.", + agent=researcher, + async_execution=True # Will be executed asynchronously +) + +write_article = Task( + description="Write an article about AI, its history, and interesting ideas.", + expected_output="A 4 paragraph article about AI.", + agent=writer, + context=[list_ideas, list_important_history] # Will wait for the output of the two tasks to be completed +) + +#... +``` + +## 콜백 메커니즘 + +콜백 함수는 작업이 완료된 후 실행되며, 작업 결과에 따라 동작 또는 알림을 트리거할 수 있습니다. + +```python Code +# ... + +def callback_function(output: TaskOutput): + # Do something after the task is completed + # Example: Send an email to the manager + print(f""" + Task completed! + Task: {output.description} + Output: {output.raw} + """) + +research_task = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool], + callback=callback_function +) + +#... +``` + +## 특정 Task Output 접근하기 + +crew가 실행을 마치면, 해당 task 객체의 `output` 속성을 사용하여 특정 task의 output에 접근할 수 있습니다: + +```python Code +# ... +task1 = Task( + description='Find and summarize the latest AI news', + expected_output='A bullet list summary of the top 5 most important AI news', + agent=research_agent, + tools=[search_tool] +) + +#... + +crew = Crew( + agents=[research_agent], + tasks=[task1, task2, task3], + verbose=True +) + +result = crew.kickoff() + +# Returns a TaskOutput object with the description and results of the task +print(f""" + Task completed! + Task: {task1.output.description} + Output: {task1.output.raw} +""") +``` + +## 도구 재정의 메커니즘 + +작업에서 도구를 지정하면 에이전트의 기능을 동적으로 조정할 수 있어 CrewAI의 유연성이 강조됩니다. + +## 오류 처리 및 검증 메커니즘 + +작업을 생성하고 실행하는 동안, 작업 속성의 견고성과 신뢰성을 보장하기 위해 특정 검증 메커니즘이 마련되어 있습니다. 이는 다음에 국한되지 않습니다: + +- 작업마다 한 가지 출력 유형만 설정하여 명확한 출력 기대치를 유지함 +- 고유 식별자 시스템의 무결성을 유지하기 위해 `id` 속성의 수동 할당을 방지함 + +이러한 검증 절차는 crewAI 프레임워크 내에서 작업 실행의 일관성과 신뢰성을 유지하는 데 도움이 됩니다. + +## 파일 저장 시 디렉토리 생성 + +`create_directory` 매개변수는 CrewAI가 작업 결과를 파일로 저장할 때 디렉토리를 자동으로 생성할지 여부를 제어합니다. 이 기능은 출력물을 체계적으로 정리하고, 특히 복잡한 프로젝트 계층 구조에서 파일 경로가 올바르게 구조화되도록 보장하는 데 매우 유용합니다. + +### 기본 동작 + +기본적으로 `create_directory=True`로 설정되어 있으며, 이는 CrewAI가 출력 파일 경로에 누락된 디렉토리를 자동으로 생성함을 의미합니다: + +```python Code +# 기본 동작 - 디렉토리가 자동으로 생성됩니다 +report_task = Task( + description='Generate a comprehensive market analysis report', + expected_output='A detailed market analysis with charts and insights', + agent=analyst_agent, + output_file='reports/2025/market_analysis.md', # 'reports/2025/'가 없으면 생성됩니다 + markdown=True +) +``` + +### 디렉터리 생성 비활성화 + +자동 디렉터리 생성을 방지하고 디렉터리가 이미 존재함을 보장하려면 `create_directory=False`로 설정하세요: + +```python Code +# Strict mode - directory must already exist +strict_output_task = Task( + description='Save critical data that requires existing infrastructure', + expected_output='Data saved to pre-configured location', + agent=data_agent, + output_file='secure/vault/critical_data.json', + create_directory=False # Will raise RuntimeError if 'secure/vault/' doesn't exist +) +``` + +### YAML 구성 + +이 동작은 YAML 태스크 정의에서도 구성할 수 있습니다: + +```yaml tasks.yaml +analysis_task: + description: > + 분기별 재무 분석 생성 + expected_output: > + 분기별 인사이트가 포함된 종합 재무 보고서 + agent: financial_analyst + output_file: reports/quarterly/q4_2024_analysis.pdf + create_directory: true # 'reports/quarterly/' 디렉토리를 자동으로 생성 + +audit_task: + description: > + 컴플라이언스 감사 수행 및 기존 감사 디렉토리에 저장 + expected_output: > + 컴플라이언스 감사 보고서 + agent: auditor + output_file: audit/compliance_report.md + create_directory: false # 디렉토리가 이미 존재해야 함 +``` + +### 사용 사례 + +**자동 디렉토리 생성 (`create_directory=True`):** +- 개발 및 프로토타이핑 환경 +- 날짜 기반 폴더로 동적 보고서 생성 +- 디렉토리 구조가 달라질 수 있는 자동화된 워크플로우 +- 사용자별 폴더가 필요한 멀티 테넌트 애플리케이션 + +**수동 디렉토리 관리 (`create_directory=False`):** +- 엄격한 파일 시스템 제어가 필요한 운영 환경 +- 디렉토리가 사전 구성되어야 하는 보안 민감 애플리케이션 +- 특정 권한 요구 사항이 있는 시스템 +- 디렉토리 생성이 감사되는 규정 준수 환경 + +### 오류 처리 + +`create_directory=False`이고 디렉토리가 존재하지 않는 경우, CrewAI는 `RuntimeError`를 발생시킵니다: + +```python Code +try: + result = crew.kickoff() +except RuntimeError as e: + # Handle missing directory error + print(f"Directory creation failed: {e}") + # Create directory manually or use fallback location +``` + +아래 영상을 통해 CrewAI에서 구조화된 출력을 사용하는 방법을 확인하세요: + + + +## 결론 + +작업(task)은 CrewAI 에이전트의 행동을 이끄는 원동력입니다. +작업과 그 결과를 적절하게 정의함으로써, 에이전트가 독립적으로 또는 협업 단위로 효과적으로 작동할 수 있는 기반을 마련할 수 있습니다. +작업에 적합한 도구를 장착하고, 실행 과정을 이해하며, 견고한 검증 절차를 따르는 것은 CrewAI의 잠재력을 극대화하는 데 필수적입니다. +이를 통해 에이전트가 할당된 작업에 효과적으로 준비되고, 작업이 의도대로 수행될 수 있습니다. diff --git a/docs/v1.15.13/ko/concepts/testing.mdx b/docs/v1.15.13/ko/concepts/testing.mdx new file mode 100644 index 0000000000..671143d9a0 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/testing.mdx @@ -0,0 +1,49 @@ +--- +title: 테스트 +description: CrewAI Crew를 테스트하고 그 성능을 평가하는 방법을 알아보세요. +icon: vial +mode: "wide" +--- + +## 개요 + +테스트는 개발 프로세스에서 매우 중요한 부분이며, crew가 예상대로 동작하는지 확인하는 것이 필수적입니다. crewAI를 사용하면 내장된 테스트 기능을 통해 crew를 쉽게 테스트하고 성능을 평가할 수 있습니다. + +### 테스트 기능 사용하기 + +CLI 명령어 `crewai test`를 추가하여 crew 테스트를 쉽게 할 수 있습니다. 이 명령어는 지정한 반복 횟수만큼 crew를 실행하고, 자세한 성능 지표를 제공합니다. 매개변수로는 `n_iterations`와 `model`이 있으며, 이들은 선택 사항이고 각각 기본값은 2와 `gpt-4o-mini`입니다. 현재는 OpenAI만 지원됩니다. + +```bash +crewai test +``` + +더 많은 반복 횟수로 실행하거나 다른 모델을 사용하려면 다음과 같이 매개변수를 지정할 수 있습니다: + +```bash +crewai test --n_iterations 5 --model gpt-4o +``` + +또는 축약형을 사용할 수 있습니다: + +```bash +crewai test -n 5 -m gpt-4o +``` + +`crewai test` 명령어를 실행하면 crew가 지정한 횟수만큼 실행되고, 수행이 끝나면 성능 지표가 표시됩니다. + +실행 마지막에 표시되는 점수 표는 다음과 같은 지표로 crew의 성능을 보여줍니다: + +
**작업 점수 (1-10 높을수록 좋음)**
+ +| Tasks/Crew/Agents | Run 1 | Run 2 | Avg. Total | Agents | Additional Info | +|:------------------|:-----:|:-----:|:----------:|:------------------------------:|:---------------------------------| +| Task 1 | 9.0 | 9.5 | **9.2** | Professional Insights | | +| | | | | Researcher | | +| Task 2 | 9.0 | 10.0 | **9.5** | Company Profile Investigator | | +| Task 3 | 9.0 | 9.0 | **9.0** | Automation Insights | | +| | | | | Specialist | | +| Task 4 | 9.0 | 9.0 | **9.0** | Final Report Compiler | Automation Insights Specialist | +| Crew | 9.00 | 9.38 | **9.2** | | | +| Execution Time (s) | 126 | 145 | **135** | | | + +위 예시는 두 번 실행한 crew의 테스트 결과를 보여주며, 각 작업과 crew 전체의 평균 총점이 포함되어 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/concepts/tools.mdx b/docs/v1.15.13/ko/concepts/tools.mdx new file mode 100644 index 0000000000..cd0e961736 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/tools.mdx @@ -0,0 +1,287 @@ +--- +title: 도구 +description: CrewAI 프레임워크 내에서 에이전트 협업과 작업 실행을 위해 도구를 이해하고 활용하기. +icon: screwdriver-wrench +mode: "wide" +--- + +## 개요 + +CrewAI 도구는 에이전트에게 웹 검색, 데이터 분석부터 동료 간 협업 및 작업 위임에 이르기까지 다양한 기능을 제공합니다. +이 문서에서는 CrewAI 프레임워크 내에서 이러한 도구를 생성, 통합 및 활용하는 방법과, 협업 도구에 초점을 맞춘 새로운 기능에 대해 설명합니다. + + + 도구는 에이전트에게 행동을 취할 수 있는 **호출 가능한 함수**를 제공합니다. [MCP](/ko/mcp/overview) (원격 도구 서버), [앱](/ko/concepts/agent-capabilities) (플랫폼 통합), [스킬](/ko/concepts/skills) (도메인 전문성), [지식](/ko/concepts/knowledge) (검색된 사실)과 함께 작동합니다. 각 유형을 언제 사용해야 하는지 알아보려면 [에이전트 기능](/ko/concepts/agent-capabilities) 개요를 참조하세요. + + +## Tool이란 무엇인가? + +CrewAI에서 tool은 에이전트가 다양한 작업을 수행하기 위해 활용할 수 있는 기술 또는 기능입니다. +이에는 [CrewAI Toolkit](https://github.com/joaomdmoura/crewai-tools) 및 [LangChain Tools](https://python.langchain.com/docs/integrations/tools)의 tool이 포함되어, +간단한 검색부터 복잡한 상호작용, 그리고 에이전트 간의 효과적인 협업까지 모두 가능하게 합니다. + + +CrewAI 엔터프라이즈는 주요 비즈니스 시스템 및 API와의 사전 구축된 통합을 제공하는 종합적인 Tools Repository를 제공합니다. 며칠이 걸리던 엔터프라이즈 tool로 에이전트를 몇 분 만에 배포할 수 있습니다. + +엔터프라이즈 Tools Repository에는 다음이 포함됩니다: +- 인기 엔터프라이즈 시스템용 사전 구축 커넥터 +- 커스텀 tool 생성 인터페이스 +- 버전 관리 및 공유 기능 +- 보안 및 규정 준수 기능 + + +## 도구의 주요 특징 + +- **유틸리티**: 웹 검색, 데이터 분석, 콘텐츠 생성, 에이전트 협업과 같은 작업을 위해 제작됨. +- **통합성**: 도구를 워크플로우에 원활하게 통합하여 에이전트의 역량을 강화함. +- **맞춤화 가능성**: 맞춤형 도구를 개발하거나 기존 도구를 활용할 수 있는 유연성을 제공하여 에이전트의 특정 요구 사항에 대응함. +- **오류 처리**: 원활한 작동을 보장하기 위해 강력한 오류 처리 메커니즘을 포함함. +- **캐싱 메커니즘**: 성능 최적화와 중복 작업 감소를 위한 지능형 캐싱 기능을 갖춤. +- **비동기 지원**: 동기 및 비동기 도구를 모두 처리하여 논블로킹(Non-blocking) 작업을 가능하게 함. + +## CrewAI 도구 사용하기 + +crewAI 도구로 에이전트의 기능을 확장하려면, 우선 추가 도구 패키지를 설치하세요: + +```bash +pip install 'crewai[tools]' +``` + +아래는 도구 사용 예시입니다: + +```python Code +import os +from crewai import Agent, Task, Crew +# crewAI 도구 임포트 +from crewai_tools import ( + DirectoryReadTool, + FileReadTool, + SerperDevTool, + WebsiteSearchTool +) + +# API 키 설정 +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API 키 +os.environ["OPENAI_API_KEY"] = "Your Key" + +# 도구 인스턴스화 +docs_tool = DirectoryReadTool(directory='./blog-posts') +file_tool = FileReadTool() +search_tool = SerperDevTool() +web_rag_tool = WebsiteSearchTool() + +# 에이전트 생성 +researcher = Agent( + role='Market Research Analyst', + goal='Provide up-to-date market analysis of the AI industry', + backstory='An expert analyst with a keen eye for market trends.', + tools=[search_tool, web_rag_tool], + verbose=True +) + +writer = Agent( + role='Content Writer', + goal='Craft engaging blog posts about the AI industry', + backstory='A skilled writer with a passion for technology.', + tools=[docs_tool, file_tool], + verbose=True +) + +# 작업 정의 +research = Task( + description='Research the latest trends in the AI industry and provide a summary.', + expected_output='A summary of the top 3 trending developments in the AI industry with a unique perspective on their significance.', + agent=researcher +) + +write = Task( + description='Write an engaging blog post about the AI industry, based on the research analyst's summary. Draw inspiration from the latest blog posts in the directory.', + expected_output='A 4-paragraph blog post formatted in markdown with engaging, informative, and accessible content, avoiding complex jargon.', + agent=writer, + output_file='blog-posts/new_post.md' # 최종 블로그 글이 여기에 저장됩니다 +) + +# 계획 기능을 활성화하여 crew 구성 +crew = Crew( + agents=[researcher, writer], + tasks=[research, write], + verbose=True, + planning=True, # 계획 기능 활성화 +) + +# 작업 실행 +crew.kickoff() +``` + +## 사용 가능한 CrewAI 도구 + +- **에러 처리**: 모든 도구는 에러 처리 기능이 내장되어 있어, 에이전트가 예외 상황을 우아하게 관리하며 작업을 계속할 수 있습니다. +- **캐싱 메커니즘**: 모든 도구는 캐싱을 지원하여, 에이전트가 이전에 얻은 결과를 효율적으로 재사용할 수 있고 외부 자원에 대한 부하를 줄이며 실행 시간을 단축할 수 있습니다. 또한 도구의 `cache_function` 속성을 사용하여 캐싱 메커니즘을 세밀하게 제어할 수 있습니다. + +사용 가능한 도구 목록과 그 설명은 다음과 같습니다: + +| 도구 | 설명 | +| :-------------------------------- | :---------------------------------------------------------------------------------------------------- | +| **ApifyActorsTool** | 웹 스크래핑 및 자동화 작업을 위해 Apify Actors를 워크플로우에 통합하는 도구입니다. | +| **BrowserbaseLoadTool** | 웹 브라우저와 상호작용하고 데이터를 추출하는 도구입니다. | +| **CodeDocsSearchTool** | 코드 문서 및 관련 기술 문서를 검색하는 데 최적화된 RAG 도구입니다. | +| **CodeInterpreterTool** | 파이썬 코드를 해석하는 도구입니다. | +| **ComposioTool** | Composio 도구의 사용을 가능하게 합니다. | +| **CSVSearchTool** | CSV 파일 내에서 검색하도록 설계된 RAG 도구이며, 구조화된 데이터를 처리하도록 맞춤화되어 있습니다. | +| **DALL-E Tool** | DALL-E API를 사용해 이미지를 생성하는 도구입니다. | +| **DirectorySearchTool** | 디렉터리 내에서 검색하는 RAG 도구로, 파일 시스템을 탐색할 때 유용합니다. | +| **DOCXSearchTool** | DOCX 문서 내에서 검색하는 데 특화된 RAG 도구로, Word 파일을 처리할 때 이상적입니다. | +| **DirectoryReadTool** | 디렉터리 구조와 그 내용을 읽고 처리하도록 지원하는 도구입니다. | +| **ExaSearchTool** | 다양한 데이터 소스를 폭넓게 검색하기 위해 설계된 도구입니다. | +| **FileReadTool** | 다양한 파일 형식을 지원하며 파일에서 데이터를 읽고 추출할 수 있는 도구입니다. | +| **FirecrawlSearchTool** | Firecrawl을 이용해 웹페이지를 검색하고 결과를 반환하는 도구입니다. | +| **FirecrawlCrawlWebsiteTool** | Firecrawl을 사용해 웹페이지를 크롤링하는 도구입니다. | +| **FirecrawlScrapeWebsiteTool** | Firecrawl을 통해 웹페이지의 URL을 스크래핑하고 그 내용을 반환하는 도구입니다. | +| **GithubSearchTool** | GitHub 저장소 내에서 검색하는 RAG 도구로, 코드 및 문서 검색에 유용합니다. | +| **SerperDevTool** | 개발 용도로 특화된 도구로, 특정 기능이 개발 중입니다. | +| **TXTSearchTool** | 텍스트(.txt) 파일 내에서 검색하는 데 중점을 둔 RAG 도구로, 비구조적 데이터에 적합합니다. | +| **JSONSearchTool** | JSON 파일 내에서 검색하도록 설계된 RAG 도구로, 구조화된 데이터 처리에 적합합니다. | +| **LlamaIndexTool** | LlamaIndex 도구의 사용을 가능하게 합니다. | +| **MDXSearchTool** | 마크다운(MDX) 파일 내에서 검색하도록 맞춤화된 RAG 도구로, 문서화에 유용합니다. | +| **PDFSearchTool** | PDF 문서 내에서 검색하는 RAG 도구로, 스캔된 문서를 처리하기에 이상적입니다. | +| **PGSearchTool** | PostgreSQL 데이터베이스 내에서 검색하는 데 최적화된 RAG 도구로, 데이터베이스 쿼리에 적합합니다. | +| **Vision Tool** | DALL-E API를 사용해 이미지를 생성하는 도구입니다. | +| **RagTool** | 다양한 데이터 소스 및 형식을 처리할 수 있는 범용 RAG 도구입니다. | +| **ScrapeElementFromWebsiteTool** | 웹사이트에서 특정 요소만 스크래핑할 수 있는 도구로, 목표 데이터 추출에 유용합니다. | +| **ScrapeWebsiteTool** | 전체 웹사이트를 스크래핑할 수 있도록 도와주는 도구로, 포괄적인 데이터 수집에 이상적입니다. | +| **WebsiteSearchTool** | 웹사이트 콘텐츠를 검색하는 RAG 도구로, 웹 데이터 추출에 최적화되어 있습니다. | +| **XMLSearchTool** | XML 파일 내에서 검색하도록 설계된 RAG 도구로, 구조화된 데이터 형식에 적합합니다. | +| **YoutubeChannelSearchTool** | 유튜브 채널 내에서 검색하는 RAG 도구로, 동영상 콘텐츠 분석에 유용합니다. | +| **YoutubeVideoSearchTool** | 유튜브 동영상 내에서 검색하는 RAG 도구로, 동영상 데이터 추출에 이상적입니다. | + +## 자체 도구 만들기 + + + 개발자는 에이전트의 요구에 맞는 `custom tools`를 직접 제작하거나, + 미리 구축된 옵션을 활용할 수 있습니다. + + +CrewAI 도구를 만드는 방법에는 두 가지 주요 방법이 있습니다: + +### `BaseTool` 서브클래싱 + +```python Code +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class MyToolInput(BaseModel): + """Input schema for MyCustomTool.""" + argument: str = Field(..., description="Description of the argument.") + +class MyCustomTool(BaseTool): + name: str = "Name of my tool" + description: str = "What this tool does. It's vital for effective utilization." + args_schema: Type[BaseModel] = MyToolInput + + def _run(self, argument: str) -> str: + # Your tool's logic here + return "Tool's result" +``` + +## 비동기 도구 지원 + +CrewAI는 비동기 도구를 지원하여, 네트워크 요청, 파일 I/O 또는 기타 비동기 작업과 같이 메인 실행 스레드를 차단하지 않고 비차단 연산을 수행하는 도구를 구현할 수 있습니다. + +### 비동기 툴 만들기 + +비동기 툴을 만드는 방법에는 두 가지가 있습니다: + +#### 1. `tool` 데코레이터를 비동기 함수와 함께 사용하기 + +```python Code +from crewai.tools import tool + +@tool("fetch_data_async") +async def fetch_data_async(query: str) -> str: + """Asynchronously fetch data based on the query.""" + # Simulate async operation + await asyncio.sleep(1) + return f"Data retrieved for {query}" +``` + +#### 2. 사용자 지정 Tool 클래스에서 비동기 메서드 구현 + +```python Code +from crewai.tools import BaseTool + +class AsyncCustomTool(BaseTool): + name: str = "async_custom_tool" + description: str = "An asynchronous custom tool" + + async def _run(self, query: str = "") -> str: + """Asynchronously run the tool""" + # Your async implementation here + await asyncio.sleep(1) + return f"Processed {query} asynchronously" +``` + +### 비동기 도구 사용하기 + +비동기 도구는 표준 Crew 워크플로우와 Flow 기반 워크플로우 모두에서 원활하게 작동합니다: + +```python Code +# In standard Crew +agent = Agent(role="researcher", tools=[async_custom_tool]) + +# In Flow +class MyFlow(Flow): + @start() + async def begin(self): + crew = Crew(agents=[agent]) + result = await crew.kickoff_async() + return result +``` + +CrewAI 프레임워크는 동기 및 비동기 도구의 실행을 자동으로 처리하므로, 별도로 호출 방법을 신경 쓸 필요가 없습니다. + +### `tool` 데코레이터 활용하기 + +```python Code +from crewai.tools import tool +@tool("Name of my tool") +def my_tool(question: str) -> str: + """Clear description for what this tool is useful for, your agent will need this information to use it.""" + # Function logic here + return "Result from your custom tool" +``` + +### 커스텀 캐싱 메커니즘 + + + 도구는 선택적으로 `cache_function`을 구현하여 캐싱 동작을 세밀하게 조정할 수 있습니다. + 이 함수는 특정 조건에 따라 결과를 언제 캐싱할지 결정하여 캐싱 로직을 정교하게 제어할 수 있도록 합니다. + + +```python Code +from crewai.tools import tool + +@tool +def multiplication_tool(first_number: int, second_number: int) -> str: + """Useful for when you need to multiply two numbers together.""" + return first_number * second_number + +def cache_func(args, result): + # In this case, we only cache the result if it's a multiple of 2 + cache = result % 2 == 0 + return cache + +multiplication_tool.cache_function = cache_func + +writer1 = Agent( + role="Writer", + goal="You write lessons of math for kids.", + backstory="You're an expert in writing and you love to teach kids but you know nothing of math.", + tools=[multiplication_tool], + allow_delegation=False, + ) + #... +``` + +## 결론 + +도구는 CrewAI 에이전트의 역량을 확장하는 데 중요한 역할을 하며, 이를 통해 에이전트가 폭넓은 작업을 수행하고 효과적으로 협업할 수 있습니다. CrewAI로 솔루션을 구축할 때는, 맞춤형 또는 기존의 도구를 모두 활용하여 에이전트를 강화하고 AI 생태계를 향상시키세요. 에이전트의 성능과 기능을 최적화하기 위해 오류 처리, 캐싱 메커니즘, 그리고 도구 인자의 유연성도 고려해보시기 바랍니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/concepts/training.mdx b/docs/v1.15.13/ko/concepts/training.mdx new file mode 100644 index 0000000000..885366afe5 --- /dev/null +++ b/docs/v1.15.13/ko/concepts/training.mdx @@ -0,0 +1,132 @@ +--- +title: 교육 +description: 피드백을 조기에 제공하여 CrewAI 에이전트를 학습시키고 일관된 결과를 얻는 방법을 알아보세요. +icon: dumbbell +mode: "wide" +--- + +## 개요 + +CrewAI의 학습 기능을 사용하면 커맨드라인 인터페이스(CLI)를 통해 AI 에이전트를 학습시킬 수 있습니다. +`crewai train -n ` 명령어를 실행하면 학습 프로세스의 반복 횟수를 지정할 수 있습니다. + +학습 과정에서 CrewAI는 에이전트의 성능을 최적화하기 위한 다양한 기법과 인간의 피드백을 활용합니다. +이를 통해 에이전트는 이해력, 의사결정 능력, 문제 해결 능력을 향상할 수 있습니다. + +### CLI를 사용하여 Crew 학습시키기 + +학습 기능을 사용하려면 다음 단계를 따르십시오: + +1. 터미널 또는 명령 프롬프트를 엽니다. +2. CrewAI 프로젝트가 위치한 디렉터리로 이동합니다. +3. 다음 명령어를 실행합니다: + +```shell +crewai train -n (optional) +``` + + ``를 원하는 학습 반복 횟수로, ``을 `.pkl`로 끝나는 적절한 파일 이름으로 바꿔 입력하세요. + + +### 크루를 프로그래밍 방식으로 훈련시키기 + +크루를 프로그래밍 방식으로 훈련시키려면 다음 단계를 따르세요: + +1. 훈련을 위한 반복 횟수를 정의합니다. +2. 훈련 프로세스에 사용할 입력 파라미터를 지정합니다. +3. 잠재적인 오류를 처리하기 위해 try-except 블록 내에서 훈련 명령을 실행합니다. + +```python Code +n_iterations = 2 +inputs = {"topic": "CrewAI Training"} +filename = "your_model.pkl" + +try: + YourCrewName_Crew().crew().train( + n_iterations=n_iterations, + inputs=inputs, + filename=filename + ) + +except Exception as e: + raise Exception(f"An error occurred while training the crew: {e}") +``` + +### 주요 참고 사항 + +- **양의 정수 필수 조건:** 반복 횟수(`n_iterations`)가 양의 정수인지 확인하세요. 이 조건이 충족되지 않으면 코드에서 `ValueError`가 발생합니다. +- **파일명 필수 조건:** 파일명이 `.pkl`로 끝나는지 확인하세요. 이 조건이 충족되지 않으면 코드에서 `ValueError`가 발생합니다. +- **에러 처리:** 코드는 서브프로세스 오류 및 예기치 않은 예외를 처리하며, 사용자에게 에러 메시지를 제공합니다. + +에이전트의 복잡성에 따라 훈련 과정이 다소 시간이 소요될 수 있으며, 각 반복마다 사용자의 피드백이 필요함을 유의하세요. + +훈련이 완료되면, 에이전트는 향상된 능력과 지식을 갖추게 되어, 더욱 복잡한 작업을 해결하고 일관성 있고 가치 있는 인사이트를 제공할 수 있습니다. + +에이전트를 정기적으로 업데이트하고 재훈련하여 최신 정보와 업계 발전을 반영할 수 있도록 하세요. + +CrewAI와 함께 즐거운 훈련 되세요! 🚀 + +## 소형 언어 모델 고려사항 + + + 소형 언어 모델(≤7B 파라미터)을 학습 데이터 평가에 사용할 때, 구조화된 출력 생성 및 복잡한 지침 준수에 어려움을 겪을 수 있으니 주의하시기 바랍니다. + + +### 소형 모델의 학습 평가 한계 + + + + 소형 모델은 구조화된 학습 평가에 필요한 유효한 JSON 응답을 생성하는 데 종종 어려움을 겪으며, 이로 인해 파싱 오류와 불완전한 데이터가 발생할 수 있습니다. + + + 7B 파라미터 미만의 모델은 대형 모델에 비해 더 제한적이고 깊이 있는 추론이 부족한 평가 결과를 제공할 수 있습니다. + + + 복잡한 학습 평가 기준을 소형 모델이 완전히 따르거나 고려하지 못할 수 있습니다. + + + 소형 모델은 여러 학습 반복 과정에서 평가의 일관성이 부족할 수 있습니다. + + + +### 학습을 위한 권장 사항 + + + + 최적의 학습 품질과 신뢰할 수 있는 평가를 위해 최소 7B 파라미터 이상의 모델을 사용하는 것을 강력히 권장합니다: + + ```python + from crewai import Agent, Crew, Task, LLM + + # Recommended minimum for training evaluation + llm = LLM(model="mistral/open-mistral-7b") + + # Better options for reliable training evaluation + llm = LLM(model="anthropic/claude-3-sonnet-20240229-v1:0") + llm = LLM(model="gpt-4o") + + # Use this LLM with your agents + agent = Agent( + role="Training Evaluator", + goal="Provide accurate training feedback", + llm=llm + ) + ``` + + + 더 강력한 모델일수록 더 우수한 피드백과 뛰어난 추론을 제공하므로, 더욱 효과적인 학습 반복이 가능합니다. + + + + 학습 평가를 위해 반드시 소형 모델을 사용해야 한다면 다음과 같은 제약 사항에 유의하세요: + + ```python + # Using a smaller model (expect some limitations) + llm = LLM(model="huggingface/microsoft/Phi-3-mini-4k-instruct") + ``` + + + CrewAI는 소형 모델에 대한 최적화 기능을 포함하고 있지만, 더 많은 인간의 개입이 필요한 덜 신뢰할 수 있고 세밀하지 않은 평가 결과가 발생할 수 있습니다. + + + \ No newline at end of file diff --git a/docs/v1.15.13/ko/examples/cookbooks.mdx b/docs/v1.15.13/ko/examples/cookbooks.mdx new file mode 100644 index 0000000000..9b835cd1b1 --- /dev/null +++ b/docs/v1.15.13/ko/examples/cookbooks.mdx @@ -0,0 +1,23 @@ +--- +title: CrewAI Cookbooks +description: 패턴을 빠르게 익히기 위한 기능 중심 Quickstarts와 노트북. +icon: book +mode: "wide" +--- + +## Quickstarts & Demos + + + + 특정 CrewAI 기능을 보여주는 데모와 소규모 프로젝트. + + + 실습을 위한 인터랙티브 노트북. + + + + +Cookbooks로 패턴을 빠르게 익힌 뒤, 프로덕션급 구현은 Full Examples에서 확인하세요. + + + diff --git a/docs/v1.15.13/ko/examples/example.mdx b/docs/v1.15.13/ko/examples/example.mdx new file mode 100644 index 0000000000..68dcccc5d5 --- /dev/null +++ b/docs/v1.15.13/ko/examples/example.mdx @@ -0,0 +1,86 @@ +--- +title: CrewAI 예시 +description: Crews, Flows, 통합, Notebooks로 구성된 예시 모음입니다. +icon: rocket-launch +mode: "wide" +--- + +## Crews + + + + 다중 에이전트 마케팅 캠페인 기획. + + + 개인화된 여행 계획. + + + 벡터 검색 기반 이력서 매칭. + + + 채용 공고 자동 생성. + + + 파이썬 게임을 설계·구축하는 멀티 에이전트 팀. + + + 후보자 소싱 및 평가. + + + 전체 crew 예시 목록. + + + +## Flows + + + + 라우팅 기반 콘텐츠 생성. + + + 이메일 모니터링과 자동 응답. + + + 휴먼‑인‑더‑루프 리드 평가. + + + 노트 처리 및 연동. + + + 반복적 자가 개선 워크플로우. + + + 병렬 챕터 생성. + + + 전체 flow 예시 목록. + + + +## 통합 (Integrations) + + + + LangGraph 프레임워크 연동. + + + Azure OpenAI와 함께 사용. + + + NVIDIA 생태계 연동. + + + 전체 통합 예시. + + + +## 노트북 (Notebooks) + + + + Simple QA Crew + Flow. + + + 학습과 실험을 위한 인터랙티브 예시 모음. + + \ No newline at end of file diff --git a/docs/v1.15.13/ko/guides/advanced/customizing-prompts.mdx b/docs/v1.15.13/ko/guides/advanced/customizing-prompts.mdx new file mode 100644 index 0000000000..c65b86abe5 --- /dev/null +++ b/docs/v1.15.13/ko/guides/advanced/customizing-prompts.mdx @@ -0,0 +1,331 @@ +--- +title: 프롬프트 커스터마이징 +description: CrewAI를 위한 저수준 프롬프트 커스터마이징에 대해 자세히 알아보고, 다양한 모델과 언어에 대해 매우 맞춤화되고 복잡한 사용 사례를 구현할 수 있습니다. +icon: message-pen +mode: "wide" +--- + +## 프롬프트를 커스터마이즈해야 하는 이유 + +CrewAI의 기본 프롬프트는 많은 시나리오에서 잘 작동하지만, 저수준 커스터마이징은 훨씬 더 유연하고 강력한 에이전트 행동으로 이어집니다. 더 깊은 제어를 통해 얻을 수 있는 이점은 다음과 같습니다: + +1. **특정 LLM에 맞게 최적화** – GPT-4, Claude, Llama와 같은 다양한 모델은 각자의 고유한 아키텍처에 맞는 프롬프트 형식에서 최고의 성능을 발휘합니다. +2. **언어 변경** – 영어를 넘어서는 언어로만 작동하는 에이전트를 구축하여 미묘한 뉘앙스도 정확하게 처리할 수 있습니다. +3. **복잡한 도메인에 특화** – 헬스케어, 금융, 법률 등 매우 전문적인 산업군에 맞춰 프롬프트를 조정할 수 있습니다. +4. **톤과 스타일 조정** – 에이전트의 톤과 스타일을 좀 더 형식적, 캐주얼, 창의적, 혹은 분석적으로 만들 수 있습니다. +5. **초고도 커스텀 사례 지원** – 복잡하고 프로젝트에 특화된 요구사항을 충족하기 위해 고급 프롬프트 구조 및 포맷을 활용할 수 있습니다. + +이 가이드에서는 CrewAI의 프롬프트를 더 낮은 레벨에서 활용하여, 에이전트의 사고 및 상호작용 방식을 세밀하게 제어하는 방법을 다룹니다. + +## CrewAI의 Prompt 시스템 이해하기 + +내부적으로 CrewAI는 광범위하게 커스터마이즈할 수 있는 모듈식 prompt 시스템을 사용합니다: + +- **Agent 템플릿** – 각 agent가 할당된 역할을 수행하는 방식을 결정합니다. +- **Prompt 슬라이스** – 작업, 도구 사용, 출력 구조와 같은 특수한 동작을 제어합니다. +- **오류 처리** – agent가 실패, 예외, 또는 타임아웃에 어떻게 반응할지 지정합니다. +- **도구별 prompt** – 도구가 호출되거나 사용되는 방법에 대한 상세 지침을 정의합니다. + +이 요소들이 어떻게 구성되어 있는지 보려면 [CrewAI 저장소의 원본 prompt 템플릿](https://github.com/crewAIInc/crewAI/blob/main/src/crewai/translations/en.json)을 확인하세요. 여기서 필요에 따라 오버라이드하거나 수정하여 고급 동작을 구현할 수 있습니다. + +## 기본 시스템 지침 이해하기 + + +**프로덕션 투명성 문제**: CrewAI는 여러분이 인지하지 못하는 사이에 기본 지침을 프롬프트에 자동으로 삽입합니다. 이 섹션에서는 내부적으로 어떤 일이 일어나고 있는지와 완전한 제어권을 얻는 방법을 설명합니다. + + +여러분이 `role`, `goal`, `backstory`로 에이전트를 정의할 때, CrewAI는 형식 및 동작을 제어하는 추가 시스템 지침을 자동으로 추가합니다. 이러한 기본 삽입을 이해하는 것은 완전한 프롬프트 투명성이 필요한 프로덕션 시스템에서 매우 중요합니다. + +### CrewAI가 자동으로 삽입하는 내용 + +에이전트 구성에 따라 CrewAI는 다양한 기본 지침을 추가합니다: + +#### 도구가 없는 에이전트를 위한 안내 +```text +"I MUST use these formats, my job depends on it!" +``` + +#### 도구가 있는 에이전트를 위한 안내 +```text +"IMPORTANT: Use the following format in your response: + +Thought: you should always think about what to do +Action: the action to take, only one name of [tool_names] +Action Input: the input to the action, just a simple JSON object... +``` + +#### 구조화된 출력(JSON/Pydantic)의 경우 +```text +"Ensure your final answer contains only the content in the following format: {output_format} +Ensure the final output does not include any code block markers like ```json or ```python." +``` + +### 전체 시스템 프롬프트 보기 + +LLM에 전달되는 프롬프트가 정확히 무엇인지 확인하려면, 생성된 프롬프트를 확인할 수 있습니다: + +```python +from crewai import Agent, Crew, Task +from crewai.utilities.prompts import Prompts + +# 에이전트 생성 +agent = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + backstory="You are an expert data analyst with 10 years of experience.", + verbose=True +) + +# 샘플 태스크 생성 +task = Task( + description="Analyze the sales data and identify trends", + expected_output="A detailed analysis with key insights and trends", + agent=agent +) + +# 프롬프트 생성기 생성 +prompt_generator = Prompts( + agent=agent, + has_tools=len(agent.tools) > 0, + use_system_prompt=agent.use_system_prompt +) + +# 실제 프롬프트 생성 및 확인 +generated_prompt = prompt_generator.task_execution() + +# LLM에 전달될 전체 시스템 프롬프트 출력 +if "system" in generated_prompt: + print("=== SYSTEM PROMPT ===") + print(generated_prompt["system"]) + print("\n=== USER PROMPT ===") + print(generated_prompt["user"]) +else: + print("=== COMPLETE PROMPT ===") + print(generated_prompt["prompt"]) + +# 태스크 설명이 어떻게 포맷되는지도 확인할 수 있습니다 +print("\n=== TASK CONTEXT ===") +print(f"Task Description: {task.description}") +print(f"Expected Output: {task.expected_output}") +``` + +### 기본 지침 재정의 + +프롬프트에 대한 완전한 제어를 얻기 위해 여러 가지 옵션이 있습니다: + +#### 옵션 1: 커스텀 템플릿 (권장) +```python +from crewai import Agent + +# Define your own system template without default instructions +custom_system_template = """You are {role}. {backstory} +Your goal is: {goal} + +Respond naturally and conversationally. Focus on providing helpful, accurate information.""" + +custom_prompt_template = """Task: {input} + +Please complete this task thoughtfully.""" + +agent = Agent( + role="Research Assistant", + goal="Help users find accurate information", + backstory="You are a helpful research assistant.", + system_template=custom_system_template, + prompt_template=custom_prompt_template, + use_system_prompt=True # Use separate system/user messages +) +``` + +#### 옵션 2: 사용자 지정 프롬프트 파일 +특정 프롬프트 슬라이스를 오버라이드하려면 `custom_prompts.json` 파일을 생성하세요: + +```json +{ + "slices": { + "no_tools": "\nProvide your best answer in a natural, conversational way.", + "tools": "\nYou have access to these tools: {tools}\n\nUse them when helpful, but respond naturally.", + "formatted_task_instructions": "Format your response as: {output_format}" + } +} +``` + +그런 다음 crew에서 사용하세요: + +```python +crew = Crew( + agents=[agent], + tasks=[task], + prompt_file="custom_prompts.json", + verbose=True +) +``` + + +`agent.i18n`은 이전 버전과의 호환성을 위해서만 유지되며 사용이 중단될 예정입니다. 런타임 프롬프트 커스터마이징에는 `Crew`에 `prompt_file`을 전달하세요. 프롬프트 슬라이스를 코드에서 직접 읽어야 한다면 i18n 유틸리티를 직접 사용하세요: + + +```python +from crewai.utilities.i18n import get_i18n + +i18n = get_i18n("custom_prompts.json") +format_slice = i18n.slice("format") +tool_prompt = i18n.tools("ask_question") +``` + +#### 옵션 3: o1 모델에 대한 시스템 프롬프트 비활성화 +```python +agent = Agent( + role="Analyst", + goal="Analyze data", + backstory="Expert analyst", + use_system_prompt=False # Disables system prompt separation +) +``` + +### 관측 도구를 활용한 디버깅 + +프로덕션 투명성을 위해 관측 플랫폼과 통합하여 모든 prompt 및 LLM 상호작용을 모니터링하세요. 이를 통해 LLM에 어떤 prompt(기본 지침 포함)가 전송되고 있는지 정확히 확인할 수 있습니다. + +다양한 플랫폼(Langfuse, MLflow, Weights & Biases, 커스텀 로깅 솔루션 등)과의 통합에 대한 자세한 가이드는 [관측 문서](/ko/observability/overview)를 참고하세요. + +### 프로덕션을 위한 모범 사례 + +1. **프로덕션에 배포하기 전에 반드시 생성된 prompt를 점검하세요** +2. **prompt 내용을 완전히 제어해야 할 경우에는 커스텀 템플릿을 사용하세요** +3. **지속적인 prompt 모니터링을 위해 관측 도구를 통합하세요** ([Observability 문서](/ko/observability/overview) 참고) +4. **서로 다른 LLM으로 테스트하세요**. 기본 instruction은 모델마다 다르게 작동할 수 있습니다 +5. **팀 투명성을 위해 prompt 커스터마이징을 문서화하세요** + + +기본 instruction은 일관된 agent 동작을 보장하기 위해 존재하지만, 도메인 특화 요구사항과 충돌할 수 있습니다. 위의 커스터마이징 옵션을 사용하여 프로덕션 시스템에서 agent의 동작을 완전히 제어할 수 있습니다. + + +## 프롬프트 파일 관리 모범 사례 + +저수준 프롬프트 커스터마이징을 수행할 때는 다음 지침을 따라 조직적이고 유지 관리가 용이하도록 하세요: + +1. **파일 분리** – 커스터마이징한 프롬프트는 메인 코드베이스 외부의 전용 JSON 파일에 저장하세요. +2. **버전 관리** – 리포지토리 내에서 변경 사항을 추적하여 프롬프트 조정 내역이 명확히 문서화되도록 하세요. +3. **모델 또는 언어별 정리** – `prompts_llama.json` 또는 `prompts_es.json`과 같이 네이밍 스킴을 사용해 특화된 구성을 빠르게 식별할 수 있도록 하세요. +4. **변경 사항 문서화** – 주석을 추가하거나 README를 유지 관리하여 커스터마이징의 목적과 범위를 상세히 기술하세요. +5. **수정 최소화** – 실제로 조정이 필요한 특정 부분만 오버라이드하고, 나머지 부분은 기본 기능을 유지하세요. + +## 프롬프트를 커스터마이즈하는 가장 간단한 방법 + +가장 간단한 접근 방법 중 하나는 오버라이드하려는 프롬프트에 대한 JSON 파일을 생성한 다음, 해당 파일을 Crew에 지정하는 것입니다. + +1. 업데이트된 프롬프트 슬라이스로 JSON 파일을 만드세요. +2. Crew의 `prompt_file` 파라미터를 통해 그 파일을 참조하세요. + +그러면 CrewAI가 기본값과 사용자가 지정한 내용을 병합하므로, 모든 프롬프트를 다시 정의할 필요가 없습니다. 방법은 다음과 같습니다: + +프롬프트 슬라이스를 코드에서 직접 읽어야 하는 경우에는 `agent.i18n`을 읽는 대신 동일한 프롬프트 파일로 `crewai.utilities.i18n.get_i18n()`을 사용하세요. + +### 예시: 기본 프롬프트 커스터마이징 + +수정하고 싶은 프롬프트를 포함하는 `custom_prompts.json` 파일을 생성하세요. 변경 사항만이 아니라 포함해야 하는 모든 최상위 프롬프트를 반드시 나열해야 합니다: + +```json +{ + "slices": { + "format": "When responding, follow this structure:\n\nTHOUGHTS: Your step-by-step thinking\nACTION: Any tool you're using\nRESULT: Your final answer or conclusion" + } +} +``` + +그 다음 아래와 같이 통합하세요: + +```python +from crewai import Agent, Crew, Task, Process + +# 평소와 같이 에이전트와 태스크를 생성 +researcher = Agent( + role="Research Specialist", + goal="Find information on quantum computing", + backstory="You are a quantum physics expert", + verbose=True +) + +research_task = Task( + description="Research quantum computing applications", + expected_output="A summary of practical applications", + agent=researcher +) + +# 커스텀 프롬프트 파일로 crew를 생성 +crew = Crew( + agents=[researcher], + tasks=[research_task], + prompt_file="path/to/custom_prompts.json", + verbose=True +) + +# crew 실행 +result = crew.kickoff() +``` + +이 몇 가지 간단한 수정으로, agent가 소통하고 태스크를 해결하는 방식을 세밀하게 제어할 수 있습니다. + +## 특정 모델에 맞춘 최적화 + +모델마다 잘 동작하는 프롬프트의 구조가 다릅니다. 프롬프트를 모델의 뉘앙스에 맞게 더욱 깊이 있게 조정하면 성능이 크게 향상될 수 있습니다. + +### 예시: Llama 3.3 프롬프트 템플릿 + +예를 들어, Meta의 Llama 3.3과 작업할 때는 더 깊은 수준의 커스터마이징이 다음에 설명된 권장 구조를 반영할 수 있습니다: +https://www.llama.com/docs/model-cards-and-prompt-formats/llama3_1/#prompt-template + +다음은 Llama 3.3을 코드에서 활용하도록 Agent를 세밀하게 튜닝하는 방법을 보여주는 예시입니다: + +```python +from crewai import Agent, Crew, Task, Process +from crewai_tools import DirectoryReadTool, FileReadTool + +# Define templates for system, user (prompt), and assistant (response) messages +system_template = """<|begin_of_text|><|start_header_id|>system<|end_header_id|>{{ .System }}<|eot_id|>""" +prompt_template = """<|start_header_id|>user<|end_header_id|>{{ .Prompt }}<|eot_id|>""" +response_template = """<|start_header_id|>assistant<|end_header_id|>{{ .Response }}<|eot_id|>""" + +# Create an Agent using Llama-specific layouts +principal_engineer = Agent( + role="Principal Engineer", + goal="Oversee AI architecture and make high-level decisions", + backstory="You are the lead engineer responsible for critical AI systems", + verbose=True, + llm="groq/llama-3.3-70b-versatile", # Using the Llama 3 model + system_template=system_template, + prompt_template=prompt_template, + response_template=response_template, + tools=[DirectoryReadTool(), FileReadTool()] +) + +# Define a sample task +engineering_task = Task( + description="Review AI implementation files for potential improvements", + expected_output="A summary of key findings and recommendations", + agent=principal_engineer +) + +# Create a Crew for the task +llama_crew = Crew( + agents=[principal_engineer], + tasks=[engineering_task], + process=Process.sequential, + verbose=True +) + +# Execute the crew +result = llama_crew.kickoff() +print(result.raw) +``` + +이와 같이 더 심도 있는 설정을 통해 별도의 JSON 파일 없이도 Llama 기반 워크플로에 대해 포괄적이고 저수준의 제어를 할 수 있습니다. + +## 결론 + +CrewAI에서의 저수준 prompt 커스터마이제이션은 매우 맞춤화되고 복잡한 사용 사례에 대한 문을 엽니다. 잘 구성된 prompt 파일(또는 직접 작성한 인라인 템플릿)을 구축함으로써 다양한 모델, 언어, 특화된 도메인을 수용할 수 있습니다. 이러한 수준의 유연성 덕분에 원하는 AI 동작을 정확하게 설계할 수 있으며, override하지 않을 경우에도 CrewAI가 신뢰할 수 있는 기본값을 제공한다는 점에서 안심할 수 있습니다. + + +이제 CrewAI에서 고급 prompt 커스터마이징을 위한 기초를 갖추었습니다. 모델별 구조나 도메인별 제약에 맞춰 적용하든, 이러한 저수준 접근 방식은 agent 상호작용을 매우 전문적으로 조정할 수 있게 해줍니다. + diff --git a/docs/v1.15.13/ko/guides/advanced/fingerprinting.mdx b/docs/v1.15.13/ko/guides/advanced/fingerprinting.mdx new file mode 100644 index 0000000000..bc4b4e3201 --- /dev/null +++ b/docs/v1.15.13/ko/guides/advanced/fingerprinting.mdx @@ -0,0 +1,134 @@ +--- +title: 지문 인식 +description: CrewAI의 지문 인식 시스템을 사용하여 컴포넌트를 전체 라이프사이클 동안 고유하게 식별하고 추적하는 방법을 알아보세요. +icon: fingerprint +mode: "wide" +--- + +## 개요 + +CrewAI의 Fingerprints는 컴포넌트를 고유하게 식별하고 그 생애주기를 추적할 수 있는 방법을 제공합니다. 각 `Agent`, `Crew`, `Task`는 생성 시 자동으로 고유한 fingerprint를 부여받으며, 이는 수동으로 변경할 수 없습니다. + +이러한 fingerprints는 다음과 같은 용도로 사용할 수 있습니다: +- 컴포넌트 사용 감사 및 추적 +- 컴포넌트 식별 무결성 보장 +- 컴포넌트에 메타데이터 첨부 +- 추적 가능한 작업 체인 생성 + +## 지문(Fingerprints)의 작동 방식 + +지문(fingerprint)은 `crewai.security` 모듈의 `Fingerprint` 클래스의 인스턴스입니다. 각 지문에는 다음과 같은 정보가 포함되어 있습니다: + +- UUID 문자열: 컴포넌트의 고유 식별자로, 자동으로 생성되며 수동으로 설정할 수 없습니다. +- 생성 타임스탬프: 지문이 생성된 시점을 나타내며, 자동으로 설정되고 수동으로 수정할 수 없습니다. +- 메타데이터: 추가 정보를 담은 사전(dictionary)으로, 사용자 정의가 가능합니다. + +지문은 컴포넌트가 생성될 때 자동으로 생성되어 할당됩니다. 각 컴포넌트는 읽기 전용 속성을 통해 자신의 지문을 제공합니다. + +## 기본 사용법 + +### 지문 접근하기 + +```python +from crewai import Agent, Crew, Task + +# Create components - fingerprints are automatically generated +agent = Agent( + role="Data Scientist", + goal="Analyze data", + backstory="Expert in data analysis" +) + +crew = Crew( + agents=[agent], + tasks=[] +) + +task = Task( + description="Analyze customer data", + expected_output="Insights from data analysis", + agent=agent +) + +# Access the fingerprints +agent_fingerprint = agent.fingerprint +crew_fingerprint = crew.fingerprint +task_fingerprint = task.fingerprint + +# Print the UUID strings +print(f"Agent fingerprint: {agent_fingerprint.uuid_str}") +print(f"Crew fingerprint: {crew_fingerprint.uuid_str}") +print(f"Task fingerprint: {task_fingerprint.uuid_str}") +``` + +### 지문 메타데이터 작업 + +지문에 추가적인 맥락 정보를 제공하기 위해 메타데이터를 추가할 수 있습니다: + +```python +# Add metadata to the agent's fingerprint +agent.security_config.fingerprint.metadata = { + "version": "1.0", + "department": "Data Science", + "project": "Customer Analysis" +} + +# Access the metadata +print(f"Agent metadata: {agent.fingerprint.metadata}") +``` + +## 지문(Fingerprint) 지속성 + +지문은 컴포넌트의 생애 주기 전체에 걸쳐 지속되고 변하지 않도록 설계되었습니다. 컴포넌트를 수정하더라도 지문은 동일하게 유지됩니다: + +```python +original_fingerprint = agent.fingerprint.uuid_str + +# Modify the agent +agent.goal = "New goal for analysis" + +# The fingerprint remains unchanged +assert agent.fingerprint.uuid_str == original_fingerprint +``` + +## 결정론적 지문 + +UUID와 생성 타임스탬프를 직접 설정할 수는 없지만, `generate` 메서드와 시드(seed)를 사용하여 결정론적 지문을 만들 수 있습니다: + +```python +from crewai.security import Fingerprint + +# 시드 문자열을 사용하여 결정론적 지문 생성 +deterministic_fingerprint = Fingerprint.generate(seed="my-agent-id") + +# 동일한 시드로 항상 동일한 지문이 생성됨 +same_fingerprint = Fingerprint.generate(seed="my-agent-id") +assert deterministic_fingerprint.uuid_str == same_fingerprint.uuid_str + +# 메타데이터도 설정할 수 있음 +custom_fingerprint = Fingerprint.generate( + seed="my-agent-id", + metadata={"version": "1.0"} +) +``` + +## 고급 사용 + +### Fingerprint 구조 + +각 fingerprint는 다음과 같은 구조를 가지고 있습니다: + +```python +from crewai.security import Fingerprint + +fingerprint = agent.fingerprint + +# UUID 문자열 - 고유 식별자 (자동 생성) +uuid_str = fingerprint.uuid_str # e.g., "123e4567-e89b-12d3-a456-426614174000" + +# 생성 타임스탬프 (자동 생성) +created_at = fingerprint.created_at # datetime 객체 + +# 메타데이터 - 추가 정보용 (사용자 지정 가능) +metadata = fingerprint.metadata # 딕셔너리, 기본값은 {} +``` \ No newline at end of file diff --git a/docs/v1.15.13/ko/guides/agents/crafting-effective-agents.mdx b/docs/v1.15.13/ko/guides/agents/crafting-effective-agents.mdx new file mode 100644 index 0000000000..b7ec97a7c7 --- /dev/null +++ b/docs/v1.15.13/ko/guides/agents/crafting-effective-agents.mdx @@ -0,0 +1,454 @@ +--- +title: 효과적인 에이전트 제작 +description: 복잡한 문제를 효과적으로 해결하기 위해 협업하는 강력하고 전문화된 AI 에이전트를 설계하는 모범 사례를 배워보세요. +icon: robot +mode: "wide" +--- + +## 에이전트 설계의 예술과 과학 + +CrewAI의 핵심에는 에이전트가 있습니다. 에이전트는 협업 프레임워크 내에서 특정 역할을 수행하도록 설계된 전문화된 AI 엔터티입니다. 기본적인 에이전트를 만드는 것은 간단하지만, 진정으로 효과적이고 탁월한 결과를 만들어내는 에이전트를 설계하려면 주요 설계 원칙과 모범 사례를 이해해야 합니다. + +이 가이드는 여러분이 에이전트 설계의 예술을 마스터할 수 있도록 도와줍니다. 이를 통해 효과적으로 협업하고, 비판적으로 사고하며, 특정 요구에 맞춤화된 고품질 결과물을 만들어내는 전문화된 AI 페르소나를 설계할 수 있게 됩니다. + +### 에이전트 설계가 중요한 이유 + +에이전트를 정의하는 방식은 다음에 중대한 영향을 미칩니다: + +1. **출력 품질**: 잘 설계된 에이전트는 더 관련성 높고, 품질이 뛰어난 결과를 생성합니다 +2. **협업 효율성**: 상호 보완적인 역량을 가진 에이전트들이 함께 더 효율적으로 작업합니다 +3. **작업 성과**: 명확한 역할과 목표를 가진 에이전트가 작업을 더 효과적으로 수행합니다 +4. **시스템 확장성**: 신중하게 설계된 에이전트는 여러 crew와 다양한 컨텍스트에서 재사용될 수 있습니다 + +이러한 측면에서 뛰어난 에이전트를 만들기 위한 모범 사례를 함께 살펴보겠습니다. + +## 80/20 법칙: 에이전트보다 작업에 집중하세요 + +효과적인 AI 시스템을 구축할 때 이 중요한 원칙을 기억하세요: **노력의 80%는 작업 설계에, 20%만 에이전트 정의에 투자해야 합니다**. + +왜일까요? 아무리 완벽하게 정의된 에이전트라도 잘못된 작업 설계에서는 실패하지만, 잘 설계된 작업은 단순한 에이전트까지도 뛰어나게 만들 수 있기 때문입니다. 즉, + +- 대부분의 시간을 명확한 작업 지침 작성에 할애하세요 +- 상세한 입력과 예상 결과를 정의하세요 +- 실행을 안내할 예시와 컨텍스트를 추가하세요 +- 남은 시간에는 에이전트 역할, 목표, 배경에 집중하세요 + +이는 에이전트 설계가 중요하지 않다는 의미가 아닙니다. 분명히 중요합니다. 하지만 실행 실패의 대부분은 작업 설계에서 발생하므로, 그에 따라 우선순위를 두어야 합니다. + +## 효과적인 에이전트 설계의 핵심 원칙 + +### 1. 역할-목표-배경 이야기 프레임워크 + +CrewAI에서 가장 강력한 에이전트는 세 가지 핵심 요소의 탄탄한 기반 위에 구축됩니다: + +#### 역할: 에이전트의 전문화된 기능 + +역할은 에이전트가 수행하는 일과 전문 분야를 정의합니다. 역할을 설계할 때는 다음을 준수하세요: + +- **구체적이고 전문적으로 작성하세요**: "작가" 대신 "기술 문서 전문가"나 "창의적 스토리텔러"처럼 명확하게 표현하세요. +- **현실 세계의 직업과 일치시키세요**: 역할을 잘 알려진 직업 유형에 기반하세요. +- **도메인 전문성을 포함하세요**: 에이전트의 지식 분야를 명확히 하세요 (예: "시장 동향에 특화된 금융 분석가"). + +**효과적인 역할 예시:** +```yaml +role: "Senior UX Researcher specializing in user interview analysis" +role: "Full-Stack Software Architect with expertise in distributed systems" +role: "Corporate Communications Director specializing in crisis management" +``` + +#### 목표: 에이전트의 목적과 동기 + +목표는 에이전트의 노력을 이끌고 의사 결정 과정을 형성합니다. 효과적인 목표는 다음과 같아야 합니다: + +- **명확하고 결과 중심적이어야 함**: 에이전트가 달성하려는 것이 무엇인지 정의합니다. +- **품질 기준을 강조해야 함**: 작업의 품질에 대한 기대치를 포함합니다. +- **성공 기준을 통합해야 함**: "좋음"이 무엇인지 에이전트가 이해할 수 있도록 도와줍니다. + +**효과적인 목표의 예시:** +```yaml +goal: "Uncover actionable user insights by analyzing interview data and identifying recurring patterns, unmet needs, and improvement opportunities" +goal: "Design robust, scalable system architectures that balance performance, maintainability, and cost-effectiveness" +goal: "Craft clear, empathetic crisis communications that address stakeholder concerns while protecting organizational reputation" +``` + +#### 배경 이야기: 에이전트의 경험과 관점 + +배경 이야기는 에이전트에게 깊이를 부여하며, 문제를 해결하고 타인과 상호작용하는 방식에 영향을 미칩니다. 좋은 배경 이야기는 다음과 같습니다: + +- **전문성과 경험을 확립**: 에이전트가 어떻게 자신의 기술을 습득했는지 설명합니다. +- **업무 스타일 및 가치를 정의**: 에이전트가 일에 어떻게 접근하는지 설명합니다. +- **통합된 페르소나 생성**: 배경 이야기의 모든 요소가 역할과 목표에 부합하는지 확인합니다. + +**효과적인 배경 이야기 예시:** +```yaml +backstory: "You have spent 15 years conducting and analyzing user research for top tech companies. You have a talent for reading between the lines and identifying patterns that others miss. You believe that good UX is invisible and that the best insights come from listening to what users don't say as much as what they do say." + +backstory: "With 20+ years of experience building distributed systems at scale, you've developed a pragmatic approach to software architecture. You've seen both successful and failed systems and have learned valuable lessons from each. You balance theoretical best practices with practical constraints and always consider the maintenance and operational aspects of your designs." + +backstory: "As a seasoned communications professional who has guided multiple organizations through high-profile crises, you understand the importance of transparency, speed, and empathy in crisis response. You have a methodical approach to crafting messages that address concerns while maintaining organizational credibility." +``` + +### 2. 전문가가 일반가보다 우수함 + +에이전트는 일반적인 역할보다 전문화된 역할을 부여할 때 훨씬 더 우수한 성능을 보입니다. 고도로 집중된 에이전트는 더 정확하고 관련성 높은 결과물을 제공합니다: + +**일반적 (효과 적음):** +```yaml +role: "Writer" +``` + +**전문화 (효과 좋음):** +```yaml +role: "Technical Blog Writer specializing in explaining complex AI concepts to non-technical audiences" +``` + +**전문가의 이점:** +- 기대되는 출력물에 대한 더 명확한 이해 +- 더 일관된 성과 +- 특정 작업과의 더 나은 정렬 +- 도메인별 판단능력 향상 + +### 3. 전문화와 다재다능성의 균형 + +효과적인 에이전트는 전문성(한 가지를 매우 잘하는 것)과 다재다능성(다양한 상황에 적응할 수 있는 것) 사이에서 적절한 균형을 이룹니다: + +- **역할에 전문화하고, 적용에는 다재다능하게**: 여러 맥락에서 적용할 수 있는 전문 기술을 가진 에이전트를 만드세요 +- **지나치게 좁은 정의는 피하기**: 에이전트가 자신이 전문으로 하는 영역 내에서 다양한 변형을 처리할 수 있도록 하세요 +- **협업 맥락을 고려하기**: 함께 일하게 될 다른 에이전트들과 전문 분야가 상호 보완될 수 있도록 에이전트를 설계하세요 + +### 4. 적절한 전문성 수준 설정 + +에이전트에게 할당하는 전문성 수준은 작업 접근 방식에 영향을 미칩니다: + +- **초급 에이전트**: 단순한 작업, 브레인스토밍, 초기 초안에 적합 +- **중급 에이전트**: 대부분의 표준 작업에서 신뢰성 있는 실행에 적합 +- **전문가 에이전트**: 깊이와 세밀함이 요구되는 복잡하고 전문적인 작업에 최적 +- **월드 클래스 에이전트**: 예외적인 품질이 필요한 중요한 작업에 할당 + +작업의 복잡성과 품질 요구 사항에 따라 적합한 전문성 수준을 선택하세요. 대부분의 협업 crew에서는 다양한 전문성 수준이 어우러지는 것이 가장 효과적이며, 핵심 전문 기능에는 더 높은 전문성을 배정하는 것이 좋습니다. + +## 실제 예시: 적용 전과 적용 후 + +이러한 모범 사례를 적용하기 전과 후의 agent 정의 예시를 살펴보겠습니다: + +### 예시 1: 콘텐츠 제작 에이전트 + +**이전:** +```yaml +role: "Writer" +goal: "Write good content" +backstory: "You are a writer who creates content for websites." +``` + +**이후:** +```yaml +role: "B2B Technology Content Strategist" +goal: "Create compelling, technically accurate content that explains complex topics in accessible language while driving reader engagement and supporting business objectives" +backstory: "You have spent a decade creating content for leading technology companies, specializing in translating technical concepts for business audiences. You excel at research, interviewing subject matter experts, and structuring information for maximum clarity and impact. You believe that the best B2B content educates first and sells second, building trust through genuine expertise rather than marketing hype." +``` + +### 예시 2: 리서치 에이전트 + +**변경 전:** +```yaml +role: "Researcher" +goal: "Find information" +backstory: "You are good at finding information online." +``` + +**변경 후:** +```yaml +role: "Academic Research Specialist in Emerging Technologies" +goal: "Discover and synthesize cutting-edge research, identifying key trends, methodologies, and findings while evaluating the quality and reliability of sources" +backstory: "With a background in both computer science and library science, you've mastered the art of digital research. You've worked with research teams at prestigious universities and know how to navigate academic databases, evaluate research quality, and synthesize findings across disciplines. You're methodical in your approach, always cross-referencing information and tracing claims to primary sources before drawing conclusions." +``` + +## 에이전트를 위한 효과적인 작업 설계하기 + +에이전트 설계도 중요하지만, 작업 설계는 성공적인 실행을 위해 매우 중요합니다. 에이전트가 성공할 수 있도록 작업을 설계할 때 참고할 수 있는 모범 사례는 다음과 같습니다: + +### 효과적인 작업의 구조 + +잘 설계된 작업은 서로 다른 목적을 가진 두 가지 주요 구성 요소를 가지고 있습니다: + +#### 작업 설명: 프로세스 +설명은 무엇을 어떻게 해야 하는지에 초점을 맞춰야 하며, 아래를 포함해야 합니다: +- 실행을 위한 상세 지침 +- 맥락 및 배경 정보 +- 범위 및 제약 조건 +- 따라야 할 프로세스 단계 + +#### 예상 산출물: 결과물 +예상 산출물은 최종 결과가 어떻게 보여야 하는지 정의해야 합니다: +- 형식 명세(마크다운, JSON 등) +- 구조 요구사항 +- 품질 기준 +- 좋은 결과물의 예시(가능할 경우) + +### 작업 설계 모범 사례 + +#### 1. 단일 목적, 단일 산출물 +작업은 하나의 명확한 목표에 집중할 때 가장 좋은 성과를 냅니다: + +**나쁜 예시(너무 광범위함):** +```yaml +task_description: "Research market trends, analyze the data, and create a visualization." +``` + +**좋은 예시(집중됨):** +```yaml +# Task 1 +research_task: + description: "Research the top 5 market trends in the AI industry for 2024." + expected_output: "A markdown list of the 5 trends with supporting evidence." + +# Task 2 +analysis_task: + description: "Analyze the identified trends to determine potential business impacts." + expected_output: "A structured analysis with impact ratings (High/Medium/Low)." + +# Task 3 +visualization_task: + description: "Create a visual representation of the analyzed trends." + expected_output: "A description of a chart showing trends and their impact ratings." +``` + +#### 2. 입력 및 출력 명시 + +항상 작업에 사용할 입력값과 출력이 어떻게 보여야 하는지 명확하게 지정하세요: + +**예시:** +```yaml +analysis_task: + description: > + Analyze the customer feedback data from the CSV file. + Focus on identifying recurring themes related to product usability. + Consider sentiment and frequency when determining importance. + expected_output: > + A markdown report with the following sections: + 1. Executive summary (3-5 bullet points) + 2. Top 3 usability issues with supporting data + 3. Recommendations for improvement +``` + +#### 3. 목적 및 맥락 포함 +작업이 왜 중요한지, 더 큰 워크플로우에서 어떻게 맞물리는지 설명하세요: + +**예시:** +```yaml +competitor_analysis_task: + description: > + Analyze our three main competitors' pricing strategies. + This analysis will inform our upcoming pricing model revision. + Focus on identifying patterns in how they price premium features + and how they structure their tiered offerings. +``` + +#### 4. 구조화된 출력 도구 사용하기 +기계가 읽을 수 있는 출력을 위해서, 포맷을 명확히 지정하세요: + +**예시:** +```yaml +data_extraction_task: + description: "Extract key metrics from the quarterly report." + expected_output: "JSON object with the following keys: revenue, growth_rate, customer_acquisition_cost, and retention_rate." +``` + +## 피해야 할 일반적인 실수 + +실제 구현에서 얻은 교훈을 바탕으로, 에이전트 및 태스크 설계에서 가장 흔한 실수는 다음과 같습니다: + +### 1. 불명확한 작업 지시 + +**문제:** 작업에 충분한 세부 정보가 없어 에이전트가 효과적으로 실행하기 어렵습니다. + +**잘못 설계된 예시:** +```yaml +research_task: + description: "Research AI trends." + expected_output: "A report on AI trends." +``` + +**개선된 버전:** +```yaml +research_task: + description: > + Research the top emerging AI trends for 2024 with a focus on: + 1. Enterprise adoption patterns + 2. Technical breakthroughs in the past 6 months + 3. Regulatory developments affecting implementation + + For each trend, identify key companies, technologies, and potential business impacts. + expected_output: > + A comprehensive markdown report with: + - Executive summary (5 bullet points) + - 5-7 major trends with supporting evidence + - For each trend: definition, examples, and business implications + - References to authoritative sources +``` + +### 2. 너무 많은 작업을 시도하는 "God Tasks" + +**문제:** 여러 복잡한 작업을 하나의 지시 세트로 결합하는 태스크. + +**잘못된 설계 예시:** +```yaml +comprehensive_task: + description: "Research market trends, analyze competitor strategies, create a marketing plan, and design a launch timeline." +``` + +**개선된 버전:** +이 작업을 순차적이고 집중된 태스크로 분리하세요: +```yaml +# Task 1: Research +market_research_task: + description: "Research current market trends in the SaaS project management space." + expected_output: "A markdown summary of key market trends." + +# Task 2: Competitive Analysis +competitor_analysis_task: + description: "Analyze strategies of the top 3 competitors based on the market research." + expected_output: "A comparison table of competitor strategies." + context: [market_research_task] + +# Continue with additional focused tasks... +``` + +### 3. 설명과 기대 출력 불일치 + +**문제:** 작업 설명에서 요구하는 내용과 기대 출력이 서로 다릅니다. + +**설계가 미흡한 예시:** +```yaml +analysis_task: + description: "Analyze customer feedback to find areas of improvement." + expected_output: "A marketing plan for the next quarter." +``` + +**개선된 버전:** +```yaml +analysis_task: + description: "Analyze customer feedback to identify the top 3 areas for product improvement." + expected_output: "A report listing the 3 priority improvement areas with supporting customer quotes and data points." +``` + +### 4. 당신이 직접 프로세스를 이해하지 못함 + +**문제:** 당신이 완전히 이해하지 못하는 작업을 에이전트에게 수행하도록 요청함. + +**해결책:** +1. 먼저 직접 작업을 수동으로 수행해보세요 +2. 프로세스, 의사결정 지점, 정보 출처를 문서화하세요 +3. 이 문서를 작업 설명의 기초로 사용하세요 + +### 5. 계층 구조의 조기 사용 + +**문제:** 순차적인 프로세스만으로도 충분한 경우에 불필요하게 복잡한 에이전트 계층 구조를 만드는 것. + +**해결 방법:** 우선 순차적 프로세스부터 시작하고, 워크플로우의 복잡성이 정말로 필요할 때만 계층적 모델로 전환하세요. + +### 6. 모호하거나 일반적인 에이전트 정의 + +**문제:** 일반적인 에이전트 정의는 일반적인 결과로 이어집니다. + +**잘못된 설계 예시:** +```yaml +agent: + role: "Business Analyst" + goal: "Analyze business data" + backstory: "You are good at business analysis." +``` + +**개선된 버전:** +```yaml +agent: + role: "SaaS Metrics Specialist focusing on growth-stage startups" + goal: "Identify actionable insights from business data that can directly impact customer retention and revenue growth" + backstory: "With 10+ years analyzing SaaS business models, you've developed a keen eye for the metrics that truly matter for sustainable growth. You've helped numerous companies identify the leverage points that turned around their business trajectory. You believe in connecting data to specific, actionable recommendations rather than general observations." +``` + +## 고급 에이전트 설계 전략 + +### 협업을 위한 설계 + +여러 agent가 crew 내에서 함께 작업할 때 다음 사항을 고려하십시오: + +- **상호 보완적인 스킬**: 각기 다르지만 상호 보완되는 능력을 가진 agent를 설계하세요. +- **업무 인계 시점**: agent 간에 작업이 어떻게 전달될지 명확한 인터페이스를 정의하세요. +- **건설적인 긴장감**: 때때로 약간씩 다른 관점을 가진 agent를 만들면 생산적인 대화를 통해 더 나은 결과를 이끌어낼 수 있습니다. + +예를 들어, 콘텐츠 제작 crew는 다음과 같이 구성될 수 있습니다: + +```yaml +# Research Agent +role: "Research Specialist for technical topics" +goal: "Gather comprehensive, accurate information from authoritative sources" +backstory: "You are a meticulous researcher with a background in library science..." + +# Writer Agent +role: "Technical Content Writer" +goal: "Transform research into engaging, clear content that educates and informs" +backstory: "You are an experienced writer who excels at explaining complex concepts..." + +# Editor Agent +role: "Content Quality Editor" +goal: "Ensure content is accurate, well-structured, and polished while maintaining consistency" +backstory: "With years of experience in publishing, you have a keen eye for detail..." +``` + +### 전문화된 도구 사용자 생성 + +일부 agent는 특정 도구를 효과적으로 활용하도록 특별히 설계될 수 있습니다: + +```yaml +role: "Data Analysis Specialist" +goal: "Derive meaningful insights from complex datasets through statistical analysis" +backstory: "With a background in data science, you excel at working with structured and unstructured data..." +tools: [PythonREPLTool, DataVisualizationTool, CSVAnalysisTool] +``` + +### LLM 기능에 맞춘 에이전트 맞춤화 + +다양한 LLM은 서로 다른 강점을 가지고 있습니다. 이러한 기능을 염두에 두고 에이전트를 설계하세요: + +```yaml +# For complex reasoning tasks +analyst: + role: "Data Insights Analyst" + goal: "..." + backstory: "..." + llm: openai/gpt-4o + +# For creative content +writer: + role: "Creative Content Writer" + goal: "..." + backstory: "..." + llm: anthropic/claude-3-opus +``` + +## 에이전트 설계 테스트 및 반복 + +에이전트 설계는 종종 반복적인 과정입니다. 다음은 실용적인 접근 방식입니다: + +1. **프로토타입으로 시작하기**: 초기 에이전트 정의 생성 +2. **샘플 작업으로 테스트하기**: 대표적인 작업에서 성능 평가 +3. **출력물 분석**: 강점과 약점 파악 +4. **정의 수정**: 관찰에 따라 역할, 목표, 백스토리 조정 +5. **협업 테스트**: 에이전트가 crew 환경에서 어떻게 작동하는지 평가 + +## 결론 + +효과적인 agent를 만드는 것은 예술이자 과학입니다. 여러분의 특정 요구에 맞춘 역할, 목표, 그리고 backstory를 신중하게 정의하고, 잘 설계된 task와 결합함으로써 뛰어난 결과를 만들어내는 전문화된 AI 협업자를 만들 수 있습니다. + +agent와 task의 설계는 반복적인 과정임을 기억하세요. 이러한 모범 사례로 시작하여 agent가 실제로 동작하는 모습을 관찰하고, 배운 점을 바탕으로 접근 방식을 개선하세요. 그리고 항상 80/20 법칙을 명심하세요. agent로부터 최고의 결과를 얻기 위해서는 명확하고 집중된 task를 만드는 데 대부분의 노력을 집중하는 것이 중요합니다. + + +축하합니다! 이제 효과적인 agent 설계의 원칙과 실천법을 이해하셨습니다. 이 기술들을 적용하여 강력하고 전문화된 agent들이 복잡한 task를 매끄럽게 협력하여 완수할 수 있도록 만드세요. + + +## 다음 단계 + +- 특정 사용 사례에 맞는 다양한 agent 구성을 실험해 보세요 +- [첫 crew 만들기](/ko/guides/crews/first-crew)에 대해 배우며 agent들이 어떻게 함께 작동하는지 확인해 보세요 +- 더 발전된 오케스트레이션을 위해 [CrewAI Flows](/ko/guides/flows/first-flow)를 탐색해 보세요 \ No newline at end of file diff --git a/docs/v1.15.13/ko/guides/coding-tools/agents-md.mdx b/docs/v1.15.13/ko/guides/coding-tools/agents-md.mdx new file mode 100644 index 0000000000..d95184ac9f --- /dev/null +++ b/docs/v1.15.13/ko/guides/coding-tools/agents-md.mdx @@ -0,0 +1,61 @@ +--- +title: 코딩 도구 +description: AGENTS.md를 사용하여 CrewAI 프로젝트 전반에서 코딩 에이전트와 IDE를 안내합니다. +icon: terminal +mode: "wide" +--- + +## AGENTS.md를 사용하는 이유 + +`AGENTS.md`는 가벼운 저장소 로컬 지침 파일로, 코딩 에이전트에게 일관되고 프로젝트별 안내를 제공합니다. 프로젝트 루트에 배치하고 어시스턴트가 작업하는 방식(컨벤션, 명령어, 아키텍처 노트, 가드레일)에 대한 신뢰할 수 있는 소스로 활용하세요. + +## CLI로 프로젝트 생성 + +CrewAI CLI를 사용하여 프로젝트를 스캐폴딩하면, `AGENTS.md`가 루트에 자동으로 추가됩니다. + +```bash +# Crew +crewai create crew my_crew + +# Flow +crewai create flow my_flow + +# Tool repository +crewai tool create my_tool +``` + +## 도구 설정: 어시스턴트에 AGENTS.md 연결 + +### Codex + +Codex는 저장소에 배치된 `AGENTS.md` 파일로 안내할 수 있습니다. 컨벤션, 명령어, 워크플로우 기대치 등 지속적인 프로젝트 컨텍스트를 제공하는 데 사용하세요. + +### Claude Code + +Claude Code는 프로젝트 메모리를 `CLAUDE.md`에 저장합니다. `/init`으로 부트스트랩하고 `/memory`로 편집할 수 있습니다. Claude Code는 `CLAUDE.md` 내에서 임포트도 지원하므로, `@AGENTS.md`와 같은 한 줄을 추가하여 공유 지침을 중복 없이 가져올 수 있습니다. + +간단하게 다음과 같이 사용할 수 있습니다: + +```bash +mv AGENTS.md CLAUDE.md +``` + +### Gemini CLI와 Google Antigravity + +Gemini CLI와 Antigravity는 저장소 루트 및 상위 디렉토리에서 프로젝트 컨텍스트 파일(기본값: `GEMINI.md`)을 로드합니다. Gemini CLI 설정에서 `context.fileName`을 설정하여 `AGENTS.md`를 대신(또는 추가로) 읽도록 구성할 수 있습니다. 예를 들어, `AGENTS.md`만 설정하거나 각 도구의 형식을 유지하고 싶다면 `AGENTS.md`와 `GEMINI.md`를 모두 포함할 수 있습니다. + +간단하게 다음과 같이 사용할 수 있습니다: + +```bash +mv AGENTS.md GEMINI.md +``` + +### Cursor + +Cursor는 `AGENTS.md`를 프로젝트 지침 파일로 지원합니다. 프로젝트 루트에 배치하여 Cursor의 코딩 어시스턴트에 안내를 제공하세요. + +### Windsurf + +Claude Code는 Windsurf와의 공식 통합을 제공합니다. Windsurf 내에서 Claude Code를 사용하는 경우, 위의 Claude Code 안내를 따르고 `CLAUDE.md`에서 `AGENTS.md`를 임포트하세요. + +Windsurf의 네이티브 어시스턴트를 사용하는 경우, 프로젝트 규칙 또는 지침 기능(사용 가능한 경우)을 구성하여 `AGENTS.md`에서 읽거나 내용을 직접 붙여넣으세요. diff --git a/docs/v1.15.13/ko/guides/coding-tools/build-with-ai.mdx b/docs/v1.15.13/ko/guides/coding-tools/build-with-ai.mdx new file mode 100644 index 0000000000..0d575b645f --- /dev/null +++ b/docs/v1.15.13/ko/guides/coding-tools/build-with-ai.mdx @@ -0,0 +1,214 @@ +--- +title: "AI와 함께 빌드하기" +description: "CrewAI로 빌드·배포·확장하는 데 필요한 모든 것 — 스킬, 기계가 읽을 수 있는 문서, 배포, 엔터프라이즈 기능을 AI 코딩 에이전트용으로 정리했습니다." +icon: robot +mode: "wide" +--- + +# AI와 함께 빌드하기 + +CrewAI는 AI 네이티브입니다. 이 페이지는 Claude Code, Codex, Cursor, Gemini CLI 등 개발자가 crew와 flow를 배포하도록 돕는 코딩 에이전트가 CrewAI로 빌드할 때 필요한 내용을 한곳에 모았습니다. + +### 지원 코딩 에이전트 + + + + + + + + + + + 이 페이지는 사람과 AI 어시스턴트 모두를 위해 작성되었습니다. 코딩 에이전트라면 CrewAI 맥락은 **Skills**부터, 전체 문서 접근은 **llms.txt**를 사용하세요. + + +--- + +## 1. Skills — 에이전트에게 CrewAI 가르치기 + +**Skills**는 코딩 에이전트에게 Flow 스캐폴딩, Crew 구성, 도구 사용, 프레임워크 관례 등 CrewAI에 대한 깊은 지식을 담은 지침 묶음입니다. + + + + Anthropic + CrewAI 스킬은 **Claude Code 플러그인 마켓플레이스**에서 제공됩니다. AI 네이티브 기업들이 쓰는 것과 같은 배포 채널입니다. + ```shell + /plugin marketplace add crewAIInc/skills + /plugin install crewai-skills@crewai-plugins + /reload-plugins + ``` + + CrewAI와 관련된 질문을 하면 다음 네 가지 스킬이 자동으로 활성화됩니다. + + | 스킬 | 실행 시점 | + |------|-------------| + | `getting-started` | 새 프로젝트 스캐폴딩, `LLM.call()` / `Agent` / `Crew` / `Flow` 선택, `crew.jsonc` / `main.py` 연결 | + | `design-agent` | 에이전트 구성 — 역할, 목표, 배경 이야기, 도구, LLM, 메모리, 가드레일 | + | `design-task` | 태스크 설명, 의존성, 구조화된 출력(`output_pydantic`, `output_json`), 사람 검토 | + | `ask-docs` | 최신 API 정보를 위해 [CrewAI 문서 MCP 서버](https://docs.crewai.com/mcp) 조회 | + + + Claude Code, Codex, Cursor, Gemini CLI 등 모든 코딩 에이전트에서 사용할 수 있습니다. + ```shell + npx skills add crewaiinc/skills + ``` + [skills.sh 레지스트리](https://skills.sh/crewaiinc/skills)에서 가져옵니다. + + + + + + 위 방법 중 하나를 사용하세요 — Claude Code 플러그인 마켓플레이스 또는 `npx skills add`. 둘 다 공식 [crewAIInc/skills](https://github.com/crewAIInc/skills) 팩을 설치합니다. + + + 스킬 팩이 에이전트에게 알려 주는 내용: + - **Flow** — 상태ful 앱, 단계, crew 킥오프 + - **Crew 및 에이전트** — JSON-first 패턴(`crew.jsonc`, `agents/*.jsonc`), 역할, 태스크, 위임 + - **도구 및 통합** — 검색, API, MCP 서버, 일반적인 CrewAI 도구 + - **프로젝트 레이아웃** — CLI 스캐폴드와 저장소 관례 + - **최신 패턴** — 현재 CrewAI 문서와 모범 사례 반영 + + + 매 세션마다 프레임워크를 다시 설명하지 않아도 에이전트가 CrewAI 프로젝트를 스캐폴딩하고 빌드할 수 있습니다. + + + + + + CrewAI 에이전트에서 스킬이 동작하는 방식 — 주입, 활성화, 패턴. + + + crewAIInc/skills 팩 개요와 포함 내용. + + + Claude Code, Codex, Cursor, Gemini CLI용 AGENTS.md 설정. + + + 공식 목록 — 스킬, 설치 통계, 감사 정보. + + + +--- + +## 2. llms.txt — 기계가 읽을 수 있는 문서 + +CrewAI는 AI 어시스턴트가 전체 문서에 기계가 읽을 수 있는 형태로 바로 접근할 수 있도록 `llms.txt` 파일을 제공합니다. + +``` +https://docs.crewai.com/llms.txt +``` + + + + [`llms.txt`](https://llmstxt.org/)는 문서를 대규모 언어 모델이 소비하기 쉽게 만드는 새로운 표준입니다. HTML을 스크래핑하는 대신, 필요한 내용이 담긴 하나의 구조화된 텍스트 파일을 가져올 수 있습니다. + + CrewAI의 `llms.txt`는 **이미 제공 중**이며, 에이전트가 바로 사용할 수 있습니다. + + + CrewAI 참고 문서가 필요할 때 코딩 에이전트에 URL을 알려 주세요. + + ``` + Fetch https://docs.crewai.com/llms.txt for CrewAI documentation. + ``` + + Claude Code, Cursor 등 많은 코딩 에이전트가 URL을 직접 가져올 수 있습니다. 파일에는 CrewAI 개념, API, 가이드를 아우르는 구조화된 문서가 포함되어 있습니다. + + + - **스크래핑 불필요** — 한 번의 요청으로 깔끔한 구조화 콘텐츠 + - **항상 최신** — docs.crewai.com에서 직접 제공 + - **LLM에 최적화** — 브라우저가 아니라 컨텍스트 윈도우에 맞게 포맷 + - **스킬과 상호 보완** — 스킬은 패턴을, llms.txt는 참조를 제공 + + + +--- + +## 3. 엔터프라이즈에 배포 + +로컬 crew를 몇 분 안에 **CrewAI AMP**(Agent Management Platform) 프로덕션으로 가져가세요. + + + + crew 또는 flow를 스캐폴딩하고 테스트합니다. + ```bash + crewai create crew my_crew + cd my_crew + crewai run + ``` + + + 프로젝트 구조가 준비되었는지 확인합니다. + ```bash + crewai deploy --prepare + ``` + 구조와 요구 사항은 [준비 가이드](https://docs-platform.crewai.com/platform/ko/guides/prepare-for-deployment)를 참고하세요. + + + CrewAI AMP 플랫폼으로 푸시합니다. + ```bash + crewai deploy + ``` + [GitHub 연동](https://docs-platform.crewai.com/platform/ko/guides/deploy-to-amp) 또는 [Crew Studio](https://docs-platform.crewai.com/platform/ko/guides/enable-crew-studio)로도 배포할 수 있습니다. + + + 배포된 crew는 REST API 엔드포인트를 받습니다. 모든 애플리케이션에 통합할 수 있습니다. + ```bash + curl -X POST https://app.crewai.com/api/v1/crews//kickoff \ + -H "Authorization: Bearer $CREWAI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"inputs": {"topic": "AI agents"}}' + ``` + + + + + + 전체 배포 가이드 — CLI, GitHub, Crew Studio 방법. + + + 플랫폼 개요 — 프로덕션 crew에 AMP가 제공하는 것. + + + +--- + +## 4. 엔터프라이즈 기능 + +CrewAI AMP는 프로덕션 팀을 위해 만들어졌습니다. 배포 외에 제공되는 것은 다음과 같습니다. + + + + 모든 crew 실행에 대한 상세 실행 추적, 로그, 성능 지표. 에이전트 결정, 도구 호출, 태스크 완료를 실시간으로 모니터링합니다. + + + 시각적으로 crew를 만들고, 맞춤 설정하고, 배포하는 노코드/로코드 인터페이스 — 코드로 보내거나 바로 배포할 수 있습니다. + + + crew 실행에서 실시간 이벤트를 시스템으로 스트리밍합니다. Slack, Zapier 등 웹훅 소비자와 연동할 수 있습니다. + + + SSO, RBAC, 조직 단위 제어. 팀 전체에서 crew 생성·배포·접근 권한을 관리합니다. + + + 조직 전체에 맞춤 도구를 게시하고 공유합니다. 레지스트리에서 커뮤니티 도구를 설치합니다. + + + 자체 인프라에서 CrewAI AMP를 실행합니다. 데이터 상주와 규정 준수 제어와 함께 플랫폼 전체 기능을 사용할 수 있습니다. + + + + + + AI 에이전트 워크플로를 프로토타입에서 프로덕션으로 옮겨야 하는 팀을 위한 제품입니다. 관측 가능성, 접근 제어, 확장 가능한 인프라를 제공합니다. 스타트업이든 대기업이든 운영 복잡도는 AMP가 맡고, 에이전트 구축에 집중할 수 있습니다. + + + - **클라우드 (app.crewai.com)** — CrewAI가 관리, 프로덕션까지 가장 빠른 경로 + - **Factory(셀프 호스팅)** — 데이터 통제를 위해 자체 인프라에서 실행 + - **하이브리드** — 민감도에 따라 클라우드와 셀프 호스팅을 혼합 + + + + + 가입하고 첫 crew를 프로덕션에 배포해 보세요. + diff --git a/docs/v1.15.13/ko/guides/concepts/evaluating-use-cases.mdx b/docs/v1.15.13/ko/guides/concepts/evaluating-use-cases.mdx new file mode 100644 index 0000000000..ff9a3c3353 --- /dev/null +++ b/docs/v1.15.13/ko/guides/concepts/evaluating-use-cases.mdx @@ -0,0 +1,504 @@ +--- +title: CrewAI 사용 사례 평가 +description: AI 애플리케이션 요구 사항을 평가하고 복잡성과 정밀도 요구 사항에 따라 Crews와 Flows 중 올바른 접근 방식을 선택하는 방법을 알아보세요. +icon: scale-balanced +mode: "wide" +--- + +## 의사결정 프레임워크 이해하기 + +CrewAI로 AI 애플리케이션을 구축할 때 가장 중요한 결정 중 하나는 특정 사용 사례에 적합한 방식을 선택하는 것입니다. Crew를 사용할까요? Flow를 사용할까요? 아니면 둘의 조합을 사용할까요? 이 가이드는 요구 사항을 평가하고 정보에 기반한 아키텍처 결정을 내리는 데 도움이 됩니다. + +이 결정의 핵심은 애플리케이션에서의 **복잡성**과 **정밀성**의 관계를 이해하는 것입니다: + + + 복잡성 vs. 정밀성 매트릭스 + + +이 매트릭스를 통해 다양한 방식이 복잡성과 정밀성에 대한 요구 사항과 어떻게 일치하는지 시각적으로 확인할 수 있습니다. 각 사분면이 의미하는 바와 그것이 아키텍처 선택에 어떻게 도움이 되는지 함께 살펴보겠습니다. + +## 복잡성-정밀도 행렬 설명 + +### 복잡성이란 무엇인가? + +CrewAI 애플리케이션의 맥락에서 **복잡성**은 다음을 의미합니다: + +- 요구되는 뚜렷한 단계 또는 작업 수 +- 수행해야 할 작업의 다양성 +- 서로 다른 구성 요소 간의 상호 의존성 +- 조건부 로직과 분기의 필요성 +- 전체 워크플로우의 정교함 + +### 정밀성이란 무엇인가? + +**정밀성**은 이 맥락에서 다음을 의미합니다: + +- 최종 결과물에 요구되는 정확성 +- 구조화되고 예측 가능한 결과의 필요성 +- 재현성의 중요성 +- 각 단계에 대한 통제 수준 +- 출력의 변동 허용치 + +### 네 가지 사분면 + +#### 1. 낮은 복잡도, 낮은 정밀도 + +**특징:** +- 단순하고 직관적인 작업 +- 출력 결과의 일부 변형 허용 +- 제한된 단계 수 +- 창의적이거나 탐색적인 응용 + +**권장 접근법:** 최소한의 에이전트를 가진 Simple Crews + +**예시 사용 사례:** +- 기본 콘텐츠 생성 +- 아이디어 브레인스토밍 +- 간단한 요약 작업 +- 창의적 글쓰기 보조 + +#### 2. 낮은 복잡성, 높은 정밀도 + +**특징:** +- 정확하고 구조화된 결과물이 요구되는 단순한 워크플로우 +- 재현 가능한 결과가 필요한 경우 +- 단계는 제한적이지만, 높은 정확도가 요구됨 +- 주로 데이터 처리 또는 변환이 포함됨 + +**권장 방식:** 직접적인 LLM 호출이나 구조화된 출력이 있는 간단한 Crew 사용 + +**예시 활용 사례:** +- 데이터 추출 및 변환 +- 양식 작성 및 검증 +- 구조화된 콘텐츠 생성(JSON, XML) +- 단순 분류 작업 + +#### 3. 높은 복잡성, 낮은 정밀도 + +**특징:** +- 여러 단계로 이루어진 다단계 프로세스 +- 창의적이거나 탐색적인 출력물 +- 구성 요소 간의 복잡한 상호작용 +- 최종 결과의 변동성 허용 + +**권장 접근 방식:** 여러 전문화된 agent가 포함된 Complex Crew + +**예시 사용 사례:** +- 연구 및 분석 +- 콘텐츠 생성 파이프라인 +- 탐색적 데이터 분석 +- 창의적 문제 해결 + +#### 4. 높은 복잡성, 높은 정밀도 + +**특징:** +- 구조화된 산출물이 요구되는 복잡한 워크플로 +- 엄격한 정확성 요구사항을 가진 여러 상호 의존적인 단계 +- 정교한 처리와 정밀한 결과 모두 필요 +- 종종 임무에 중요한 애플리케이션 + +**권장 접근 방식:** 검증 단계를 포함한 여러 Crew를 오케스트레이션하는 Flows + +**예시 사용 사례:** +- 엔터프라이즈 의사결정 지원 시스템 +- 복잡한 데이터 처리 파이프라인 +- 다단계 문서 처리 +- 규제 산업 애플리케이션 + +## 크루와 플로우 중에서 선택하기 + +### Crews를 선택해야 할 때 + +Crews는 다음과 같은 경우에 이상적입니다: + +1. **협업 지능이 필요할 때** - 서로 다른 전문성을 가진 여러 agent들이 함께 작업해야 할 때 +2. **문제가 창발적 사고를 요구할 때** - 다양한 관점과 접근 방식에서의 해결책이 이득이 될 때 +3. **작업이 주로 창의적이거나 분석적일 때** - 작업이 리서치, 콘텐츠 제작, 분석을 포함할 때 +4. **엄격한 구조보다는 적응력을 중시할 때** - agent의 자율성이 workflow에 도움이 될 때 +5. **출력 형식이 다소 유연할 수 있을 때** - 출력 구조에 약간의 변동이 허용될 때 + +```python +# Example: Research Crew for market analysis +from crewai import Agent, Crew, Process, Task + +# Create specialized agents +researcher = Agent( + role="Market Research Specialist", + goal="Find comprehensive market data on emerging technologies", + backstory="You are an expert at discovering market trends and gathering data." +) + +analyst = Agent( + role="Market Analyst", + goal="Analyze market data and identify key opportunities", + backstory="You excel at interpreting market data and spotting valuable insights." +) + +# Define their tasks +research_task = Task( + description="Research the current market landscape for AI-powered healthcare solutions", + expected_output="Comprehensive market data including key players, market size, and growth trends", + agent=researcher +) + +analysis_task = Task( + description="Analyze the market data and identify the top 3 investment opportunities", + expected_output="Analysis report with 3 recommended investment opportunities and rationale", + agent=analyst, + context=[research_task] +) + +# Create the crew +market_analysis_crew = Crew( + agents=[researcher, analyst], + tasks=[research_task, analysis_task], + process=Process.sequential, + verbose=True +) + +# Run the crew +result = market_analysis_crew.kickoff() +``` + +### 플로우를 선택해야 할 때 + +플로우는 다음과 같은 경우에 이상적입니다: + +1. **실행에 대한 정밀한 제어가 필요할 때** - 워크플로우에 정확한 순서 지정과 상태 관리가 필요한 경우 +2. **애플리케이션에 복잡한 상태 요구사항이 있을 때** - 여러 단계에 걸쳐 상태를 유지하고 변환해야 하는 경우 +3. **구조화되고 예측 가능한 출력이 필요할 때** - 애플리케이션에서 일관되고 포맷된 결과가 필요한 경우 +4. **워크플로우에 조건부 로직이 포함될 때** - 중간 결과에 따라 다른 경로를 선택해야 하는 경우 +5. **AI와 절차적 코드를 결합해야 할 때** - 솔루션에 AI 기능과 전통적인 프로그래밍이 모두 필요한 경우 + +```python +# Example: Customer Support Flow with structured processing +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel +from typing import List, Dict + +# Define structured state +class SupportTicketState(BaseModel): + ticket_id: str = "" + customer_name: str = "" + issue_description: str = "" + category: str = "" + priority: str = "medium" + resolution: str = "" + satisfaction_score: int = 0 + +class CustomerSupportFlow(Flow[SupportTicketState]): + @start() + def receive_ticket(self): + # In a real app, this might come from an API + self.state.ticket_id = "TKT-12345" + self.state.customer_name = "Alex Johnson" + self.state.issue_description = "Unable to access premium features after payment" + return "Ticket received" + + @listen(receive_ticket) + def categorize_ticket(self, _): + # Use a direct LLM call for categorization + from crewai import LLM + llm = LLM(model="openai/gpt-4o-mini") + + prompt = f""" + Categorize the following customer support issue into one of these categories: + - Billing + - Account Access + - Technical Issue + - Feature Request + - Other + + Issue: {self.state.issue_description} + + Return only the category name. + """ + + self.state.category = llm.call(prompt).strip() + return self.state.category + + @router(categorize_ticket) + def route_by_category(self, category): + # Route to different handlers based on category + return category.lower().replace(" ", "_") + + @listen("billing") + def handle_billing_issue(self): + # Handle billing-specific logic + self.state.priority = "high" + # More billing-specific processing... + return "Billing issue handled" + + @listen("account_access") + def handle_access_issue(self): + # Handle access-specific logic + self.state.priority = "high" + # More access-specific processing... + return "Access issue handled" + + # Additional category handlers... + + @listen("billing", "account_access", "technical_issue", "feature_request", "other") + def resolve_ticket(self, resolution_info): + # Final resolution step + self.state.resolution = f"Issue resolved: {resolution_info}" + return self.state.resolution + +# Run the flow +support_flow = CustomerSupportFlow() +result = support_flow.kickoff() +``` + +### 크루와 플로우를 결합해야 할 때 + +가장 정교한 애플리케이션은 종종 크루와 플로우를 결합할 때 이점을 얻습니다: + +1. **복잡한 다단계 프로세스** - 플로우를 사용해 전체 프로세스를 오케스트레이션하고, 크루를 통해 복잡한 하위 작업을 처리합니다. +2. **창의성과 구조가 모두 필요한 애플리케이션** - 창의적인 작업에는 크루를 사용하고, 구조적인 처리는 플로우로 처리합니다. +3. **엔터프라이즈급 AI 애플리케이션** - 플로우로 상태 및 프로세스 흐름을 관리하면서, 크루를 활용해 특화된 작업을 수행합니다. + +```python +# Example: Content Production Pipeline combining Crews and Flows +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel +from typing import List, Dict + +class ContentState(BaseModel): + topic: str = "" + target_audience: str = "" + content_type: str = "" + outline: Dict = {} + draft_content: str = "" + final_content: str = "" + seo_score: int = 0 + +class ContentProductionFlow(Flow[ContentState]): + @start() + def initialize_project(self): + # Set initial parameters + self.state.topic = "Sustainable Investing" + self.state.target_audience = "Millennial Investors" + self.state.content_type = "Blog Post" + return "Project initialized" + + @listen(initialize_project) + def create_outline(self, _): + # Use a research crew to create an outline + researcher = Agent( + role="Content Researcher", + goal=f"Research {self.state.topic} for {self.state.target_audience}", + backstory="You are an expert researcher with deep knowledge of content creation." + ) + + outliner = Agent( + role="Content Strategist", + goal=f"Create an engaging outline for a {self.state.content_type}", + backstory="You excel at structuring content for maximum engagement." + ) + + research_task = Task( + description=f"Research {self.state.topic} focusing on what would interest {self.state.target_audience}", + expected_output="Comprehensive research notes with key points and statistics", + agent=researcher + ) + + outline_task = Task( + description=f"Create an outline for a {self.state.content_type} about {self.state.topic}", + expected_output="Detailed content outline with sections and key points", + agent=outliner, + context=[research_task] + ) + + outline_crew = Crew( + agents=[researcher, outliner], + tasks=[research_task, outline_task], + process=Process.sequential, + verbose=True + ) + + # Run the crew and store the result + result = outline_crew.kickoff() + + # Parse the outline (in a real app, you might use a more robust parsing approach) + import json + try: + self.state.outline = json.loads(result.raw) + except: + # Fallback if not valid JSON + self.state.outline = {"sections": result.raw} + + return "Outline created" + + @listen(create_outline) + def write_content(self, _): + # Use a writing crew to create the content + writer = Agent( + role="Content Writer", + goal=f"Write engaging content for {self.state.target_audience}", + backstory="You are a skilled writer who creates compelling content." + ) + + editor = Agent( + role="Content Editor", + goal="Ensure content is polished, accurate, and engaging", + backstory="You have a keen eye for detail and a talent for improving content." + ) + + writing_task = Task( + description=f"Write a {self.state.content_type} about {self.state.topic} following this outline: {self.state.outline}", + expected_output="Complete draft content in markdown format", + agent=writer + ) + + editing_task = Task( + description="Edit and improve the draft content for clarity, engagement, and accuracy", + expected_output="Polished final content in markdown format", + agent=editor, + context=[writing_task] + ) + + writing_crew = Crew( + agents=[writer, editor], + tasks=[writing_task, editing_task], + process=Process.sequential, + verbose=True + ) + + # Run the crew and store the result + result = writing_crew.kickoff() + self.state.final_content = result.raw + + return "Content created" + + @listen(write_content) + def optimize_for_seo(self, _): + # Use a direct LLM call for SEO optimization + from crewai import LLM + llm = LLM(model="openai/gpt-4o-mini") + + prompt = f""" + Analyze this content for SEO effectiveness for the keyword "{self.state.topic}". + Rate it on a scale of 1-100 and provide 3 specific recommendations for improvement. + + Content: {self.state.final_content[:1000]}... (truncated for brevity) + + Format your response as JSON with the following structure: + {{ + "score": 85, + "recommendations": [ + "Recommendation 1", + "Recommendation 2", + "Recommendation 3" + ] + }} + """ + + seo_analysis = llm.call(prompt) + + # Parse the SEO analysis + import json + try: + analysis = json.loads(seo_analysis) + self.state.seo_score = analysis.get("score", 0) + return analysis + except: + self.state.seo_score = 50 + return {"score": 50, "recommendations": ["Unable to parse SEO analysis"]} + +# Run the flow +content_flow = ContentProductionFlow() +result = content_flow.kickoff() +``` + +## 실용적인 평가 프레임워크 + +특정 사용 사례에 맞는 올바른 접근 방식을 결정하려면 다음 단계별 평가 프레임워크를 따르세요: + +### 1단계: 복잡성 평가 + +아래와 같은 기준으로 애플리케이션의 복잡성을 1~10점 척도로 평가하세요: + +1. **단계 수**: 얼마나 많은 개별 작업이 필요한가요? + - 1-3단계: 낮은 복잡성 (1-3) + - 4-7단계: 중간 복잡성 (4-7) + - 8단계 이상: 높은 복잡성 (8-10) + +2. **상호 의존성**: 서로 다른 부분 간의 연결성은 어느 정도인가요? + - 의존성이 거의 없음: 낮은 복잡성 (1-3) + - 다소 의존성 있음: 중간 복잡성 (4-7) + - 복잡한 다중 의존성: 높은 복잡성 (8-10) + +3. **조건부 논리**: 얼마나 많은 분기 및 의사결정이 필요한가요? + - 선형 프로세스: 낮은 복잡성 (1-3) + - 분기가 일부 있음: 중간 복잡성 (4-7) + - 복잡한 결정 트리: 높은 복잡성 (8-10) + +4. **도메인 지식**: 요구되는 지식의 전문성은 어느 정도인가요? + - 일반적인 지식: 낮은 복잡성 (1-3) + - 일부 전문 지식 필요: 중간 복잡성 (4-7) + - 여러 도메인에 대한 깊은 전문성 필요: 높은 복잡성 (8-10) + +평균 점수를 계산하여 전체 복잡성을 결정하세요. + +### 2단계: 정밀도 요구사항 평가 + +정밀도 요구사항을 1-10점 척도로 평가하세요. 다음을 고려합니다: + +1. **출력 구조**: 출력이 얼마나 구조화되어야 합니까? + - 자유형 텍스트: 낮은 정밀도 (1-3) + - 반구조화: 중간 정밀도 (4-7) + - 엄격한 포맷(JSON, XML): 높은 정밀도 (8-10) + +2. **정확성 필요성**: 사실적 정확성이 얼마나 중요합니까? + - 창의적 콘텐츠: 낮은 정밀도 (1-3) + - 정보성 콘텐츠: 중간 정밀도 (4-7) + - 중요한 정보: 높은 정밀도 (8-10) + +3. **재현성**: 실행마다 결과가 얼마나 일관되어야 합니까? + - 변동 허용: 낮은 정밀도 (1-3) + - 어느 정도 일관성 필요: 중간 정밀도 (4-7) + - 정확한 재현성 필요: 높은 정밀도 (8-10) + +4. **오류 허용도**: 오류의 영향은 어느 정도입니까? + - 영향 적음: 낮은 정밀도 (1-3) + - 영향 보통: 중간 정밀도 (4-7) + - 영향 큼: 높은 정밀도 (8-10) + +평균 점수를 계산하여 전체 정밀도 요구사항을 결정하세요. + +### 3단계: 매트릭스에 매핑하기 + +복잡도와 정밀도 점수를 매트릭스에 표시하세요: + +- **낮은 복잡도(1-4), 낮은 정밀도(1-4)**: Simple Crews +- **낮은 복잡도(1-4), 높은 정밀도(5-10)**: 직접적인 LLM 호출이 있는 Flows +- **높은 복잡도(5-10), 낮은 정밀도(1-4)**: Complex Crews +- **높은 복잡도(5-10), 높은 정밀도(5-10)**: Crews를 오케스트레이션하는 Flows + +### 4단계: 추가 요소 고려 + +복잡성과 정밀성 외에도 다음을 고려하세요: + +1. **개발 시간**: crew는 프로토타입을 더 빠르게 만들 수 있습니다 +2. **유지보수 필요**: flow는 장기적인 유지보수에 더 적합합니다 +3. **팀 전문성**: 팀이 다양한 접근법에 얼마나 익숙한지 고려하세요 +4. **확장성 요구 사항**: flow는 일반적으로 복잡한 애플리케이션에 더 잘 확장됩니다 +5. **통합 필요**: 솔루션이 기존 시스템과 어떻게 통합될지 고려하세요 + +## 결론 + +Crews와 Flows 중에서 선택하거나 결합하는 것은 CrewAI 애플리케이션의 효과성, 유지 관리성, 확장성에 영향을 미치는 중요한 아키텍처적 결정입니다. 복잡성과 정밀성이라는 차원에서 사용 사례를 평가함으로써, 귀하의 특정 요구 사항에 부합하는 정보에 기반한 결정을 내릴 수 있습니다. + +가장 좋은 접근방식은 애플리케이션이 성숙해지면서 종종 진화한다는 점을 기억하세요. 귀하의 요구를 충족하는 가장 간단한 해결책으로 시작하고, 경험이 쌓이고 요구 사항이 명확해지면 아키텍처를 개선할 준비를 하세요. + + +이제 CrewAI 사용 사례를 평가하고, 복잡성과 정밀성 요구 사항에 따라 올바른 접근법을 선택할 수 있는 프레임워크를 갖추게 되었습니다. 이를 통해 보다 효과적이고 유지 관리 가능하며 확장성 있는 AI 애플리케이션을 구축할 수 있습니다. + + +## 다음 단계 + +- [효과적인 에이전트 만들기](/ko/guides/agents/crafting-effective-agents)에 대해 더 알아보기 +- [처음으로 crew 만들기](/ko/guides/crews/first-crew) 살펴보기 +- [flow 상태 관리 마스터하기](/ko/guides/flows/mastering-flow-state)에 깊이 파고들기 +- 더 깊은 이해를 위해 [핵심 개념](/ko/concepts/agents) 확인하기 \ No newline at end of file diff --git a/docs/v1.15.13/ko/guides/crews/first-crew.mdx b/docs/v1.15.13/ko/guides/crews/first-crew.mdx new file mode 100644 index 0000000000..9362c5948d --- /dev/null +++ b/docs/v1.15.13/ko/guides/crews/first-crew.mdx @@ -0,0 +1,140 @@ +--- +title: 첫 번째 Crew 만들기 +description: JSON-first crew 설정으로 협업 AI 팀을 만드는 단계별 튜토리얼입니다. +icon: users-gear +mode: "wide" +--- + +## 리서치 Crew 만들기 + +이 가이드에서는 두 에이전트가 주제를 조사하고 markdown 보고서를 작성하는 crew를 만듭니다. 새 crew 프로젝트는 JSON-first입니다. 에이전트는 `agents/*.jsonc`, 태스크와 crew 설정은 `crew.jsonc`에 두며, `crewai run`이 이 정의를 직접 로드합니다. + +### 준비 사항 + +1. [설치 가이드](/ko/installation)에 따라 CrewAI 설치 +2. [LLM 설정](/ko/concepts/llms#setting-up-your-llm)에 따라 모델 API 키 설정 +3. 웹 검색을 사용할 경우 [Serper.dev](https://serper.dev/) API 키 준비 + +## 1단계: 새 Crew 만들기 + +```bash +crewai create crew research_crew +cd research_crew +``` + +생성되는 구조: + +```text +research_crew/ +├── .gitignore +├── .env +├── agents/ +│ └── researcher.jsonc +├── crew.jsonc +├── knowledge/ +├── pyproject.toml +├── README.md +├── skills/ +└── tools/ +``` + + +`crew.py`, `config/agents.yaml`, `config/tasks.yaml`을 쓰는 기존 레이아웃이 필요하면 `crewai create crew research_crew --classic`을 사용하세요. + + +## 2단계: 에이전트 정의 + +생성된 `agents/researcher.jsonc` 파일을 교체하고 `agents/analyst.jsonc`를 추가합니다. 파일 이름이 `crew.jsonc`에서 참조하는 에이전트 이름입니다. + +```jsonc agents/researcher.jsonc +{ + "role": "Senior Research Specialist for {topic}", + "goal": "Find comprehensive and accurate information about {topic}, with a focus on recent developments and key insights.", + "backstory": "You are an experienced research specialist who organizes complex information into clear, useful notes.", + // 사용하는 모델로 바꾸세요. 예: "openai/gpt-4o". + "llm": "provider/model-id", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +```jsonc agents/analyst.jsonc +{ + "role": "Report Analyst for {topic}", + "goal": "Turn research findings into a clear, well-structured report.", + "backstory": "You are a careful analyst with strong technical writing skills and a talent for extracting useful insights.", + // 사용하는 모델로 바꾸세요. 예: "openai/gpt-4o". + "llm": "provider/model-id", + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +`provider/model-id`를 `openai/gpt-4o`, `anthropic/claude-sonnet-4-6`, `gemini/gemini-2.0-flash-001` 같은 모델로 바꾸세요. + +## 3단계: 태스크와 Crew 설정 + +`crew.jsonc`를 다음으로 교체합니다: + +```jsonc crew.jsonc +{ + "name": "Research Crew", + "agents": ["researcher", "analyst"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research on {topic}. Focus on key concepts, recent developments, major challenges, notable applications, and future outlook.", + "expected_output": "A comprehensive research document with organized sections, specific facts, and useful examples about {topic}.", + "agent": "researcher" + }, + { + "name": "analysis_task", + "description": "Analyze the research findings and create a polished report on {topic}. Include an executive summary, key insights, trend analysis, and recommendations.", + "expected_output": "A professional markdown report with clear headings, a concise summary, main findings, and recommendations.", + "agent": "analyst", + "context": ["research_task"], + "output_file": "output/report.md", + "markdown": true + } + ], + "process": "sequential", + "verbose": true, + "memory": true, + "inputs": { + "topic": "Artificial Intelligence in Healthcare" + } +} +``` + +`context`는 이전 태스크 이름을 가리키므로 analyst가 research 태스크 출력을 받습니다. `inputs`는 `{topic}`의 기본값을 제공합니다. 기본값이 없으면 `crewai run`이 실행 중에 물어봅니다. + +## 4단계: 환경 변수 설정 + +`.env`를 편집합니다: + +```sh +SERPER_API_KEY=your_serper_api_key +# 모델 제공자 API 키도 추가하세요. +``` + +## 5단계: 설치 및 실행 + +```bash +crewai install +crewai run +``` + +실행이 끝나면 `output/report.md`를 확인하세요. + + +신뢰하는 출처의 JSON crew 프로젝트만 실행하세요. `custom:` 도구와 `{"python": "module.attribute"}` 참조는 crew 로드 시 로컬 Python 코드를 실행합니다. + + + +주제를 조사하고 보고서를 작성하는 JSON-first crew를 만들었습니다. + diff --git a/docs/v1.15.13/ko/guides/flows/conversational-flows.mdx b/docs/v1.15.13/ko/guides/flows/conversational-flows.mdx new file mode 100644 index 0000000000..3a18cd1da5 --- /dev/null +++ b/docs/v1.15.13/ko/guides/flows/conversational-flows.mdx @@ -0,0 +1,474 @@ +--- +title: 대화형 Flow +description: 턴마다 kickoff, 메시지 기록, 의도 라우팅, 트레이싱, WebSocket 브리지로 멀티턴 채팅 앱을 만듭니다. +icon: comments +mode: "wide" +--- + +## 개요 + +대화형 앱은 각 사용자 입력을 **동일한 세션 id**로 **새 flow 실행**으로 처리합니다. CrewAI는 메시지 기록, 선택적 의도 분류, 지연 트레이싱, UI 브리지, 그리고 대화형 flow용 로컬 `flow.chat()` REPL을 제공합니다. + +| 개념 | 구현 | +|------|------| +| 세션 id | `handle_turn(..., session_id=...)` → `kickoff(inputs={"id": ...})` → `state.id` | +| 사용자 입력 | `handle_turn(message)`가 그래프 실행 전 `state.messages`에 추가 | +| 턴 완료 | `FlowFinished`는 **이번 실행**만 의미; 다음 `handle_turn`로 대화 계속 | +| 세션 전체 트레이스 | `ConversationConfig(defer_trace_finalization=True)` + `finalize_session_traces()` | + +## 턴 API + +REST, WebSocket, 테스트, 커스텀 UI에서 오는 모든 사용자 메시지에는 **`flow.handle_turn(message, session_id=...)`**를 사용하세요. 대화형 `Flow`를 로컬 터미널 채팅 루프로 실행하고 싶을 때는 **`flow.chat()`**을 사용하세요. + +`Flow.kickoff()`는 `user_message=` 또는 `session_id=` 키워드 인자를 받지 않습니다. 대화형 flow에서는 `handle_turn()`이 보류 중인 메시지를 저장하고 내부적으로 `kickoff(inputs={"id": session_id})`를 호출합니다. + +| API | 용도 | +|-----|------| +| `handle_turn(message, session_id=...)` | 대화형 `Flow`용 한 턴 편의 래퍼 | +| `chat()` | 대화형 `Flow`용 로컬 터미널 REPL | +| `kickoff(inputs={...})` | 대화형 턴 처리 없이 flow를 직접 실행 | +| `ask()` | 한 스텝 **내부** 블로킹 프롬프트 (마법사, 확인) | +| `@human_feedback` | **스텝 출력** 승인/거부 — 다음 채팅 줄이 아님 | +| `ChatSession.handle_turn(...)` | `handle_turn` 위의 전송 계층 (SSE / WebSocket) | + +## 빠른 시작 + +```python +from uuid import uuid4 + +from crewai import Flow +from crewai.flow import listen +from crewai.experimental.conversational import ( + ConversationConfig, + ConversationState, +) + + +@ConversationConfig(defer_trace_finalization=True) +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context): + message = self.state.current_user_message or "" + if "주문" in message or "order" in message.lower(): + return "order" + if "안녕" in message or "goodbye" in message.lower(): + return "goodbye" + return "help" + + @listen("order") + def handle_order(self): + reply = "주문이 배송 중입니다." + self.append_assistant_message(reply) + return reply + + @listen("help") + def handle_help(self): + reply = "무엇을 도와드릴까요?" + self.append_assistant_message(reply) + return reply + + @listen("goodbye") + def handle_goodbye(self): + reply = "안녕히 가세요!" + self.append_assistant_message(reply) + return reply + + +session_id = str(uuid4()) +flow = SupportFlow() + +try: + flow.handle_turn("주문 어디까지 왔나요?", session_id=session_id) + flow.handle_turn("반품은 어떻게 하나요?", session_id=session_id) +finally: + flow.finalize_session_traces() # 전체 대화에 대한 단일 trace 링크 +``` + +## 턴 생명주기 + +각 `handle_turn`은 다음 파이프라인을 실행합니다: + +1. **`_configure_conversational_kickoff`** — `session_id` / `user_message`를 `inputs`에 병합, `ConversationalConfig` 적용, 설정 시 지연 트레이싱 활성화. +2. **상태 복원** — `inputs["id"]`가 있고 `@persist`가 설정되면 최신 스냅샷 로드. +3. **`FlowStarted`** — 지연 세션의 첫 턴에서만 발생. +4. **`prepare_conversational_turn`** — 사용자 메시지를 `state.messages`에 추가, `last_user_message` 설정, `last_intent` 초기화, `intents` / `default_intents` + `intent_llm` 설정 시 분류. +5. **그래프 실행** — `@start` → `@router` → `@listen` 핸들러. +6. **실행 종료** — 지연 활성화 시 턴별 `flow_finished` 및 trace 종료 **건너뜀**; 중첩 `Agent.kickoff()` / crew도 부모 batch를 닫지 않음. + +핸들러는 **`append_assistant_message(reply)`**를 호출해 다음 턴의 `conversation_messages`에 어시스턴트 응답이 포함되게 하세요. 사용자 입력은 `handle_turn`이 이미 저장합니다 — 핸들러에서 다시 추가하지 마세요. + +## `ConversationalConfig` (클래스 수준 기본값) + +`Flow` 서브클래스에 `conversational_config: ClassVar[ConversationalConfig | None]`로 설정합니다. + +| 필드 | 기본값 | 목적 | +|------|--------|------| +| `default_intents` | `None` | kickoff 전 자동 분류용 outcome 라벨 | +| `intent_llm` | `None` | 분류용 모델 (intent 사용 시 필수) | +| `interactive_prompt` | `"You: "` | `kickoff(interactive=True)` 프롬프트 | +| `interactive_timeout` | `None` | 대화형 모드 줄 단위 타임아웃 | +| `exit_commands` | `exit`, `quit` | 대화형 모드 종료 단어 | +| `defer_trace_finalization` | `True` | 턴 간 하나의 trace batch 유지 | + +`intents=` 및 `intent_llm=` 키워드로 kickoff마다 재정의할 수 있습니다. + +## `ChatState` (권장 persist 형태) + +```python +from crewai.flow import ChatState + + +class MyChatState(ChatState): + # 상속: id, messages, last_user_message, last_intent, session_ready + research_turn_count: int = 0 + custom_flag: bool = False +``` + +| 필드 | 역할 | +|------|------| +| `id` | 세션 UUID (`session_id` / `inputs["id"]`와 동일) | +| `messages` | LLM 기록용 `{role, content}` 리스트 | +| `last_user_message` | 이번 턴의 최신 사용자 입력 | +| `last_intent` | 분류 후 라우트 라벨 (사용 시) | +| `session_ready` | 일회성 bootstrap 플래그 | + +`ConversationalInputs`는 `kickoff(inputs={...})`용 `TypedDict`: `id`, `user_message`, `last_intent`. + +## `Flow` 대화 API + +### `kickoff` / `kickoff_async` 파라미터 + +| 파라미터 | 목적 | +|----------|------| +| `user_message` | 이번 턴 텍스트 (또는 `{"role": "user", "content": "..."}`) | +| `session_id` | 대화 UUID → `inputs["id"]` / `state.id` | +| `intents` | kickoff 전 `classify_intent`용 outcome 라벨 | +| `intent_llm` | 분류 LLM (`intents`와 함께 필수) | +| `interactive` | `ask()` CLI 루프 (로컬 데모 전용) | +| `interactive_prompt` | 대화형 모드 프롬프트 | +| `interactive_timeout` | 줄 단위 `ask()` 타임아웃 | +| `exit_commands` | 대화형 모드 종료 단어 | +| `inputs` | 추가 상태 필드 | +| `restore_from_state_id` | 다른 persist flow에서 fork 복원 | + +### 인스턴스 속성 + +| 속성 | 목적 | +|------|------| +| `conversational_config` | 클래스 수준 `ConversationalConfig` | +| `defer_trace_finalization` | 인스턴스 플래그; kickoff 시 config에서 자동 설정 | +| `suppress_flow_events` | 콘솔 flow 패널 숨김; **트레이싱은 계속 기록** | +| `stream` | 스트리밍; `ChatSession.handle_turn(..., stream=True)`와 함께 | + +### 메서드 및 프로퍼티 + +| 이름 | 설명 | +|------|------| +| `append_message(role, content, **extra)` | `state.messages`에 추가 | +| `conversation_messages` | LLM 호출용 읽기 전용 기록 | +| `classify_intent(text, outcomes, *, llm, context=None)` | outcome 매핑 (`@human_feedback`와 동일 collapse) | +| `receive_user_message(text, *, outcomes=None, llm=None)` | 사용자 메시지 추가; 선택적 `last_intent` | +| `finalize_session_traces()` | 지연 `flow_finished` 발생 및 세션 trace batch 종료 | +| `_should_defer_trace_finalization()` | 턴별 trace 종료 지연 여부 | +| `input_history` | `ask()` 프롬프트/응답 감사 기록 | + +### 모듈 헬퍼 (`crewai.flow.conversation`) + +테스트 또는 커스텀 오케스트레이션용: + +| 함수 | 설명 | +|------|------| +| `normalize_kickoff_inputs(...)` | 대화 kwargs를 `inputs`에 병합 | +| `get_conversation_messages(flow)` | 상태 또는 내부 버퍼에서 메시지 읽기 | +| `append_message(flow, ...)` | 인스턴스 메서드와 동일 | +| `prepare_conversational_turn(flow, ...)` | 턴 수화 (보통 kickoff가 호출) | +| `receive_user_message(flow, ...)` | 인스턴스 메서드와 동일 | +| `set_state_field(flow, name, value)` | dict 또는 Pydantic 상태 필드 설정 | +| `get_conversational_config(flow)` | 클래스 `conversational_config` 읽기 | +| `input_history_to_messages(entries)` | `input_history`를 LLM 메시지 형식으로 | + +## 의도 라우팅 패턴 + +### A. `ConversationalConfig`로 사전 분류 (가장 단순) + +`default_intents`와 `intent_llm` 설정. 각 kickoff가 `@router` 전에 분류; `route()`에서 `self.state.last_intent` 읽기. + +### B. `@router` 내부에서 분류 (풍부한 프롬프트) + +`default_intents=None`으로 kickoff는 메시지만 추가. `route()`에서 커스텀 프롬프트로 `classify_intent` 호출: + +```python +@router(bootstrap) +def route(self): + intent = self.classify_intent( + self._routing_prompt(self.state.last_user_message), + ("GREETING", "ORDER", "RESEARCH", "GOODBYE"), + llm=self.conversational_config.intent_llm or "gpt-4o-mini", + ) + self.state.last_intent = intent + return intent +``` + +웹 리서치나 다단계 tool이 필요하면 **`@listen("RESEARCH")`** 등에서 `Agent.kickoff()`와 tool 사용 — 단순 `LLM.call()` 대신. + +## flow가 끝났지만 사용자는 계속 대화할 때 + +`FlowFinished`는 **이번 그래프 실행**이 완료됨을 의미합니다. 같은 `session_id`로 또 다른 `kickoff`로 대화가 이어집니다. `@persist`가 `messages`, 플래그, 컨텍스트를 복원합니다. + +**Persist 패턴:** 전체 `Flow` 클래스보다 **단일 종료 스텝**(예: `finalize`)에 `@persist`를 두는 것이 좋습니다. 클래스 수준 persist는 매 메서드 후 저장하며, `load_state`는 최신 행을 사용해 같은 턴의 핸들러 업데이트를 놓칠 수 있습니다. + +후속 채팅 줄에 `@human_feedback`를 쓰지 마세요. 특정 스텝 출력을 사람이 승인해야 할 때만 사용하세요. + +## 대화형 `Flow` (실험적) + + + **실험적 기능입니다.** 대화형 `Flow`의 API 표면(`conversational = True`, + `handle_turn`, `ConversationConfig`, `RouterConfig`, `ConversationState`, + 내장 그래프와 헬퍼)은 `crewai.experimental` 하위에 있으며 정식 출시 + 전까지 변경될 수 있습니다. 특정 동작에 의존한다면 CrewAI 버전을 고정하고 + 변경 사항이 있는지 changelog를 확인하세요. 피드백과 이슈 환영합니다. + + +`Flow` 서브클래스에 `conversational = True`를 지정하면 대화형 챗 그래프가 활성화됩니다. 베이스 `Flow`가 `@start` / `@router` / `converse_turn` / `end_conversation` 그래프를 노출하고, `state.messages`를 관리하며, router LLM을 구동하고, 턴 간 trace 배치를 열린 상태로 유지합니다. 여러분은 **커스텀 라우트**만 작성하면 되고, 나머지는 프레임워크가 담당합니다. + +LLM 기반 라우터와 라우트별 핸들러로 멀티턴 챗을 만들고 싶지만 라이프사이클을 직접 배선하고 싶지 않을 때 사용하세요. 완전한 제어가 필요하면 위의 `Flow[ChatState]`로 내려가세요. + +### 빠른 예제 + +```python +from crewai import LLM, Flow +from crewai.flow import listen +from crewai.experimental.conversational import ( + ConversationConfig, + ConversationState, + RouterConfig, +) + + +ROUTER_LLM = LLM(model="gpt-4o-mini") + + +@ConversationConfig( + system_prompt="A multi-agent assistant for ordinary chat and tool-backed tasks.", + llm=ROUTER_LLM, + router=RouterConfig(), # 라우트 + 설명은 @listen 핸들러에서 자동 발견 +) +class SupportFlow(Flow[ConversationState]): + conversational = True + + @listen("INTERNET_SEARCH") + def handle_internet_search(self) -> str: + """Fresh web research, current news, real-time lookups.""" + ... + self.append_assistant_message(reply) + return reply + + @listen("CREWAI_DOCS") + def handle_crewai_docs(self) -> str: + """Look up the CrewAI documentation for framework/API questions.""" + ... + self.append_assistant_message(reply) + return reply + + +flow = SupportFlow() +try: + flow.handle_turn("뭘 할 수 있어?") # converse(빌트인)로 라우팅 + flow.handle_turn("AI 뉴스를 웹에서 찾아줘.") # INTERNET_SEARCH로 라우팅 + flow.handle_turn("첫 번째 결과를 요약해줘.") # 다시 converse로 라우팅 +finally: + flow.finalize_session_traces() +``` + +로컬 터미널 채팅에는 `chat()`을 사용하세요: + +```python +def kickoff() -> None: + SupportFlow().chat() +``` + +`chat()`은 `handle_turn()`을 REPL로 감싸고, `exit` / `quit`에서 종료하며, 기본적으로 빈 줄을 건너뛰고, 세션이 끝날 때 `finalize_session_traces()`를 호출합니다. + +### `ConversationConfig` + +클래스 단위의 챗 기본값을 부착하는 클래스 데코레이터입니다. + +| 필드 | 기본값 | 목적 | +|------|--------|------| +| `system_prompt` | i18n `slices.conversational_system_prompt` | 빌트인 `converse_turn`이 사용하는 system 메시지. 빈 문자열(`""`)을 전달하면 system 메시지를 끕니다. | +| `llm` | `None` | 대화용 LLM (빌트인 `converse_turn`이 사용하고 router 폴백도 됨). | +| `router` | `None` | LLM 기반 라우팅을 위한 `RouterConfig`. 없으면 항상 `converse`로 떨어집니다. | +| `answer_from_history_prompt` | 프레임워크 기본값 | 선택적인 `answer_from_history` 라우트용 system 메시지. | +| `answer_from_history_llm` | `None` | 설정되면 `answer_from_history` 단축 경로가 활성화됩니다. | +| `intent_llm` | `None` | 레거시 `intents=`/`default_intents` 사전 분류용 LLM. | +| `default_intents` | `None` | 레거시 사전 분류용 outcome 레이블. | +| `visible_agent_outputs` | `None` | `"all"` 또는 `append_agent_result()` 결과를 사용자에게 공개로 승격할 에이전트 이름 목록. | +| `defer_trace_finalization` | `True` | `handle_turn()` 호출들 사이에서 하나의 trace 배치를 열어 둡니다. | + +### `RouterConfig`와 자동 생성되는 라우트 카탈로그 + +```python +RouterConfig( + prompt="선택적인 도메인 프레이밍 (정책, 톤, 페르소나).", + response_format=MyRoute, # 선택; 없으면 자동 생성 + llm=ROUTER_LLM, # ConversationConfig.llm으로 폴백 + routes=["INTERNET_SEARCH", "CREWAI_DOCS"], # 선택; 리스너에서 추론 + route_descriptions={ + "INTERNET_SEARCH": "이 라우트만 docstring 대신 사용할 설명.", + }, + default_intent="converse", # LLM 호출 실패 또는 LLM 없음일 때 사용 + fallback_intent="converse", # LLM이 잘못된 라우트를 반환할 때 사용 + intent_field="intent", +) +``` + +router에 전달되는 프롬프트는 자동으로 만들어집니다. 각 라우트의 설명은 다음 우선순위로 결정됩니다: + +1. `RouterConfig.route_descriptions[label]` — 명시적 오버라이드. +2. `Flow.builtin_route_descriptions[label]` — `converse`, `end`, `answer_from_history`용 프레임워크 캐닝 텍스트 (router LLM용으로 다듬어진 문구). +3. `@listen(label)` 핸들러 docstring의 첫 줄(비어있지 않은 줄). +4. 빈 문자열 (라우트만 카탈로그에 등장하고 설명은 없음). + +실제 사용에서 **새 라우트를 추가하는 방법은 `@listen("X")` + 한 줄짜리 docstring**입니다: + +```python +@listen("INTERNET_SEARCH") +def handle_internet_search(self) -> str: + """Fresh web research, current news, real-time lookups.""" + ... +``` + +…그러면 router LLM은 다음을 봅니다: + +``` +Routes: +- CREWAI_DOCS: Look up the CrewAI documentation for framework/API questions. +- INTERNET_SEARCH: Fresh web research, current news, real-time lookups. +- converse: Ordinary chat, follow-ups, summaries, clarifications… +- end: User signals the conversation is finished (goodbye, exit, done). +``` + +`RouterConfig.prompt`는 **도메인 프레이밍** (어시스턴트 페르소나, 비즈니스 규칙, 톤)을 위한 자리입니다. 라우트 카탈로그는 자동 생성되니 `prompt` 안에 라우트 목록을 넣지 마세요. 핸들러를 추가하는 순간 동기화가 깨집니다. + +### 빌트인 라우트 + +| 라우트 | 핸들러 | 목적 | +|--------|--------|------| +| `converse` | `converse_turn` | 기본 챗 핸들러. system prompt + 정식 메시지 히스토리와 함께 `ConversationConfig.llm`을 호출합니다. | +| `end` | `end_conversation` | `state.ended = True`로 설정하고 종료 응답을 보냅니다. | +| `answer_from_history` | `answer_from_history_turn` | 선택적. `ConversationConfig.answer_from_history_llm`이 설정되어 있고 메시지를 히스토리만으로 답할 수 있을 때 라우팅됩니다. | + +서브클래스에 같은 이름의 핸들러를 정의하면 어떤 것이든 오버라이드할 수 있습니다. + +### `handle_turn()` 시맨틱 + +`flow.handle_turn(message)`는 한 턴을 실행합니다: + +1. 그래프가 다시 실행되도록 턴 단위 실행 추적(`_completed_methods`, `_method_outputs`)을 초기화합니다 — 이게 없으면 동일 인스턴스에서 반복 `kickoff` 호출 시 `Flow.kickoff_async`가 `inputs={"id": ...}`를 체크포인트 복원으로 간주해 2번째 턴부터 단락 회로가 발생합니다. +2. 사용자 메시지를 `state.messages`에 추가하고 `current_user_message` / `last_user_message`를 설정합니다. `last_intent`는 **이전 턴 값이 유지**되어 router LLM이 신호로 활용할 수 있습니다. +3. `conversation_start` → `route_conversation` → 선택된 `@listen` 핸들러 순으로 실행됩니다. +4. router는 결정을 `state.last_intent`에 저장합니다 (다음 턴의 router 컨텍스트에서 보입니다). +5. 핸들러가 문자열을 반환했지만 `append_assistant_message`를 직접 호출하지 않았다면, `handle_turn`이 대신 추가해 줍니다. + +채팅 메시지에는 `handle_turn()`을 호출하세요. `kickoff(inputs={"id": ...})`를 직접 호출하면 대화형 턴 래퍼 없이 flow 그래프가 실행됩니다. + +### 로컬 REPL용 `chat()` + +`flow.chat()`은 `handle_turn()` 위에 얹은 바로 쓸 수 있는 터미널 래퍼입니다: + +```python +flow = SupportFlow() +flow.chat() +``` + +일반적인 로컬 루프를 처리합니다: + +1. 사용자 메시지를 입력받습니다. +2. `exit` / `quit`, `EOFError`, `KeyboardInterrupt`에서 멈춥니다. +3. `handle_turn(message, session_id=...)`를 호출합니다. +4. 어시스턴트 결과를 출력합니다. +5. `finally` 블록에서 지연된 세션 trace를 finalize합니다. + +주입 가능한 I/O로 터미널 동작을 커스터마이즈할 수 있습니다: + +```python +flow.chat( + session_id="demo-session", + prompt="You: ", + assistant_prefix="Assistant: ", + exit_commands=("exit", "quit", "bye"), +) +``` + +웹 앱, 백그라운드 worker, 테스트, 커스텀 transport에서는 계속 `handle_turn()`을 직접 사용하세요. + +### 커스텀 router 동작 + +매 라우팅 결정마다 사이드 이펙트(이벤트 버스 셋업, 텔레메트리)를 실행하려면 `route_turn`을 오버라이드하세요: + +```python +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context: dict[str, Any]) -> str | None: + self.event_bus = MyBus(self) + return super().route_turn(context) +``` + +LLM router를 우회해 프로그램적으로 라우트를 선택하려면 `route_turn`에서 문자열을 반환하세요. `None`을 반환하면 `_route_with_config(...)`로 떨어집니다. + +### `append_assistant_message`와 `append_agent_result` + +`@listen(label)` 핸들러 안에서 두 가지 중 선택하세요: + +- `self.append_assistant_message(text)` — 사용자에게 보이는 어시스턴트 턴을 `state.messages`에 추가합니다. 다음 턴의 `converse_turn`이 이 내용을 보게 됩니다. +- `self.append_agent_result(agent_name, result, visibility="private")` — 구조화된 이벤트를 `state.events`에, 스레드를 `state.agent_threads[agent_name]`에 기록합니다. public 가시성은 자동으로 `append_assistant_message`도 호출합니다. 정식 히스토리를 더럽히지 말아야 할 임시 작업에는 private을 쓰세요. + +`ConversationConfig.visible_agent_outputs`로 특정 에이전트의 private 결과를 전역적으로 public으로 승격할 수 있습니다 (`"all"` 또는 이름 리스트). + +## 턴 간 트레이싱 + +`defer_trace_finalization=True` (`ConversationalConfig` 기본값): + +- 채팅 세션 전체에 **하나의 trace batch**. +- 첫 턴에만 **`flow_started`**; `finalize_session_traces()`에서 **`flow_finished`** 한 번. +- 턴별 `kickoff`는 “Trace batch finalized”를 출력하지 않음. +- **중첩 작업** (`Agent.kickoff()`, crew, Exa tool)은 **부모** batch에 추가; 내부 `AgentExecutor` flow가 세션 batch를 조기 종료하지 않음. + +```python +flow.chat(session_id=session_id) +``` + +`flow.chat()`이 `finalize_session_traces()`를 대신 호출합니다. `handle_turn()`이나 `kickoff(...)`로 직접 루프를 소유하는 경우, 세션이 끝날 때 `finalize_session_traces()`를 호출하세요. + +`suppress_flow_events=True`는 Rich 콘솔 패널만 숨깁니다. trace 및 method 이벤트는 계속 발생합니다. + +### 대화형 `Flow` trace 수명 주기 + +실험적 [대화형 `Flow`](#대화형-flow-실험적)는 동일한 tracing 수명 주기를 따릅니다. `defer_trace_finalization` 기본값이 `True`이므로 각 `handle_turn()`이 세션 trace를 열어 둡니다. 세션 끝에서 항상 finalize하세요 — REPL/루프를 `try/finally`로 감싸고 종료 시 `flow.finalize_session_traces()`를 호출하세요. 호출하지 않으면 batch가 열린 채 남아 마지막 대화가 export되지 않을 수 있습니다. + +## 스트리밍 + +`Flow` 클래스에 `stream = True`. `kickoff(...)`가 표준 이벤트 버스를 통해 `assistant_delta` 등 이벤트를 발생시킵니다. + +## import + +```python +from crewai.flow import ( + ChatState, + ConversationalConfig, + ConversationalInputs, + Flow, + listen, + persist, + router, + start, +) +``` + +## 참고 + +- [Flow 상태 관리 마스터하기](/ko/guides/flows/mastering-flow-state) +- [첫 Flow 만들기](/ko/guides/flows/first-flow) +- 데모: `lib/crewai/runner_conversational_flow_simple.py` diff --git a/docs/v1.15.13/ko/guides/flows/first-flow.mdx b/docs/v1.15.13/ko/guides/flows/first-flow.mdx new file mode 100644 index 0000000000..04d0f3edf2 --- /dev/null +++ b/docs/v1.15.13/ko/guides/flows/first-flow.mdx @@ -0,0 +1,550 @@ +--- +title: 첫 Flow 빌드하기 +description: 정밀한 실행 제어가 가능한 구조화된 이벤트 기반 워크플로우를 만드는 방법을 배웁니다. +icon: diagram-project +mode: "wide" +--- + +## Flows로 AI 워크플로우 제어하기 + +CrewAI Flows는 AI 오케스트레이션의 새로운 수준을 제공합니다. 즉, AI agent crew의 협업 능력과 절차적 프로그래밍의 정밀성 및 유연성을 결합합니다. crew가 agent 협업에서 탁월하다면, flow는 AI 시스템의 다양한 구성요소가 어떻게 그리고 언제 상호작용하는지에 대해 세밀하게 제어할 수 있게 해줍니다. + +이 가이드에서는 원하는 주제에 대한 포괄적인 학습 가이드를 생성하는 강력한 CrewAI Flow를 만드는 과정을 소개합니다. 이 튜토리얼을 통해 Flow가 일반 코드, 직접적인 LLM 호출, crew 기반 처리 등을 결합하여 AI 워크플로우에 구조적이고 이벤트 기반의 제어를 제공하는 방법을 시연할 것입니다. + +### 플로우의 강력한 점 + +플로우를 통해 다음과 같은 작업을 할 수 있습니다: + +1. **다양한 AI 상호작용 패턴 결합** - 복잡한 협업 작업에는 crew를 사용하고, 더 단순한 작업에는 직접적인 LLM 호출과 절차적 논리에는 일반 코드를 사용하세요. +2. **이벤트 기반 시스템 구축** - 구성 요소가 특정 이벤트와 데이터 변경에 어떻게 반응할지 정의할 수 있습니다. +3. **구성 요소 간 상태 유지** - 애플리케이션의 다양한 부분 간에 데이터를 공유하고 변환할 수 있습니다. +4. **외부 시스템과 통합** - 데이터베이스, API, 사용자 인터페이스와 같은 외부 시스템과 AI 워크플로우를 원활하게 연동할 수 있습니다. +5. **복잡한 실행 경로 생성** - 조건부 분기, 병렬 처리 및 동적인 워크플로우를 설계할 수 있습니다. + +### 무엇을 구축하고 배우게 될까요 + +이 가이드가 끝나면 여러분은 다음을 달성할 수 있습니다: + +1. **사용자 입력, AI 계획, 그리고 멀티 에이전트 콘텐츠 생성이 결합된 정교한 콘텐츠 생성 시스템을 구축**했습니다. +2. **시스템의 다양한 구성 요소 간 정보 흐름을 오케스트레이션(조율)**했습니다. +3. **이전 단계의 완료에 따라 각 단계가 반응하는 이벤트 기반 아키텍처를 구현**했습니다. +4. **더 복잡한 AI 애플리케이션을 확장하고 맞춤화할 수 있는 기반을 구축**했습니다. + +이번 가이드의 creator flow는 다음과 같은 훨씬 더 발전된 애플리케이션에 적용할 수 있는 기본 패턴을 보여줍니다: + +- 여러 전문화된 하위 시스템을 결합하는 대화형 AI assistant +- AI 기반 변환을 포함한 복잡한 데이터 처리 파이프라인 +- 외부 서비스 및 API와 통합되는 자율적 에이전트 +- 인간이 개입하는 프로세스를 포함한 다단계 의사결정 시스템 + +함께 여러분의 첫 번째 flow를 만들어 봅시다! + +## 사전 준비 사항 + +시작하기 전에 다음을 확인하세요: + +1. [설치 가이드](/ko/installation)에 따라 CrewAI를 설치했는지 확인하십시오. +2. [LLM 설정 가이드](/ko/concepts/llms#setting-up-your-llm)에 따라 환경에 LLM API 키를 설정했는지 확인하십시오. +3. Python에 대한 기본적인 이해 + +## 1단계: 새로운 CrewAI Flow 프로젝트 생성 + +먼저, CLI를 사용하여 새로운 CrewAI Flow 프로젝트를 생성해봅시다. 이 명령어는 필요한 모든 디렉터리와 템플릿 파일이 포함된 기본 프로젝트 구조를 만들어줍니다. + +```bash +crewai create flow guide_creator_flow +cd guide_creator_flow +``` + +이렇게 하면 flow에 필요한 기본 구조를 가진 프로젝트가 생성됩니다. + + + CrewAI Framework 개요 + + +## 2단계: 프로젝트 구조 이해하기 + +생성된 프로젝트는 다음과 같은 구조를 가지고 있습니다. 시작용 embedded crew는 클래식 Python/YAML 레이아웃을 사용합니다. Flow 안에서 JSON-first crew를 사용하려면 crew 폴더에 `crew.jsonc`와 `agents/*.jsonc`를 만들고 `crewai.project.load_crew`로 로드하세요. 예시는 [Flows](/ko/concepts/flows#building-your-crews)를 참고하세요. + +``` +guide_creator_flow/ +├── .gitignore +├── pyproject.toml +├── README.md +├── .env +└── src/ + └── guide_creator_flow/ + ├── __init__.py + ├── main.py + ├── crews/ + │ └── poem_crew/ + │ ├── config/ + │ │ ├── agents.yaml + │ │ └── tasks.yaml + │ └── poem_crew.py + └── tools/ + └── custom_tool.py +``` + +이 구조는 flow의 다양한 구성 요소를 명확하게 분리해줍니다: +- `src/guide_creator_flow/main.py` 파일의 main flow 로직 +- `src/guide_creator_flow/crews` 디렉터리의 특화된 crew들 +- `src/guide_creator_flow/tools` 디렉터리의 custom tool들 + +이제 이 구조를 수정하여 guide creator flow를 만들 것입니다. 이 flow는 포괄적인 학습 가이드 생성을 조직하는 역할을 합니다. + +## 3단계: Content Writer Crew 추가 + +우리 flow에는 콘텐츠 생성 프로세스를 처리할 전문화된 crew가 필요합니다. CrewAI CLI를 사용하여 content writer crew를 추가해봅시다: + +```bash +crewai flow add-crew content-crew +``` + +이 명령어는 자동으로 crew에 필요한 디렉터리와 템플릿 파일을 생성합니다. content writer crew는 가이드의 각 섹션을 작성하고 검토하는 역할을 담당하며, 메인 애플리케이션에 의해 조율되는 전체 flow 내에서 작업하게 됩니다. + +## 4단계: 콘텐츠 작가 Crew 구성 + +이제 콘텐츠 작가 crew를 JSONC로 구성합니다. 가이드의 고품질 콘텐츠를 만들기 위해 협업하는 두 명의 전문 에이전트 - 작가와 리뷰어 - 를 설정합니다. + +1. `src/guide_creator_flow/crews/content_crew/agents/content_writer.jsonc`를 만듭니다: + +```jsonc +{ + "role": "Educational Content Writer", + "goal": "Create engaging, informative content that thoroughly explains the assigned topic and provides valuable insights to the reader.", + "backstory": "You are a talented educational writer who explains complex concepts in accessible language and organizes information clearly.", + "llm": "provider/model-id", + "settings": { + "verbose": true + } +} +``` + +2. `src/guide_creator_flow/crews/content_crew/agents/content_reviewer.jsonc`를 만듭니다: + +```jsonc +{ + "role": "Educational Content Reviewer and Editor", + "goal": "Ensure content is accurate, comprehensive, well-structured, and consistent with previously written sections.", + "backstory": "You are a meticulous editor with an eye for detail, clarity, and coherence.", + "llm": "provider/model-id", + "settings": { + "verbose": true + } +} +``` + +`provider/model-id`를 사용하는 모델로 바꾸세요. 예: `openai/gpt-4o`, `gemini/gemini-2.0-flash-001`, `anthropic/claude-sonnet-4-6`. + +3. `src/guide_creator_flow/crews/content_crew/crew.jsonc`를 만듭니다: + +```jsonc +{ + "name": "Content Crew", + "agents": ["content_writer", "content_reviewer"], + "tasks": [ + { + "name": "write_section_task", + "description": "Write a comprehensive section on the topic: \"{section_title}\".\n\nSection description: {section_description}\nTarget audience: {audience_level} level learners\n\nYour content should begin with a brief introduction, explain key concepts clearly with examples, include practical applications where appropriate, end with a summary, and be approximately 500-800 words.\n\nPreviously written sections:\n{previous_sections}", + "expected_output": "A well-structured, comprehensive section in Markdown format that thoroughly explains the topic and is appropriate for the target audience.", + "agent": "content_writer", + "markdown": true + }, + { + "name": "review_section_task", + "description": "Review and improve this section on \"{section_title}\":\n\n{draft_content}\n\nTarget audience: {audience_level} level learners\nPreviously written sections:\n{previous_sections}\n\nFix errors, improve clarity, verify consistency, enhance structure, and add missing key information.", + "expected_output": "An improved, polished version of the section that maintains the original structure but enhances clarity, accuracy, and consistency.", + "agent": "content_reviewer", + "context": ["write_section_task"], + "markdown": true + } + ], + "process": "sequential", + "verbose": true +} +``` + +`context` 필드를 통해 리뷰어가 작가의 출력을 사용할 수 있습니다. + +4. `src/guide_creator_flow/crews/content_crew/content_crew.py`를 작은 loader로 교체합니다: + +```python +from pathlib import Path + +from crewai.project import load_crew + + +def kickoff_content_crew(inputs: dict): + crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc")) + return crew.kickoff(inputs={**default_inputs, **inputs}) +``` + +이 loader는 런타임에 `crew.jsonc`를 `Crew`로 바꿉니다. 이 crew는 독립적으로도 작동할 수 있지만, 우리의 플로우에서는 더 큰 시스템의 일부로 오케스트레이션됩니다. + +## 5단계: 플로우(Flow) 생성 + +이제 가장 흥미로운 부분입니다 - 전체 가이드 생성 과정을 오케스트레이션할 플로우를 만드는 단계입니다. 이곳에서 우리는 일반 Python 코드, 직접적인 LLM 호출, 그리고 우리의 컨텐츠 제작 crew를 결합하여 일관된 시스템으로 만듭니다. + +우리의 플로우는 다음과 같은 일을 수행합니다: +1. 주제와 대상 독자 수준에 대한 사용자 입력을 받습니다. +2. 구조화된 가이드 개요를 만들기 위해 직접 LLM 호출을 합니다. +3. 컨텐츠 writer crew를 사용하여 각 섹션을 순차적으로 처리합니다. +4. 모든 내용을 결합하여 최종 종합 문서를 완성합니다. + +`main.py` 파일에 우리의 플로우를 생성해봅시다: + +```python +#!/usr/bin/env python +import json +import os +from typing import List, Dict +from pydantic import BaseModel, Field +from crewai import LLM +from crewai.flow.flow import Flow, listen, start +from guide_creator_flow.crews.content_crew.content_crew import kickoff_content_crew + +# Define our models for structured data +class Section(BaseModel): + title: str = Field(description="Title of the section") + description: str = Field(description="Brief description of what the section should cover") + +class GuideOutline(BaseModel): + title: str = Field(description="Title of the guide") + introduction: str = Field(description="Introduction to the topic") + target_audience: str = Field(description="Description of the target audience") + sections: List[Section] = Field(description="List of sections in the guide") + conclusion: str = Field(description="Conclusion or summary of the guide") + +# Define our flow state +class GuideCreatorState(BaseModel): + topic: str = "" + audience_level: str = "" + guide_outline: GuideOutline = None + sections_content: Dict[str, str] = {} + +class GuideCreatorFlow(Flow[GuideCreatorState]): + """Flow for creating a comprehensive guide on any topic""" + + @start() + def get_user_input(self): + """Get input from the user about the guide topic and audience""" + print("\n=== Create Your Comprehensive Guide ===\n") + + # Get user input + self.state.topic = input("What topic would you like to create a guide for? ") + + # Get audience level with validation + while True: + audience = input("Who is your target audience? (beginner/intermediate/advanced) ").lower() + if audience in ["beginner", "intermediate", "advanced"]: + self.state.audience_level = audience + break + print("Please enter 'beginner', 'intermediate', or 'advanced'") + + print(f"\nCreating a guide on {self.state.topic} for {self.state.audience_level} audience...\n") + return self.state + + @listen(get_user_input) + def create_guide_outline(self, state): + """Create a structured outline for the guide using a direct LLM call""" + print("Creating guide outline...") + + # Initialize the LLM + llm = LLM(model="openai/gpt-4o-mini", response_format=GuideOutline) + + # Create the messages for the outline + messages = [ + {"role": "system", "content": "You are a helpful assistant designed to output JSON."}, + {"role": "user", "content": f""" + Create a detailed outline for a comprehensive guide on "{state.topic}" for {state.audience_level} level learners. + + The outline should include: + 1. A compelling title for the guide + 2. An introduction to the topic + 3. 4-6 main sections that cover the most important aspects of the topic + 4. A conclusion or summary + + For each section, provide a clear title and a brief description of what it should cover. + """} + ] + + # Make the LLM call with JSON response format + response = llm.call(messages=messages) + + # Parse the JSON response + outline_dict = json.loads(response) + self.state.guide_outline = GuideOutline(**outline_dict) + + # Ensure output directory exists before saving + os.makedirs("output", exist_ok=True) + + # Save the outline to a file + with open("output/guide_outline.json", "w") as f: + json.dump(outline_dict, f, indent=2) + + print(f"Guide outline created with {len(self.state.guide_outline.sections)} sections") + return self.state.guide_outline + + @listen(create_guide_outline) + def write_and_compile_guide(self, outline): + """Write all sections and compile the guide""" + print("Writing guide sections and compiling...") + completed_sections = [] + + # Process sections one by one to maintain context flow + for section in outline.sections: + print(f"Processing section: {section.title}") + + # Build context from previous sections + previous_sections_text = "" + if completed_sections: + previous_sections_text = "# Previously Written Sections\n\n" + for title in completed_sections: + previous_sections_text += f"## {title}\n\n" + previous_sections_text += self.state.sections_content.get(title, "") + "\n\n" + else: + previous_sections_text = "No previous sections written yet." + + # Run the content crew for this section + result = kickoff_content_crew(inputs={ + "section_title": section.title, + "section_description": section.description, + "audience_level": self.state.audience_level, + "previous_sections": previous_sections_text, + "draft_content": "" + }) + + # Store the content + self.state.sections_content[section.title] = result.raw + completed_sections.append(section.title) + print(f"Section completed: {section.title}") + + # Compile the final guide + guide_content = f"# {outline.title}\n\n" + guide_content += f"## Introduction\n\n{outline.introduction}\n\n" + + # Add each section in order + for section in outline.sections: + section_content = self.state.sections_content.get(section.title, "") + guide_content += f"\n\n{section_content}\n\n" + + # Add conclusion + guide_content += f"## Conclusion\n\n{outline.conclusion}\n\n" + + # Save the guide + with open("output/complete_guide.md", "w") as f: + f.write(guide_content) + + print("\nComplete guide compiled and saved to output/complete_guide.md") + return "Guide creation completed successfully" + +def kickoff(): + """Run the guide creator flow""" + GuideCreatorFlow().kickoff() + print("\n=== Flow Complete ===") + print("Your comprehensive guide is ready in the output directory.") + print("Open output/complete_guide.md to view it.") + +def plot(): + """Generate a visualization of the flow""" + flow = GuideCreatorFlow() + flow.plot("guide_creator_flow") + print("Flow visualization saved to guide_creator_flow.html") + +if __name__ == "__main__": + kickoff() +``` + +이 플로우에서 일어나는 과정을 분석해봅시다: + +1. 구조화된 데이터에 대한 Pydantic 모델을 정의하여 타입 안전성과 명확한 데이터 표현을 보장합니다. +2. 플로우 단계별로 데이터를 유지하기 위한 state 클래스를 생성합니다. +3. 세 가지 주요 플로우 단계를 구현합니다: + - `@start()` 데코레이터로 사용자 입력을 받습니다. + - 직접 LLM 호출로 가이드 개요를 생성합니다. + - content crew로 각 섹션을 처리합니다. +4. `@listen()` 데코레이터를 활용해 단계 간 이벤트 기반 관계를 설정합니다. + +이것이 바로 flows의 힘입니다 - 다양한 처리 유형(사용자 상호작용, 직접적인 LLM 호출, crew 기반 작업)을 하나의 일관된 이벤트 기반 시스템으로 결합할 수 있습니다. + +## 6단계: 환경 변수 설정하기 + +프로젝트 루트에 `.env` 파일을 생성하고 API 키를 입력하세요. 공급자 구성에 대한 자세한 내용은 [LLM 설정 가이드](/ko/concepts/llms#setting-up-your-llm)를 참고하세요. + +```sh .env +OPENAI_API_KEY=your_openai_api_key +# or +GEMINI_API_KEY=your_gemini_api_key +# or +ANTHROPIC_API_KEY=your_anthropic_api_key +``` + +## 7단계: 의존성 설치 + +필수 의존성을 설치합니다: + +```bash +crewai install +``` + +## 8단계: Flow 실행하기 + +이제 여러분의 flow가 실제로 작동하는 모습을 볼 차례입니다! CrewAI CLI를 사용하여 flow를 실행하세요: + +```bash +crewai run +``` + +이 명령어를 실행하면 flow가 다음과 같이 작동하는 것을 확인할 수 있습니다: +1. 주제와 대상 수준을 입력하라는 메시지가 표시됩니다. +2. 가이드의 체계적인 개요를 생성합니다. +3. 각 섹션을 처리할 때 content writer와 reviewer가 협업합니다. +4. 마지막으로 모든 내용을 종합하여 완성도 높은 가이드를 만듭니다. + +이는 여러 구성요소(인공지능 및 비인공지능 모두)가 포함된 복잡한 프로세스를 flows가 어떻게 조정할 수 있는지 보여줍니다. + +## 9단계: Flow 시각화하기 + +flow의 강력한 기능 중 하나는 구조를 시각화할 수 있다는 점입니다. + +```bash +crewai flow plot +``` + +이 명령은 flow의 구조를 보여주는 HTML 파일을 생성하며, 각 단계 간의 관계와 그 사이에 흐르는 데이터를 확인할 수 있습니다. 이러한 시각화는 복잡한 flow를 이해하고 디버깅하는 데 매우 유용합니다. + +## 10단계: 출력물 검토하기 + +flow가 완료되면 `output` 디렉토리에서 두 개의 파일을 찾을 수 있습니다: + +1. `guide_outline.json`: 가이드의 구조화된 개요가 포함되어 있습니다 +2. `complete_guide.md`: 모든 섹션이 포함된 종합적인 가이드입니다 + +이 파일들을 잠시 검토하고 여러분이 구축한 시스템을 되돌아보세요. 이 시스템은 사용자 입력, 직접적인 AI 상호작용, 협업 에이전트 작업을 결합하여 복잡하고 고품질의 결과물을 만들어냅니다. + +## 가능한 것의 예술: 첫 번째 Flow 그 이상 + +이 가이드에서 배운 내용은 훨씬 더 정교한 AI 시스템을 만드는 데 기반이 됩니다. 다음은 이 기본 flow를 확장할 수 있는 몇 가지 방법입니다: + +### 사용자 상호작용 향상 + +더욱 인터랙티브한 플로우를 만들 수 있습니다: +- 입력 및 출력을 위한 웹 인터페이스 +- 실시간 진행 상황 업데이트 +- 인터랙티브한 피드백 및 개선 루프 +- 다단계 사용자 상호작용 + +### 추가 처리 단계 추가하기 + +다음과 같은 추가 단계로 flow를 확장할 수 있습니다: +- 개요 작성 전 사전 리서치 +- 일러스트를 위한 이미지 생성 +- 기술 가이드용 코드 스니펫 생성 +- 최종 품질 보증 및 사실 확인 + +### 더 복잡한 Flows 생성하기 + +더 정교한 flow 패턴을 구현할 수 있습니다: +- 사용자 선호도나 콘텐츠 유형에 따른 조건 분기 +- 독립적인 섹션의 병렬 처리 +- 피드백과 함께하는 반복적 개선 루프 +- 외부 API 및 서비스와의 통합 + +### 다양한 도메인에 적용하기 + +동일한 패턴을 사용하여 다음과 같은 flow를 만들 수 있습니다: +- **대화형 스토리텔링**: 사용자 입력을 바탕으로 개인화된 이야기를 생성 +- **비즈니스 인텔리전스**: 데이터를 처리하고, 인사이트를 도출하며, 리포트를 생성 +- **제품 개발**: 아이디어 구상, 디자인, 기획을 지원 +- **교육 시스템**: 개인화된 학습 경험을 제공 + +## 주요 특징 시연 + +이 guide creator flow에서는 CrewAI의 여러 강력한 기능을 시연합니다: + +1. **사용자 상호작용**: flow는 사용자로부터 직접 입력을 수집합니다 +2. **직접적인 LLM 호출**: 효율적이고 단일 목적의 AI 상호작용을 위해 LLM 클래스를 사용합니다 +3. **Pydantic을 통한 구조화된 데이터**: 타입 안정성을 보장하기 위해 Pydantic 모델을 사용합니다 +4. **컨텍스트를 활용한 순차 처리**: 섹션을 순서대로 작성하면서 이전 섹션을 컨텍스트로 제공합니다 +5. **멀티 에이전트 crew**: 콘텐츠 생성을 위해 특화된 에이전트(writer 및 reviewer)를 활용합니다 +6. **상태 관리**: 프로세스의 다양한 단계에 걸쳐 상태를 유지합니다 +7. **이벤트 기반 아키텍처**: 이벤트에 응답하기 위해 `@listen` 데코레이터를 사용합니다 + +## 플로우 구조 이해하기 + +플로우의 주요 구성 요소를 분해하여 자신만의 플로우를 만드는 방법을 이해할 수 있도록 도와드리겠습니다: + +### 1. 직접 LLM 호출 + +Flow를 사용하면 간단하고 구조화된 응답이 필요할 때 언어 모델에 직접 호출할 수 있습니다: + +```python +llm = LLM( + model="model-id-here", # gpt-4o, gemini-2.0-flash, anthropic/claude... + response_format=GuideOutline +) +response = llm.call(messages=messages) +``` + +특정하고 구조화된 출력이 필요할 때 crew를 사용하는 것보다 더 효율적입니다. + +### 2. 이벤트 기반 아키텍처 + +Flows는 데코레이터를 사용하여 컴포넌트 간의 관계를 설정합니다: + +```python +@start() +def get_user_input(self): + # First step in the flow + # ... + +@listen(get_user_input) +def create_guide_outline(self, state): + # This runs when get_user_input completes + # ... +``` + +이렇게 하면 애플리케이션에 명확하고 선언적인 구조가 만들어집니다. + +### 3. 상태 관리 + +flow는 단계 간 상태를 유지하여 데이터를 쉽게 공유할 수 있습니다: + +```python +class GuideCreatorState(BaseModel): + topic: str = "" + audience_level: str = "" + guide_outline: GuideOutline = None + sections_content: Dict[str, str] = {} +``` + +이 방식은 flow 전반에 걸쳐 데이터를 추적하고 변환하는 타입 안전(type-safe)한 방법을 제공합니다. + +### 4. Crew 통합 + +Flow는 복잡한 협업 작업을 위해 crew와 원활하게 통합될 수 있습니다: + +```python +result = kickoff_content_crew(inputs={ + "section_title": section.title, + # ... +}) +``` + +이를 통해 애플리케이션의 각 부분에 적합한 도구를 사용할 수 있습니다. 단순한 작업에는 직접적인 LLM 호출을, 복잡한 협업에는 crew를 사용할 수 있습니다. + +## 다음 단계 + +이제 첫 번째 flow를 구축했으니 다음을 시도해 볼 수 있습니다: + +1. 더 복잡한 flow 구조와 패턴을 실험해 보세요. +2. `@router()`를 사용하여 flow에서 조건부 분기를 만들어 보세요. +3. 더 복잡한 병렬 실행을 위해 `and_` 및 `or_` 함수를 탐색해 보세요. +4. flow를 외부 API, 데이터베이스 또는 사용자 인터페이스에 연결해 보세요. +5. 여러 전문화된 crew를 하나의 flow에서 결합해 보세요. +6. [대화형 Flow](/ko/guides/flows/conversational-flows)로 멀티턴 채팅 앱 구축 (`kickoff` per message, `ChatSession`, 지연 트레이싱) + + +축하합니다! 정규 코드, 직접적인 LLM 호출, crew 기반 처리를 결합하여 포괄적인 가이드를 생성하는 첫 번째 CrewAI Flow를 성공적으로 구축하셨습니다. 이러한 기초적인 역량을 바탕으로 절차적 제어와 협업적 인텔리전스를 결합하여 복잡하고 다단계의 문제를 해결할 수 있는 점점 더 정교한 AI 애플리케이션을 만들 수 있습니다. + diff --git a/docs/v1.15.13/ko/guides/flows/inputs-id-deprecation.mdx b/docs/v1.15.13/ko/guides/flows/inputs-id-deprecation.mdx new file mode 100644 index 0000000000..226db332f2 --- /dev/null +++ b/docs/v1.15.13/ko/guides/flows/inputs-id-deprecation.mdx @@ -0,0 +1,125 @@ +--- +title: "inputs.id에서 restore_from_state_id로 마이그레이션" +description: "더 이상 지원되지 않는 inputs.id 하이드레이션에서 지원되는 restore_from_state_id 필드로 @persist 흐름을 이동" +icon: "arrow-right-arrow-left" +--- + + + `inputs` 내에서 `id`를 전달하여 `@persist` 흐름을 하이드레이트하는 것은 **더 이상 지원되지 않으며** + 향후 릴리스에서 제거될 예정입니다. 대체품인 `restore_from_state_id`는 CrewAI **v1.14.5 이상**에서 사용할 수 있으며, + 아래 단계는 업그레이드 후 적용됩니다. + + +## 개요 + +이전 실행에서 `@persist` 흐름을 하이드레이트하는 문서화된 방법은 +해당 실행의 UUID를 `inputs.id`로 전달하는 것입니다. CrewAI는 이제 +`inputs` 페이로드를 과부하하지 않고 동일한 하이드레이션을 수행하는 전용 필드인 +`restore_from_state_id`를 제공합니다 — 그리고 하이드레이션 키를 새로운 실행의 +정체성과 결합하지 않습니다. + +## 마이그레이션 + +현재 `inputs={"id": ...}`로 `@persist` 흐름을 시작하는 경우: + +```python +# 더 이상 지원되지 않음 +flow = CounterFlow() +flow.kickoff(inputs={"id": "abcd1234-5678-90ef-ghij-klmnopqrstuv"}) +``` + +`restore_from_state_id`로 전환하십시오: + +```python +# 지원됨 +flow = CounterFlow() +flow.kickoff(restore_from_state_id="abcd1234-5678-90ef-ghij-klmnopqrstuv") +``` + +두 모드는 서로 다른 계보 의미론을 가지고 있습니다: + +- `inputs={"id": }` (더 이상 지원되지 않음) — **재개**: 제공된 + id 아래에 기록이 작성되어 동일한 `flow_uuid` 이력이 확장됩니다. +- `restore_from_state_id=` — **분기**: 스냅샷에서 상태를 하이드레이트한 후 + 새로운 `state.id` 아래에 기록합니다. 원본 흐름의 이력은 보존됩니다. + +대부분의 프로덕션 시나리오에서는 — 이전 상태에서 시드된 흐름을 다시 실행하는 경우 — 분기가 +필요합니다. 전체 정신 모델은 [Flow State 마스터링](/ko/guides/flows/mastering-flow-state)을 참조하십시오. + +CrewAI AMP REST API를 통해 흐름을 시작하는 경우, 아래 [AMP](#amp)에서 +동일한 페이로드 마이그레이션을 참조하십시오. + +## 왜 `@persist`에 대해 `inputs.id`를 더 이상 지원하지 않습니까? + +`inputs.id`는 현재 이전 실행에서 `@persist` 흐름을 재개하는 문서화된 방법입니다. 문제는 +동일한 UUID가 두 가지 작업을 동시에 수행한다는 것입니다: + +1. **어떤 스냅샷에서 `@persist`가 하이드레이트되는지를 선택합니다** — 해당 UUID 아래에 저장된 상태를 로드합니다. +2. **새 실행의 흐름 실행 ID가 됩니다** (`state.id`는 SDK에서; 일부 컨텍스트에서는 `flow_id`로 표시됨) — 이 + 시작에서의 모든 `@persist` 기록도 동일한 UUID 아래에 작성됩니다. + +이 이중 역할이 이 가이드에서 설명하는 문제의 근본 원인입니다. 제공된 UUID가 새 실행의 id이기도 하므로, +동일한 `inputs.id`를 전달하는 두 번의 시작은 두 개의 별도 실행이 아닙니다 — 그들은 id를 공유하고, +지속성 기록을 공유하며, (AMP에서) 실행 목록에서 행을 공유합니다. "이 스냅샷에서 하이드레이트하지만, +이 실행을 별도로 기록하십시오"라고 말할 방법이 없습니다. + +`restore_from_state_id`가 그 분리입니다. 이는 `@persist`에 어떤 스냅샷에서 하이드레이트할지를 알려주며, +새 실행이 새로운 `state.id`를 받을 수 있도록 합니다. 하이드레이션 소스와 기록된 실행은 더 이상 동일한 UUID가 아닙니다 — 이는 대부분의 프로덕션 시나리오에서 실제로 원하는 것입니다. + +## 제거 일정 + +`@persist` 하이드레이션을 위한 `inputs.id`는 CrewAI의 향후 릴리스에서 제거될 예정입니다. 즉각적인 강제 종료는 없으며 — 기존 흐름은 계속 작동합니다 — 하지만 v1.14.5 이상으로 업그레이드하면, +새 코드에서는 `restore_from_state_id`를 사용해야 하며, 기존 흐름은 다음 편리한 기회에 마이그레이션해야 합니다. + +## AMP + +흐름을 CrewAI AMP에 배포하는 경우, 마이그레이션은 배포된 팀에 전송되는 시작 페이로드로 확장되며, +`inputs.id`를 재사용하는 가시적인 증상은 배포 대시보드에 나타납니다. 아래 두 개의 하위 섹션이 이를 다룹니다. + +### 시작 페이로드 마이그레이션 + +현재 `inputs`에 `id`를 포함하여 배포된 흐름을 시작하는 경우: + +```bash +# 더 이상 지원되지 않음 +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + -d '{"inputs": {"id": "abcd1234-5678-90ef-ghij-klmnopqrstuv", "topic": "AI Agent Frameworks"}}' \ + https://your-crew-url.crewai.com/kickoff +``` + +UUID를 최상위 `restoreFromStateId` 필드로 이동하십시오: + +```bash +# 지원됨 +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + -d '{ + "inputs": {"topic": "AI Agent Frameworks"}, + "restoreFromStateId": "abcd1234-5678-90ef-ghij-klmnopqrstuv" + }' \ + https://your-crew-url.crewai.com/kickoff +``` + +`restoreFromStateId`는 시작 페이로드에서 `inputs` 옆에 위치하며, 내부에 있지 않습니다. +`inputs` 객체는 이제 흐름이 실제로 소비하는 값만 포함합니다. + +### `inputs.id`가 재사용될 때 발생하는 일 + +AMP가 기존 실행과 `inputs.id`가 일치하는 흐름의 시작을 수신하면, +새로운 기록을 생성하는 대신 기존 기록으로 해결됩니다. 배포 대시보드에서 다음을 확인할 수 있습니다: + +- **실행 상태** — 새로운 실행의 상태가 이전 실행의 상태를 덮어씁니다. 완료된 실행은 + 다시 `실행 중`으로 전환되거나, `완료`된 실행은 새로운 시작이 실패할 경우 `오류`로 전환될 수 있습니다 — 어쨌든 대시보드는 더 이상 + 원래 실행을 반영하지 않습니다. +- **추적** — OTel 추적이 시작 간에 쌓이기 때문에 동일한 실행 id를 공유합니다; 이전 실행의 추적은 + 새로운 실행의 추적과 교체되거나 혼합됩니다. 단계별 재생은 더 이상 단일 실행에 해당하지 않습니다. +- **실행 목록** — 별도의 행으로 나타나야 할 시작이 단일 항목으로 축소되어 이력을 숨깁니다. + +`restoreFromStateId`로 마이그레이션하면 모든 시작이 자체 실행으로 유지됩니다 — 각자의 상태, 추적 및 목록의 행을 가지며 — 여전히 이전 실행에서 상태를 하이드레이트합니다. + + + 흐름이 어떤 모드가 필요한지 확실하지 않거나 마이그레이션 중 문제가 발생하면 지원 팀에 문의하십시오. + \ No newline at end of file diff --git a/docs/v1.15.13/ko/guides/flows/mastering-flow-state.mdx b/docs/v1.15.13/ko/guides/flows/mastering-flow-state.mdx new file mode 100644 index 0000000000..5e7727cb10 --- /dev/null +++ b/docs/v1.15.13/ko/guides/flows/mastering-flow-state.mdx @@ -0,0 +1,815 @@ +--- +title: 플로우 상태 관리 마스터하기 +description: 견고한 AI 애플리케이션 구축을 위한 CrewAI 플로우에서 상태를 관리, 유지 및 활용하는 종합 가이드입니다. +icon: diagram-project +mode: "wide" +--- + +## 플로우에서 State의 힘 이해하기 + +State 관리는 모든 고급 AI 워크플로우의 중추입니다. CrewAI Flows에서 state 시스템은 컨텍스트를 유지하고, 단계 간 데이터를 공유하며, 복잡한 애플리케이션 로직을 구축할 수 있도록 해줍니다. State 관리에 능숙해지는 것은 신뢰할 수 있고, 유지보수가 용이하며, 강력한 AI 애플리케이션을 만들기 위해 필수적입니다. + +이 가이드는 CrewAI Flows에서 state를 관리하는 데 꼭 알아야 할 기본 개념부터 고급 기법까지, 실용적인 코드 예제와 함께 단계별로 안내합니다. + +### 상태 관리가 중요한 이유 + +효과적인 상태 관리는 다음을 가능하게 합니다: + +1. **실행 단계 간의 컨텍스트 유지** - 워크플로의 다양한 단계 간에 정보를 원활하게 전달할 수 있습니다. +2. **복잡한 조건부 논리 구성** - 누적된 데이터를 기반으로 의사 결정을 내릴 수 있습니다. +3. **지속적인 애플리케이션 생성** - 워크플로 진행 상황을 저장하고 복원할 수 있습니다. +4. **에러를 우아하게 처리** - 더 견고한 애플리케이션을 위한 복구 패턴을 구현할 수 있습니다. +5. **애플리케이션 확장** - 적절한 데이터 조직을 통해 복잡한 워크플로를 지원할 수 있습니다. +6. **대화형 애플리케이션 활성화** - 컨텍스트 기반 AI 상호작용을 위해 대화 내역을 저장하고 접근할 수 있습니다. + +멀티턴 채팅(`kickoff` per user line, `ChatState`, 의도 라우팅, 지연 트레이싱, `ChatSession`)은 [대화형 Flow](/ko/guides/flows/conversational-flows)를 참고하세요. + +이러한 기능을 효과적으로 활용하는 방법을 살펴보겠습니다. + +## 상태 관리 기본 사항 + +### Flow 상태 라이프사이클 + +CrewAI Flow에서 상태는 예측 가능한 라이프사이클을 따릅니다: + +1. **초기화** - flow가 생성될 때, 상태는 초기화됩니다(빈 딕셔너리 또는 Pydantic 모델 인스턴스로) +2. **수정** - flow 메서드는 실행되는 동안 상태에 접근하고 이를 수정합니다 +3. **전달** - 상태는 flow 메서드들 사이에 자동으로 전달됩니다 +4. **영속화** (선택 사항) - 상태는 스토리지에 저장될 수 있고 나중에 다시 불러올 수 있습니다 +5. **완료** - 최종 상태는 모든 실행된 메서드의 누적 변경 사항을 반영합니다 + +이 라이프사이클을 이해하는 것은 효과적인 flow를 설계하는 데 매우 중요합니다. + +### 상태 관리의 두 가지 접근 방식 + +CrewAI에서는 흐름에서 상태를 관리하는 두 가지 방법을 제공합니다: + +1. **비구조적 상태** - 유연성을 위해 딕셔너리와 유사한 객체 사용 +2. **구조적 상태** - 타입 안전성과 검증을 위해 Pydantic 모델 사용 + +각 접근 방식을 자세히 살펴보겠습니다. + +## 비구조적 상태 관리 + +비구조적 상태는 사전(dictionary)과 유사한 방식을 사용하여, 단순한 애플리케이션에 유연성과 단순성을 제공합니다. + +### 작동 방식 + +비구조화된 상태의 경우: +- `self.state`를 통해 상태에 접근하며, 이는 딕셔너리처럼 동작합니다 +- 언제든지 키를 자유롭게 추가, 수정, 삭제할 수 있습니다 +- 모든 상태는 모든 flow 메서드에서 자동으로 사용할 수 있습니다 + +### 기본 예제 + +다음은 비구조적 상태 관리를 보여주는 간단한 예제입니다: + +```python +from crewai.flow.flow import Flow, listen, start + +class UnstructuredStateFlow(Flow): + @start() + def initialize_data(self): + print("Initializing flow data") + # Add key-value pairs to state + self.state["user_name"] = "Alex" + self.state["preferences"] = { + "theme": "dark", + "language": "English" + } + self.state["items"] = [] + + # The flow state automatically gets a unique ID + print(f"Flow ID: {self.state['id']}") + + return "Initialized" + + @listen(initialize_data) + def process_data(self, previous_result): + print(f"Previous step returned: {previous_result}") + + # Access and modify state + user = self.state["user_name"] + print(f"Processing data for {user}") + + # Add items to a list in state + self.state["items"].append("item1") + self.state["items"].append("item2") + + # Add a new key-value pair + self.state["processed"] = True + + return "Processed" + + @listen(process_data) + def generate_summary(self, previous_result): + # Access multiple state values + user = self.state["user_name"] + theme = self.state["preferences"]["theme"] + items = self.state["items"] + processed = self.state.get("processed", False) + + summary = f"User {user} has {len(items)} items with {theme} theme. " + summary += "Data is processed." if processed else "Data is not processed." + + return summary + +# Run the flow +flow = UnstructuredStateFlow() +result = flow.kickoff() +print(f"Final result: {result}") +print(f"Final state: {flow.state}") +``` + +### 비구조적 상태를 사용할 때 + +비구조적 상태는 다음과 같은 경우에 이상적입니다: +- 빠른 프로토타이핑 및 간단한 플로우 +- 동적으로 변화하는 상태 요구 +- 구조가 사전에 알려지지 않을 수 있는 경우 +- 간단한 상태 요구가 있는 플로우 + +비구조적 상태는 유연하지만, 타입 검사 및 스키마 검증이 없기 때문에 복잡한 애플리케이션에서 오류가 발생할 수 있습니다. + +## 구조화된 상태 관리 + +구조화된 상태는 Pydantic 모델을 사용하여 flow의 상태에 대한 스키마를 정의함으로써 타입 안전성, 검증, 그리고 더 나은 개발자 경험을 제공합니다. + +### 작동 방식 + +구조화된 상태에서는: +- 상태 구조를 나타내는 Pydantic 모델을 정의합니다. +- 이 모델 타입을 유형 매개변수로 Flow 클래스에 전달합니다. +- `self.state`를 통해 상태에 접근할 수 있으며, 이는 Pydantic 모델 인스턴스처럼 동작합니다. +- 모든 필드는 정의된 타입에 따라 검증됩니다. +- IDE 자동 완성 및 타입 체크 지원을 받을 수 있습니다. + +### 기본 예제 + +구조화된 상태 관리를 구현하는 방법은 다음과 같습니다: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel, Field +from typing import List, Dict, Optional + +# Define your state model +class UserPreferences(BaseModel): + theme: str = "light" + language: str = "English" + +class AppState(BaseModel): + user_name: str = "" + preferences: UserPreferences = UserPreferences() + items: List[str] = [] + processed: bool = False + completion_percentage: float = 0.0 + +# Create a flow with typed state +class StructuredStateFlow(Flow[AppState]): + @start() + def initialize_data(self): + print("Initializing flow data") + # Set state values (type-checked) + self.state.user_name = "Taylor" + self.state.preferences.theme = "dark" + + # The ID field is automatically available + print(f"Flow ID: {self.state.id}") + + return "Initialized" + + @listen(initialize_data) + def process_data(self, previous_result): + print(f"Processing data for {self.state.user_name}") + + # Modify state (with type checking) + self.state.items.append("item1") + self.state.items.append("item2") + self.state.processed = True + self.state.completion_percentage = 50.0 + + return "Processed" + + @listen(process_data) + def generate_summary(self, previous_result): + # Access state (with autocompletion) + summary = f"User {self.state.user_name} has {len(self.state.items)} items " + summary += f"with {self.state.preferences.theme} theme. " + summary += "Data is processed." if self.state.processed else "Data is not processed." + summary += f" Completion: {self.state.completion_percentage}%" + + return summary + +# Run the flow +flow = StructuredStateFlow() +result = flow.kickoff() +print(f"Final result: {result}") +print(f"Final state: {flow.state}") +``` + +### 구조화된 상태의 이점 + +구조화된 상태를 사용하면 여러 가지 장점이 있습니다: + +1. **타입 안정성** - 개발 단계에서 타입 오류를 잡을 수 있습니다 +2. **자체 문서화** - 상태 모델이 어떤 데이터가 사용 가능한지 명확히 문서화합니다 +3. **검증** - 데이터 타입과 제약 조건을 자동으로 검증합니다 +4. **IDE 지원** - 자동 완성과 인라인 문서화를 받을 수 있습니다 +5. **기본값** - 누락된 데이터에 대한 대체값을 쉽게 정의할 수 있습니다 + +### 구조화된 상태를 사용할 때 + +구조화된 상태는 다음과 같은 경우에 권장됩니다: +- 명확하게 정의된 데이터 스키마를 가진 복잡한 플로우 +- 여러 개발자가 동일한 코드를 작업하는 팀 프로젝트 +- 데이터 검증이 중요한 애플리케이션 +- 특정 데이터 타입 및 제약 조건을 강제로 적용해야 하는 플로우 + +## 자동 상태 ID + +비구조화 상태와 구조화 상태 모두 상태 인스턴스를 추적하고 관리하는 데 도움이 되는 고유한 식별자(UUID)를 자동으로 부여받습니다. + +### 작동 방식 + +- 비구조화 state의 경우, ID는 `self.state["id"]`로 접근할 수 있습니다. +- 구조화 state의 경우, ID는 `self.state.id`로 접근할 수 있습니다. +- 이 ID는 flow가 생성될 때 자동으로 생성됩니다. +- ID는 flow의 생명주기 동안 동일하게 유지됩니다. +- ID는 추적, 로깅, 저장된 state의 조회에 사용할 수 있습니다. + +이 UUID는 persistence를 구현하거나 여러 flow 실행을 추적할 때 특히 유용합니다. + +## 동적 상태 업데이트 + +구조화된 상태를 사용하든 비구조화된 상태를 사용하든, flow의 실행 중 언제든지 상태를 동적으로 업데이트할 수 있습니다. + +### 단계 간 데이터 전달 + +Flow 메서드는 값을 반환할 수 있으며, 이러한 반환값은 리스닝 메서드의 인자로 전달됩니다: + +```python +from crewai.flow.flow import Flow, listen, start + +class DataPassingFlow(Flow): + @start() + def generate_data(self): + # This return value will be passed to listening methods + return "Generated data" + + @listen(generate_data) + def process_data(self, data_from_previous_step): + print(f"Received: {data_from_previous_step}") + # You can modify the data and pass it along + processed_data = f"{data_from_previous_step} - processed" + # Also update state + self.state["last_processed"] = processed_data + return processed_data + + @listen(process_data) + def finalize_data(self, processed_data): + print(f"Received processed data: {processed_data}") + # Access both the passed data and state + last_processed = self.state.get("last_processed", "") + return f"Final: {processed_data} (from state: {last_processed})" +``` + +이 패턴을 사용하면 직접적인 데이터 전달과 state 업데이트를 결합하여 최대한 유연하게 작업할 수 있습니다. + +## 플로우 상태 지속 + +CrewAI의 가장 강력한 기능 중 하나는 실행 간에 플로우 상태를 지속할 수 있다는 점입니다. 이를 통해 중단, 재개, 심지어 실패 후에도 복구할 수 있는 워크플로우를 구현할 수 있습니다. + +### @persist() 데코레이터 + +`@persist()` 데코레이터는 상태 지속을 자동화하여 flow의 상태를 실행의 주요 지점마다 저장합니다. + +#### 클래스 수준 지속성 + +클래스 수준에서 `@persist()`를 적용하면 모든 메서드 실행 후 상태가 저장됩니다: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + value: int = 0 + +@persist() # Apply to the entire flow class +class PersistentCounterFlow(Flow[CounterState]): + @start() + def increment(self): + self.state.value += 1 + print(f"Incremented to {self.state.value}") + return self.state.value + + @listen(increment) + def double(self, value): + self.state.value = value * 2 + print(f"Doubled to {self.state.value}") + return self.state.value + +# First run +flow1 = PersistentCounterFlow() +result1 = flow1.kickoff() +print(f"First run result: {result1}") + +# Second run - state is automatically loaded +flow2 = PersistentCounterFlow() +result2 = flow2.kickoff() +print(f"Second run result: {result2}") # Will be higher due to persisted state +``` + +#### 메서드 수준 지속성 + +더 세밀한 제어를 위해 `@persist()`를 특정 메서드에 적용할 수 있습니다: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai.flow.persistence import persist + +class SelectivePersistFlow(Flow): + @start() + def first_step(self): + self.state["count"] = 1 + return "First step" + + @persist() # Only persist after this method + @listen(first_step) + def important_step(self, prev_result): + self.state["count"] += 1 + self.state["important_data"] = "This will be persisted" + return "Important step completed" + + @listen(important_step) + def final_step(self, prev_result): + self.state["count"] += 1 + return f"Complete with count {self.state['count']}" +``` + +#### 영속 상태 포크하기 + +`@persist`는 `kickoff` / `kickoff_async`에서 두 가지 별개의 하이드레이션 모드를 지원합니다. 동일한 계보를 계속하려면 **재개**(`inputs["id"]`)를 사용하고, 스냅샷에서 시작하는 새 계보를 시작하려면 **포크**(`restore_from_state_id`)를 사용하세요: + +| | kickoff 후 `state.id` | `@persist` 기록 위치 | +|---|---|---| +| `inputs["id"]` (재개) | 제공된 id | 제공된 id (기록 확장) | +| `restore_from_state_id` (포크) | 새 id, 또는 고정 시 `inputs["id"]` | 새 id (원본 보존) | + +```python +from crewai.flow.flow import Flow, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + id: str = "" + counter: int = 0 + +@persist +class CounterFlow(Flow[CounterState]): + @start() + def step(self): + self.state.counter += 1 + +# 실행 1: 새 상태, counter 0 -> 1 +flow_1 = CounterFlow() +flow_1.kickoff() + +# 포크: flow_1의 최신 스냅샷에서 하이드레이트, 단 새 state.id에 기록 +flow_2 = CounterFlow() +flow_2.kickoff(restore_from_state_id=flow_1.state.id) +# flow_2는 counter=1(하이드레이트)로 시작하고, step()이 2로 증가시킵니다. +# flow_1의 flow_uuid 기록은 변경되지 않습니다. +``` + +동작 노트: + +- `restore_from_state_id`가 영속에서 발견되지 않음 → kickoff는 조용히 기본 동작으로 폴백됩니다 (기존 `inputs["id"]`의 미발견 동작 미러링). 예외는 발생하지 않습니다. +- `restore_from_state_id`를 `from_checkpoint`와 결합하면 `ValueError`가 발생합니다 — 서로 다른 상태 시스템(`@persist` 대 Checkpointing)을 대상으로 하므로 결합할 수 없습니다. +- `restore_from_state_id=None`(기본값)은 매개변수 없는 kickoff와 바이트 단위로 동일합니다. +- 포크 중 `inputs["id"]`를 고정하면 새 실행이 다른 플로우와 영속 키를 공유함을 의미합니다 — 일반적으로 `restore_from_state_id`만 사용하는 것이 좋습니다. + +## 고급 상태 패턴 + +### 상태 기반 조건부 로직 + +state를 사용하여 flow에서 복잡한 조건부 로직을 구현할 수 있습니다: + +```python +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +class PaymentState(BaseModel): + amount: float = 0.0 + is_approved: bool = False + retry_count: int = 0 + +class PaymentFlow(Flow[PaymentState]): + @start() + def process_payment(self): + # Simulate payment processing + self.state.amount = 100.0 + self.state.is_approved = self.state.amount < 1000 + return "Payment processed" + + @router(process_payment) + def check_approval(self, previous_result): + if self.state.is_approved: + return "approved" + elif self.state.retry_count < 3: + return "retry" + else: + return "rejected" + + @listen("approved") + def handle_approval(self): + return f"Payment of ${self.state.amount} approved!" + + @listen("retry") + def handle_retry(self): + self.state.retry_count += 1 + print(f"Retrying payment (attempt {self.state.retry_count})...") + # Could implement retry logic here + return "Retry initiated" + + @listen("rejected") + def handle_rejection(self): + return f"Payment of ${self.state.amount} rejected after {self.state.retry_count} retries." +``` + +### 복잡한 상태 변환 처리 + +복잡한 상태 변환의 경우, 전용 메서드를 만들어 처리할 수 있습니다. + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel +from typing import List, Dict + +class UserData(BaseModel): + name: str + active: bool = True + login_count: int = 0 + +class ComplexState(BaseModel): + users: Dict[str, UserData] = {} + active_user_count: int = 0 + +class TransformationFlow(Flow[ComplexState]): + @start() + def initialize(self): + # Add some users + self.add_user("alice", "Alice") + self.add_user("bob", "Bob") + self.add_user("charlie", "Charlie") + return "Initialized" + + @listen(initialize) + def process_users(self, _): + # Increment login counts + for user_id in self.state.users: + self.increment_login(user_id) + + # Deactivate one user + self.deactivate_user("bob") + + # Update active count + self.update_active_count() + + return f"Processed {len(self.state.users)} users" + + # Helper methods for state transformations + def add_user(self, user_id: str, name: str): + self.state.users[user_id] = UserData(name=name) + self.update_active_count() + + def increment_login(self, user_id: str): + if user_id in self.state.users: + self.state.users[user_id].login_count += 1 + + def deactivate_user(self, user_id: str): + if user_id in self.state.users: + self.state.users[user_id].active = False + self.update_active_count() + + def update_active_count(self): + self.state.active_user_count = sum( + 1 for user in self.state.users.values() if user.active + ) +``` + +이와 같은 헬퍼 메서드 생성 패턴은 flow 메서드를 깔끔하게 유지하면서 복잡한 상태 조작을 가능하게 해줍니다. + +## Crews로 상태 관리하기 + +CrewAI에서 가장 강력한 패턴 중 하나는 flow 상태 관리와 crew 실행을 결합하는 것입니다. + +### 크루에 상태 전달하기 + +플로우 상태를 사용하여 크루에 매개변수를 전달할 수 있습니다: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + +class ResearchState(BaseModel): + topic: str = "" + depth: str = "medium" + results: str = "" + +class ResearchFlow(Flow[ResearchState]): + @start() + def get_parameters(self): + # In a real app, this might come from user input + self.state.topic = "Artificial Intelligence Ethics" + self.state.depth = "deep" + return "Parameters set" + + @listen(get_parameters) + def execute_research(self, _): + # Create agents + researcher = Agent( + role="Research Specialist", + goal=f"Research {self.state.topic} in {self.state.depth} detail", + backstory="You are an expert researcher with a talent for finding accurate information." + ) + + writer = Agent( + role="Content Writer", + goal="Transform research into clear, engaging content", + backstory="You excel at communicating complex ideas clearly and concisely." + ) + + # Create tasks + research_task = Task( + description=f"Research {self.state.topic} with {self.state.depth} analysis", + expected_output="Comprehensive research notes in markdown format", + agent=researcher + ) + + writing_task = Task( + description=f"Create a summary on {self.state.topic} based on the research", + expected_output="Well-written article in markdown format", + agent=writer, + context=[research_task] + ) + + # Create and run crew + research_crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + verbose=True + ) + + # Run crew and store result in state + result = research_crew.kickoff() + self.state.results = result.raw + + return "Research completed" + + @listen(execute_research) + def summarize_results(self, _): + # Access the stored results + result_length = len(self.state.results) + return f"Research on {self.state.topic} completed with {result_length} characters of results." +``` + +### State에서 Crew 출력 처리하기 + +Crew가 완료되면, 해당 출력을 처리하여 flow state에 저장할 수 있습니다: + +```python +@listen(execute_crew) +def process_crew_results(self, _): + # Parse the raw results (assuming JSON output) + import json + try: + results_dict = json.loads(self.state.raw_results) + self.state.processed_results = { + "title": results_dict.get("title", ""), + "main_points": results_dict.get("main_points", []), + "conclusion": results_dict.get("conclusion", "") + } + return "Results processed successfully" + except json.JSONDecodeError: + self.state.error = "Failed to parse crew results as JSON" + return "Error processing results" +``` + +## 상태 관리 모범 사례 + +### 1. 상태를 집중적으로 유지하세요 + +상태를 설계할 때 꼭 필요한 내용만 포함하도록 하세요: + +```python +# Too broad +class BloatedState(BaseModel): + user_data: Dict = {} + system_settings: Dict = {} + temporary_calculations: List = [] + debug_info: Dict = {} + # ...many more fields + +# Better: Focused state +class FocusedState(BaseModel): + user_id: str + preferences: Dict[str, str] + completion_status: Dict[str, bool] +``` + +### 2. 복잡한 플로우를 위한 구조화된 상태 사용 + +플로우의 복잡도가 증가할수록 구조화된 상태의 가치는 점점 커집니다: + +```python +# Simple flow can use unstructured state +class SimpleGreetingFlow(Flow): + @start() + def greet(self): + self.state["name"] = "World" + return f"Hello, {self.state['name']}!" + +# Complex flow benefits from structured state +class UserRegistrationState(BaseModel): + username: str + email: str + verification_status: bool = False + registration_date: datetime = Field(default_factory=datetime.now) + last_login: Optional[datetime] = None + +class RegistrationFlow(Flow[UserRegistrationState]): + # Methods with strongly-typed state access +``` + +### 3. 문서 상태 전이 + +복잡한 흐름의 경우, 실행 중에 상태가 어떻게 변하는지 문서화하세요: + +```python +@start() +def initialize_order(self): + """ + Initialize order state with empty values. + + State before: {} + State after: {order_id: str, items: [], status: 'new'} + """ + self.state.order_id = str(uuid.uuid4()) + self.state.items = [] + self.state.status = "new" + return "Order initialized" +``` + +### 4. 상태 오류를 정상적으로 처리하기 + +상태 접근에 대한 오류 처리를 구현하세요: + +```python +@listen(previous_step) +def process_data(self, _): + try: + # Try to access a value that might not exist + user_preference = self.state.preferences.get("theme", "default") + except (AttributeError, KeyError): + # Handle the error gracefully + self.state.errors = self.state.get("errors", []) + self.state.errors.append("Failed to access preferences") + user_preference = "default" + + return f"Used preference: {user_preference}" +``` + +### 5. 상태를 사용하여 진행 상황 추적 + +긴 실행 흐름에서 진행 상황을 추적하기 위해 상태를 활용하세요: + +```python +class ProgressTrackingFlow(Flow): + @start() + def initialize(self): + self.state["total_steps"] = 3 + self.state["current_step"] = 0 + self.state["progress"] = 0.0 + self.update_progress() + return "Initialized" + + def update_progress(self): + """Helper method to calculate and update progress""" + if self.state.get("total_steps", 0) > 0: + self.state["progress"] = (self.state.get("current_step", 0) / + self.state["total_steps"]) * 100 + print(f"Progress: {self.state['progress']:.1f}%") + + @listen(initialize) + def step_one(self, _): + # Do work... + self.state["current_step"] = 1 + self.update_progress() + return "Step 1 complete" + + # Additional steps... +``` + +### 6. 가능한 경우 불변(Immutable) 연산 사용하기 + +특히 구조화된 상태에서는 명확성을 위해 불변 연산을 선호하세요: + +```python +# 리스트를 즉시 수정하는 대신: +self.state.items.append(new_item) # 변경 가능한 연산 + +# 새로운 상태를 생성하는 것을 고려하세요: +from pydantic import BaseModel +from typing import List + +class ItemState(BaseModel): + items: List[str] = [] + +class ImmutableFlow(Flow[ItemState]): + @start() + def add_item(self): + # 추가된 항목과 함께 새로운 리스트 생성 + self.state.items = [*self.state.items, "new item"] + return "Item added" +``` + +## 플로우 상태 디버깅 + +### 상태 변경 로깅 + +개발할 때 상태 변화를 추적하기 위해 로깅을 추가하세요: + +```python +import logging +logging.basicConfig(level=logging.INFO) + +class LoggingFlow(Flow): + def log_state(self, step_name): + logging.info(f"State after {step_name}: {self.state}") + + @start() + def initialize(self): + self.state["counter"] = 0 + self.log_state("initialize") + return "Initialized" + + @listen(initialize) + def increment(self, _): + self.state["counter"] += 1 + self.log_state("increment") + return f"Incremented to {self.state['counter']}" +``` + +### 상태 시각화 + +디버깅을 위해 상태를 시각화하는 메서드를 추가할 수 있습니다: + +```python +def visualize_state(self): + """Create a simple visualization of the current state""" + import json + from rich.console import Console + from rich.panel import Panel + + console = Console() + + if hasattr(self.state, "model_dump"): + # Pydantic v2 + state_dict = self.state.model_dump() + elif hasattr(self.state, "dict"): + # Pydantic v1 + state_dict = self.state.dict() + else: + # Unstructured state + state_dict = dict(self.state) + + # Remove id for cleaner output + if "id" in state_dict: + state_dict.pop("id") + + state_json = json.dumps(state_dict, indent=2, default=str) + console.print(Panel(state_json, title="Current Flow State")) +``` + +## 결론 + +CrewAI Flows에서 상태 관리를 마스터하면 컨텍스트를 유지하고, 복잡한 결정을 내리며, 일관된 결과를 제공하는 정교하고 견고한 AI 애플리케이션을 구축할 수 있는 힘을 얻게 됩니다. + +비구조화 상태든 구조화 상태든 적절한 상태 관리 방식을 구현하면 유지 관리가 용이하고, 확장 가능하며, 실제 문제를 효과적으로 해결할 수 있는 플로우를 만들 수 있습니다. + +더 복잡한 플로우를 개발할수록 좋은 상태 관리는 유연성과 구조성 사이의 올바른 균형을 찾는 것임을 기억하세요. 이를 통해 코드가 강력하면서도 이해하기 쉬워집니다. + + +이제 CrewAI Flows에서 상태 관리의 개념과 실습을 마스터하셨습니다! 이 지식을 통해 컨텍스트를 효과적으로 유지하고, 단계 간 데이터를 공유하며, 정교한 애플리케이션 로직을 구현하는 견고한 AI 워크플로우를 만들 수 있습니다. + + +## 다음 단계 + +- flow에서 구조화된 state와 비구조화된 state를 모두 실험해 보세요 +- 장기 실행 워크플로를 위해 state 영속성을 구현해 보세요 +- [첫 crew 만들기](/ko/guides/crews/first-crew)를 탐색하여 crew와 flow가 어떻게 함께 작동하는지 확인해 보세요 +- 더 고급 기능을 원한다면 [Flow 참고 문서](/ko/concepts/flows)를 확인해 보세요 \ No newline at end of file diff --git a/docs/v1.15.13/ko/guides/migration/migrating-from-langgraph.mdx b/docs/v1.15.13/ko/guides/migration/migrating-from-langgraph.mdx new file mode 100644 index 0000000000..fe708602d1 --- /dev/null +++ b/docs/v1.15.13/ko/guides/migration/migrating-from-langgraph.mdx @@ -0,0 +1,518 @@ +--- +title: "LangGraph에서 CrewAI로 옮기기: 엔지니어를 위한 실전 가이드" +description: LangGraph로 이미 구축했다면, 프로젝트를 CrewAI로 빠르게 옮기는 방법을 알아보세요 +icon: switch +mode: "wide" +--- + +LangGraph로 에이전트를 구축해 왔습니다. `StateGraph`와 씨름하고, 조건부 에지를 연결하고, 새벽 2시에 상태 딕셔너리를 디버깅해 본 적도 있죠. 동작은 하지만 — 어느 순간부터 프로덕션으로 가는 더 나은 길이 없을까 고민하게 됩니다. + +있습니다. **CrewAI Flows**는 이벤트 기반 오케스트레이션, 조건부 라우팅, 공유 상태라는 동일한 힘을 훨씬 적은 보일러플레이트와 실제로 다단계 AI 워크플로우를 생각하는 방식에 잘 맞는 정신적 모델로 제공합니다. + +이 글은 핵심 개념을 나란히 비교하고 실제 코드 비교를 보여주며, 다음으로 손이 갈 프레임워크가 왜 CrewAI Flows인지 설명합니다. + +--- + +## 정신적 모델의 전환 + +LangGraph는 **그래프**로 생각하라고 요구합니다: 노드, 에지, 그리고 상태 딕셔너리. 모든 워크플로우는 계산 단계 사이의 전이를 명시적으로 연결하는 방향 그래프입니다. 강력하지만, 특히 워크플로우가 몇 개의 결정 지점이 있는 순차적 흐름일 때 이 추상화는 오버헤드를 가져옵니다. + +CrewAI Flows는 **이벤트**로 생각하라고 요구합니다: 시작하는 메서드, 결과를 듣는 메서드, 실행을 라우팅하는 메서드. 워크플로우의 토폴로지는 명시적 그래프 구성 대신 데코레이터 어노테이션에서 드러납니다. 이것은 단순한 문법 설탕이 아니라 — 파이프라인을 설계하고 읽고 유지하는 방식을 바꿉니다. + +핵심 매핑은 다음과 같습니다: + +| LangGraph 개념 | CrewAI Flows 대응 | +| --- | --- | +| `StateGraph` class | `Flow` class | +| `add_node()` | Methods decorated with `@start`, `@listen` | +| `add_edge()` / `add_conditional_edges()` | `@listen()` / `@router()` decorators | +| `TypedDict` state | Pydantic `BaseModel` state | +| `START` / `END` constants | `@start()` decorator / natural method return | +| `graph.compile()` | `flow.kickoff()` | +| Checkpointer / persistence | Built-in memory (LanceDB-backed) | + +실제로 어떻게 보이는지 살펴보겠습니다. + +--- + +## 데모 1: 간단한 순차 파이프라인 + +주제를 받아 조사하고, 요약을 작성한 뒤, 결과를 포맷팅하는 파이프라인을 만든다고 해봅시다. 각 프레임워크는 이렇게 처리합니다. + +### LangGraph 방식 + +```python +from typing import TypedDict +from langgraph.graph import StateGraph, START, END + +class ResearchState(TypedDict): + topic: str + raw_research: str + summary: str + formatted_output: str + +def research_topic(state: ResearchState) -> dict: + # Call an LLM or search API + result = llm.invoke(f"Research the topic: {state['topic']}") + return {"raw_research": result} + +def write_summary(state: ResearchState) -> dict: + result = llm.invoke( + f"Summarize this research:\n{state['raw_research']}" + ) + return {"summary": result} + +def format_output(state: ResearchState) -> dict: + result = llm.invoke( + f"Format this summary as a polished article section:\n{state['summary']}" + ) + return {"formatted_output": result} + +# Build the graph +graph = StateGraph(ResearchState) +graph.add_node("research", research_topic) +graph.add_node("summarize", write_summary) +graph.add_node("format", format_output) + +graph.add_edge(START, "research") +graph.add_edge("research", "summarize") +graph.add_edge("summarize", "format") +graph.add_edge("format", END) + +# Compile and run +app = graph.compile() +result = app.invoke({"topic": "quantum computing advances in 2026"}) +print(result["formatted_output"]) +``` + +함수를 정의하고 노드로 등록한 다음, 모든 전이를 수동으로 연결합니다. 이렇게 단순한 순서인데도 의례처럼 해야 할 작업이 많습니다. + +### CrewAI Flows 방식 + +```python +from crewai import LLM, Agent, Crew, Process, Task +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class ResearchState(BaseModel): + topic: str = "" + raw_research: str = "" + summary: str = "" + formatted_output: str = "" + +class ResearchFlow(Flow[ResearchState]): + @start() + def research_topic(self): + # Option 1: Direct LLM call + result = llm.call(f"Research the topic: {self.state.topic}") + self.state.raw_research = result + return result + + @listen(research_topic) + def write_summary(self, research_output): + # Option 2: A single agent + summarizer = Agent( + role="Research Summarizer", + goal="Produce concise, accurate summaries of research content", + backstory="You are an expert at distilling complex research into clear, " + "digestible summaries.", + llm=llm, + verbose=True, + ) + result = summarizer.kickoff( + f"Summarize this research:\n{self.state.raw_research}" + ) + self.state.summary = str(result) + return self.state.summary + + @listen(write_summary) + def format_output(self, summary_output): + # Option 3: a complete crew (with one or more agents) + formatter = Agent( + role="Content Formatter", + goal="Transform research summaries into polished, publication-ready article sections", + backstory="You are a skilled editor with expertise in structuring and " + "presenting technical content for a general audience.", + llm=llm, + verbose=True, + ) + format_task = Task( + description=f"Format this summary as a polished article section:\n{self.state.summary}", + expected_output="A well-structured, polished article section ready for publication.", + agent=formatter, + ) + crew = Crew( + agents=[formatter], + tasks=[format_task], + process=Process.sequential, + verbose=True, + ) + result = crew.kickoff() + self.state.formatted_output = str(result) + return self.state.formatted_output + +# Run the flow +flow = ResearchFlow() +flow.state.topic = "quantum computing advances in 2026" +result = flow.kickoff() +print(flow.state.formatted_output) + +``` + +눈에 띄는 차이점이 있습니다: 그래프 구성 없음, 에지 연결 없음, 컴파일 단계 없음. 실행 순서는 로직이 있는 곳에서 바로 선언됩니다. `@start()`는 진입점을 표시하고, `@listen(method_name)`은 단계들을 연결합니다. 상태는 타입 안전성, 검증, IDE 자동 완성까지 제공하는 제대로 된 Pydantic 모델입니다. + +--- + +## 데모 2: 조건부 라우팅 + +여기서 흥미로워집니다. 콘텐츠 유형에 따라 서로 다른 처리 경로로 라우팅하는 파이프라인을 만든다고 해봅시다. + +### LangGraph 방식 + +```python +from typing import TypedDict, Literal +from langgraph.graph import StateGraph, START, END + +class ContentState(TypedDict): + input_text: str + content_type: str + result: str + +def classify_content(state: ContentState) -> dict: + content_type = llm.invoke( + f"Classify this content as 'technical', 'creative', or 'business':\n{state['input_text']}" + ) + return {"content_type": content_type.strip().lower()} + +def process_technical(state: ContentState) -> dict: + result = llm.invoke(f"Process as technical doc:\n{state['input_text']}") + return {"result": result} + +def process_creative(state: ContentState) -> dict: + result = llm.invoke(f"Process as creative writing:\n{state['input_text']}") + return {"result": result} + +def process_business(state: ContentState) -> dict: + result = llm.invoke(f"Process as business content:\n{state['input_text']}") + return {"result": result} + +# Routing function +def route_content(state: ContentState) -> Literal["technical", "creative", "business"]: + return state["content_type"] + +# Build the graph +graph = StateGraph(ContentState) +graph.add_node("classify", classify_content) +graph.add_node("technical", process_technical) +graph.add_node("creative", process_creative) +graph.add_node("business", process_business) + +graph.add_edge(START, "classify") +graph.add_conditional_edges( + "classify", + route_content, + { + "technical": "technical", + "creative": "creative", + "business": "business", + } +) +graph.add_edge("technical", END) +graph.add_edge("creative", END) +graph.add_edge("business", END) + +app = graph.compile() +result = app.invoke({"input_text": "Explain how TCP handshakes work"}) +``` + +별도의 라우팅 함수, 명시적 조건부 에지 매핑, 그리고 모든 분기에 대한 종료 에지가 필요합니다. 라우팅 결정 로직이 그 결정을 만들어 내는 노드와 분리됩니다. + +### CrewAI Flows 방식 + +```python +from crewai import LLM, Agent +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class ContentState(BaseModel): + input_text: str = "" + content_type: str = "" + result: str = "" + +class ContentFlow(Flow[ContentState]): + @start() + def classify_content(self): + self.state.content_type = ( + llm.call( + f"Classify this content as 'technical', 'creative', or 'business':\n" + f"{self.state.input_text}" + ) + .strip() + .lower() + ) + return self.state.content_type + + @router(classify_content) + def route_content(self, classification): + if classification == "technical": + return "process_technical" + elif classification == "creative": + return "process_creative" + else: + return "process_business" + + @listen("process_technical") + def handle_technical(self): + agent = Agent( + role="Technical Writer", + goal="Produce clear, accurate technical documentation", + backstory="You are an expert technical writer who specializes in " + "explaining complex technical concepts precisely.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as technical doc:\n{self.state.input_text}") + ) + + @listen("process_creative") + def handle_creative(self): + agent = Agent( + role="Creative Writer", + goal="Craft engaging and imaginative creative content", + backstory="You are a talented creative writer with a flair for " + "compelling storytelling and vivid expression.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as creative writing:\n{self.state.input_text}") + ) + + @listen("process_business") + def handle_business(self): + agent = Agent( + role="Business Writer", + goal="Produce professional, results-oriented business content", + backstory="You are an experienced business writer who communicates " + "strategy and value clearly to professional audiences.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as business content:\n{self.state.input_text}") + ) + +flow = ContentFlow() +flow.state.input_text = "Explain how TCP handshakes work" +flow.kickoff() +print(flow.state.result) + +``` + +`@router()` 데코레이터는 메서드를 결정 지점으로 만듭니다. 리스너와 매칭되는 문자열을 반환하므로, 매핑 딕셔너리도, 별도의 라우팅 함수도 필요 없습니다. 분기 로직이 Python `if` 문처럼 읽히는 이유는, 실제로 `if` 문이기 때문입니다. + +--- + +## 데모 3: AI 에이전트 Crew를 Flow에 통합하기 + +여기서 CrewAI의 진짜 힘이 드러납니다. Flows는 LLM 호출을 연결하는 것에 그치지 않고 자율적인 에이전트 **Crew** 전체를 오케스트레이션합니다. 이는 LangGraph에 기본으로 대응되는 개념이 없습니다. + +```python +from crewai import Agent, Task, Crew +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ArticleState(BaseModel): + topic: str = "" + research: str = "" + draft: str = "" + final_article: str = "" + +class ArticleFlow(Flow[ArticleState]): + + @start() + def run_research_crew(self): + """A full Crew of agents handles research.""" + researcher = Agent( + role="Senior Research Analyst", + goal=f"Produce comprehensive research on: {self.state.topic}", + backstory="You're a veteran analyst known for thorough, " + "well-sourced research reports.", + llm="gpt-4o" + ) + + research_task = Task( + description=f"Research '{self.state.topic}' thoroughly. " + "Cover key trends, data points, and expert opinions.", + expected_output="A detailed research brief with sources.", + agent=researcher + ) + + crew = Crew(agents=[researcher], tasks=[research_task]) + result = crew.kickoff() + self.state.research = result.raw + return result.raw + + @listen(run_research_crew) + def run_writing_crew(self, research_output): + """A different Crew handles writing.""" + writer = Agent( + role="Technical Writer", + goal="Write a compelling article based on provided research.", + backstory="You turn complex research into engaging, clear prose.", + llm="gpt-4o" + ) + + editor = Agent( + role="Senior Editor", + goal="Review and polish articles for publication quality.", + backstory="20 years of editorial experience at top tech publications.", + llm="gpt-4o" + ) + + write_task = Task( + description=f"Write an article based on this research:\n{self.state.research}", + expected_output="A well-structured draft article.", + agent=writer + ) + + edit_task = Task( + description="Review, fact-check, and polish the draft article.", + expected_output="A publication-ready article.", + agent=editor + ) + + crew = Crew(agents=[writer, editor], tasks=[write_task, edit_task]) + result = crew.kickoff() + self.state.final_article = result.raw + return result.raw + +# Run the full pipeline +flow = ArticleFlow() +flow.state.topic = "The Future of Edge AI" +flow.kickoff() +print(flow.state.final_article) +``` + +핵심 인사이트는 다음과 같습니다: **Flows는 오케스트레이션 레이어를, Crews는 지능 레이어를 제공합니다.** Flow의 각 단계는 각자의 역할, 목표, 도구를 가진 협업 에이전트 팀을 띄울 수 있습니다. 구조화되고 예측 가능한 제어 흐름 *그리고* 자율적 에이전트 협업 — 두 세계의 장점을 모두 얻습니다. + +LangGraph에서 비슷한 것을 하려면 노드 함수 안에 에이전트 통신 프로토콜, 도구 호출 루프, 위임 로직을 직접 구현해야 합니다. 가능하긴 하지만, 매번 처음부터 배관을 만드는 셈입니다. + +--- + +## 데모 4: 병렬 실행과 동기화 + +실제 파이프라인은 종종 작업을 병렬로 분기하고 결과를 합쳐야 합니다. CrewAI Flows는 `and_`와 `or_` 연산자로 이를 우아하게 처리합니다. + +```python +from crewai import LLM +from crewai.flow.flow import Flow, and_, listen, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class AnalysisState(BaseModel): + topic: str = "" + market_data: str = "" + tech_analysis: str = "" + competitor_intel: str = "" + final_report: str = "" + +class ParallelAnalysisFlow(Flow[AnalysisState]): + @start() + def start_method(self): + pass + + @listen(start_method) + def gather_market_data(self): + # Your agentic or deterministic code + pass + + @listen(start_method) + def run_tech_analysis(self): + # Your agentic or deterministic code + pass + + @listen(start_method) + def gather_competitor_intel(self): + # Your agentic or deterministic code + pass + + @listen(and_(gather_market_data, run_tech_analysis, gather_competitor_intel)) + def synthesize_report(self): + # Your agentic or deterministic code + pass + +flow = ParallelAnalysisFlow() +flow.state.topic = "AI-powered developer tools" +flow.kickoff() + +``` + +여러 `@start()` 데코레이터는 병렬로 실행됩니다. `@listen` 데코레이터의 `and_()` 결합자는 `synthesize_report`가 *세 가지* 상위 메서드가 모두 완료된 뒤에만 실행되도록 보장합니다. *어떤* 상위 작업이든 끝나는 즉시 진행하고 싶다면 `or_()`도 사용할 수 있습니다. + +LangGraph에서는 병렬 분기, 동기화 노드, 신중한 상태 병합이 포함된 fan-out/fan-in 패턴을 만들어야 하며 — 모든 것을 에지로 명시적으로 연결해야 합니다. + +--- + +## 프로덕션에서 CrewAI Flows를 쓰는 이유 + +깔끔한 문법을 넘어, Flows는 여러 프로덕션 핵심 이점을 제공합니다: + +**내장 상태 지속성.** Flow 상태는 LanceDB에 의해 백업되므로 워크플로우가 크래시에서 살아남고, 재개될 수 있으며, 실행 간에 지식을 축적할 수 있습니다. LangGraph는 별도의 체크포인터를 구성해야 합니다. + +**타입 안전한 상태 관리.** Pydantic 모델은 즉시 검증, 직렬화, IDE 지원을 제공합니다. LangGraph의 `TypedDict` 상태는 런타임 검증을 하지 않습니다. + +**일급 에이전트 오케스트레이션.** Crews는 기본 프리미티브입니다. 역할, 목표, 배경, 도구를 가진 에이전트를 정의하고, Flow의 구조적 틀 안에서 자율적으로 협업하게 합니다. 다중 에이전트 조율을 다시 만들 필요가 없습니다. + +**더 단순한 정신적 모델.** 데코레이터는 의도를 선언합니다. `@start`는 "여기서 시작", `@listen(x)`는 "x 이후 실행", `@router(x)`는 "x 이후 어디로 갈지 결정"을 의미합니다. 코드는 자신이 설명하는 워크플로우처럼 읽힙니다. + +**CLI 통합.** `crewai run`으로 Flows를 실행합니다. 별도의 컴파일 단계나 그래프 직렬화가 없습니다. Flow는 Python 클래스이며, 그대로 실행됩니다. + +--- + +## 마이그레이션 치트 시트 + +LangGraph 코드베이스를 CrewAI Flows로 옮기고 싶다면, 다음의 실전 변환 가이드를 참고하세요: + +1. **상태를 매핑하세요.** `TypedDict`를 Pydantic `BaseModel`로 변환하고 모든 필드에 기본값을 추가하세요. +2. **노드를 메서드로 변환하세요.** 각 `add_node` 함수는 `Flow` 서브클래스의 메서드가 됩니다. `state["field"]` 읽기는 `self.state.field`로 바꾸세요. +3. **에지를 데코레이터로 교체하세요.** `add_edge(START, "first_node")`는 첫 메서드의 `@start()`가 됩니다. 순차적인 `add_edge("a", "b")`는 `b` 메서드의 `@listen(a)`가 됩니다. +4. **조건부 에지는 `@router`로 교체하세요.** 라우팅 함수와 `add_conditional_edges()` 매핑은 하나의 `@router()` 메서드로 통합하고, 라우트 문자열을 반환하세요. +5. **compile + invoke를 kickoff으로 교체하세요.** `graph.compile()`를 제거하고 `flow.kickoff()`를 호출하세요. +6. **Crew가 들어갈 지점을 고려하세요.** 복잡한 다단계 에이전트 로직이 있는 노드는 Crew로 분리할 후보입니다. 이 부분에서 가장 큰 품질 향상을 체감할 수 있습니다. + +--- + +## 시작하기 + +CrewAI를 설치하고 새 Flow 프로젝트를 스캐폴딩하세요: + +```bash +pip install crewai +crewai create flow my_first_flow +cd my_first_flow +``` + +이렇게 하면 바로 편집 가능한 Flow 클래스, 설정 파일, 그리고 `type = "flow"`가 이미 설정된 `pyproject.toml`이 포함된 프로젝트 구조가 생성됩니다. 다음으로 실행하세요: + +```bash +crewai run +``` + +그 다음부터는 에이전트를 추가하고 리스너를 연결한 뒤, 배포하면 됩니다. + +--- + +## 마무리 + +LangGraph는 AI 워크플로우에 구조가 필요하다는 사실을 생태계에 일깨워 주었습니다. 중요한 교훈이었습니다. 하지만 CrewAI Flows는 그 교훈을 더 빠르게 쓰고, 더 쉽게 읽으며, 프로덕션에서 더 강력한 형태로 제공합니다 — 특히 워크플로우에 여러 에이전트의 협업이 포함될 때 그렇습니다. + +단일 에이전트 체인을 넘는 무엇인가를 만들고 있다면, Flows를 진지하게 검토해 보세요. 데코레이터 기반 모델, Crews의 네이티브 통합, 내장 상태 관리를 통해 배관 작업에 쓰는 시간을 줄이고, 중요한 문제에 더 많은 시간을 쓸 수 있습니다. + +`crewai create flow`로 시작하세요. 후회하지 않을 겁니다. diff --git a/docs/v1.15.13/ko/guides/migration/upgrading-crewai.mdx b/docs/v1.15.13/ko/guides/migration/upgrading-crewai.mdx new file mode 100644 index 0000000000..6e96a4480b --- /dev/null +++ b/docs/v1.15.13/ko/guides/migration/upgrading-crewai.mdx @@ -0,0 +1,190 @@ +--- +title: "CrewAI 업그레이드" +description: "프로젝트에서 CrewAI를 업그레이드하고 버전 간 브레이킹 체인지에 적응하는 방법." +icon: "arrow-up-circle" +--- + +## 개요 + +CrewAI 릴리스는 정기적으로 새로운 기능을 제공합니다. 이 가이드는 CLI와 프로젝트의 가상 환경을 모두 최신 상태로 유지하기 위한 실용적인 단계를 안내합니다. + +새로 시작한다면 [설치](/ko/installation)를 참고하세요. 다른 프레임워크에서 옮겨오는 경우라면 [LangGraph에서 마이그레이션](/ko/guides/migration/migrating-from-langgraph)을 참고하세요. + +--- + +## 업그레이드할 수 있는 두 가지 + +CrewAI는 사용자의 머신에 두 곳에 존재하며, 각각 독립적으로 업그레이드됩니다: + +| 무엇 | 설치 방법 | 업그레이드 방법 | +|---|---|---| +| **전역 `crewai` CLI** | `uv tool install crewai` | `uv tool install crewai --upgrade` | +| **프로젝트 venv** (코드가 실행되는 곳) | `crewai install` / `uv sync` | `uv add "crewai[...]>=X.Y.Z"` 후 `crewai install` | + +이 둘은 — 그리고 자주 — 동기화가 어긋날 수 있습니다. `crewai --version`은 CLI 버전을 알려줍니다. 프로젝트 안에서 `uv pip show crewai`를 실행하면 venv 버전을 알려줍니다. 둘이 다른 것은 정상이며, 실행 중인 코드에 중요한 것은 venv 버전입니다. + +## 왜 `crewai install`만으로는 업그레이드되지 않는가 + +`crewai install`은 `uv sync`를 감싼 얇은 래퍼입니다. 현재 `uv.lock` 파일이 지시하는 것 그대로를 설치할 뿐이며 — 어떤 버전 제약도 올리지 **않습니다**. + +`pyproject.toml`이 `crewai>=1.11.1`이라 적혀 있고 lock 파일이 `1.11.1`로 해소되었다면, `crewai install`을 실행해도 `1.14.4`가 사용 가능하더라도 영원히 `1.11.1`에 머무릅니다. + +실제로 업그레이드하려면 다음을 해야 합니다: + +1. `pyproject.toml`의 버전 제약 업데이트 +2. lock 파일 재해소 +3. venv 동기화 + +`uv add`는 이 세 가지를 한 번에 처리합니다. + +## 프로젝트 업그레이드 방법 + +```bash +# 제약을 올리고 lock을 다시 만드는 한 번의 명령 +uv add "crewai[tools]>=1.14.4" + +# venv 동기화 (crewai install은 내부적으로 uv sync를 호출) +crewai install + +# 확인 +uv pip show crewai +# → Version: 1.14.4 +``` + +`[tools]`를 프로젝트에서 사용하는 extras로 바꾸세요 (예: `[tools,anthropic]`). 잘 모르겠다면 `pyproject.toml`의 `dependencies` 목록을 확인하세요. + + + `uv add`는 `pyproject.toml`과 `uv.lock`을 **둘 다** 원자적으로 업데이트합니다. `pyproject.toml`을 수동으로 편집하는 경우, `crewai install`이 새 버전을 가져가도록 하기 전에 `uv lock --upgrade-package crewai`를 실행해 lock 파일을 다시 해소해야 합니다. + + +## 전역 CLI 업그레이드 + +전역 CLI는 프로젝트와 분리되어 있습니다. 다음 명령으로 업그레이드하세요: + +```bash +uv tool install crewai --upgrade +``` + +업그레이드 후 셸이 `PATH`에 대해 경고하면 새로고침하세요: + +```bash +uv tool update-shell +``` + +이 명령은 프로젝트의 venv를 **건드리지 않습니다** — 프로젝트 내부에서는 여전히 `uv add` + `crewai install`이 필요합니다. + +## 둘이 동기화되었는지 확인 + +```bash +# 전역 CLI 버전 +crewai --version + +# 프로젝트 venv 버전 +uv pip show crewai | grep Version +``` + +둘이 일치할 필요는 없지만 — 런타임 동작에 중요한 것은 프로젝트 venv 버전입니다. + + + CrewAI는 `Python >=3.10, <3.14`를 요구합니다. `uv`가 더 오래된 인터프리터로 설치되어 있다면, `crewai install`을 실행하기 전에 지원되는 Python으로 프로젝트 venv를 다시 만드세요. + + +--- + +## 브레이킹 체인지 및 마이그레이션 노트 + +대부분의 업그레이드는 작은 조정만 필요합니다. 아래 항목들은 조용히 깨지거나 헷갈리는 트레이스백을 내는 영역들입니다. + +### Import 경로: tools와 `BaseTool` + +tools의 정식 import 위치는 `crewai.tools`입니다. 옛 경로들이 아직 튜토리얼에 등장하지만 업데이트해야 합니다. + +```python +# 이전 +from crewai_tools import BaseTool +from crewai.agents.tools import tool + +# 이후 +from crewai.tools import BaseTool, tool +``` + +`@tool` 데코레이터와 `BaseTool` 서브클래스는 모두 `crewai.tools`에 있습니다. `AgentFinish` 등 내부 에이전트 심볼들은 더 이상 공개 표면이 아닙니다 — import 중이었다면 event listener나 `Task` 콜백으로 전환하세요. + +### `Agent` 파라미터 변경 + +```python +from crewai import Agent + +agent = Agent( + role="Researcher", + goal="Find authoritative sources on {topic}", + backstory="You are a careful, source-driven researcher.", + llm="gpt-4o-mini", # 모델명 문자열 또는 LLM 객체 + verbose=True, # 정수 레벨이 아닌 bool + max_iter=15, # 버전마다 기본값이 바뀌었음 — 명시적으로 지정 + allow_delegation=False, +) +``` + +- `llm`은 문자열 모델명(설정된 provider를 통해 해소)이나 세밀한 제어를 위한 `LLM` 객체를 받습니다. +- `verbose`는 일반 `bool`입니다. 정수를 전달해도 더 이상 로그 레벨을 토글하지 않습니다. +- `max_iter`의 기본값은 릴리스 사이에 변경되었습니다. 첫 tool 호출 후 에이전트가 조용히 반복을 멈춘다면 `max_iter`를 명시적으로 지정하세요. + +### `Crew` 파라미터 + +```python +from crewai import Crew, Process + +crew = Crew( + agents=[...], + tasks=[...], + process=Process.sequential, # 또는 Process.hierarchical + memory=True, + cache=True, + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}}, +) +``` + +- `process=Process.hierarchical`은 `manager_llm=` 또는 `manager_agent=` 중 하나가 필요합니다. 둘 다 없으면 kickoff 시 검증 단계에서 오류가 발생합니다. +- 기본이 아닌 임베딩 provider와 함께 `memory=True`를 쓰려면 `embedder` dict가 필요합니다 — 아래의 [메모리와 embedder 설정](#memory-embedder-config)을 참고하세요. + +### `Task` 구조화된 출력 + +`output_pydantic`, `output_json`, 또는 `output_file`을 사용해 task 결과를 타입이 지정된 형태로 강제할 수 있습니다: + +```python +from pydantic import BaseModel +from crewai import Task + +class Article(BaseModel): + title: str + body: str + +write = Task( + description="Write an article about {topic}", + expected_output="A short article with a title and body", + agent=writer, + output_pydantic=Article, # 인스턴스가 아닌 클래스 + output_file="output/article.md", +) +``` + +`output_pydantic`은 **클래스** 자체를 받습니다. `Article(title="", body="")`을 전달하는 것은 흔한 실수이며 헷갈리는 검증 오류로 실패합니다. + +### 메모리와 embedder 설정 {#memory-embedder-config} + +`memory=True`이고 OpenAI의 기본 임베딩을 사용하지 않는다면, `embedder`를 반드시 전달해야 합니다: + +```python +crew = Crew( + agents=[...], + tasks=[...], + memory=True, + embedder={ + "provider": "ollama", + "config": {"model": "nomic-embed-text"}, + }, +) +``` + +해당 provider의 자격 증명(`OPENAI_API_KEY`, `OLLAMA_HOST` 등)을 `.env` 파일에 설정하세요. 메모리 저장 경로는 기본적으로 프로젝트-로컬입니다 — embedder를 바꾸면 차원이 호환되지 않으므로 프로젝트의 메모리 디렉터리를 삭제하세요. diff --git a/docs/v1.15.13/ko/guides/tools/publish-custom-tools.mdx b/docs/v1.15.13/ko/guides/tools/publish-custom-tools.mdx new file mode 100644 index 0000000000..9dbec2a782 --- /dev/null +++ b/docs/v1.15.13/ko/guides/tools/publish-custom-tools.mdx @@ -0,0 +1,244 @@ +--- +title: 커스텀 도구 배포하기 +description: PyPI에 게시할 수 있는 CrewAI 호환 도구를 빌드, 패키징, 배포하는 방법을 안내합니다. +icon: box-open +mode: "wide" +--- + +## 개요 + +CrewAI의 도구 시스템은 확장 가능하도록 설계되었습니다. 다른 사용자에게도 유용한 도구를 만들었다면, 독립적인 Python 라이브러리로 패키징하여 PyPI에 게시하고 모든 CrewAI 사용자가 사용할 수 있도록 할 수 있습니다. CrewAI 저장소에 PR을 보낼 필요가 없습니다. + +이 가이드에서는 도구 계약 구현, 패키지 구조화, PyPI 게시까지의 전체 과정을 안내합니다. + + +프로젝트 내에서만 사용할 커스텀 도구가 필요하다면 [커스텀 도구 생성](/ko/learn/create-custom-tools) 가이드를 참고하세요. + + +## 도구 계약 + +모든 CrewAI 도구는 다음 두 가지 인터페이스 중 하나를 충족해야 합니다: + +### 옵션 1: `BaseTool` 서브클래싱 + +`crewai.tools.BaseTool`을 서브클래싱하고 `_run` 메서드를 구현합니다. `name`, `description`, 그리고 선택적으로 입력 검증을 위한 `args_schema`를 정의합니다. + +```python +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + + +class GeolocateInput(BaseModel): + """GeolocateTool의 입력 스키마.""" + address: str = Field(..., description="지오코딩할 도로명 주소.") + + +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "도로명 주소를 위도/경도 좌표로 변환합니다." + args_schema: type[BaseModel] = GeolocateInput + + def _run(self, address: str) -> str: + # 구현 로직 + return f"40.7128, -74.0060" +``` + +### 옵션 2: `@tool` 데코레이터 사용 + +간단한 도구의 경우, `@tool` 데코레이터로 함수를 CrewAI 도구로 변환할 수 있습니다. 함수에는 반드시 독스트링(도구 설명으로 사용됨)과 타입 어노테이션이 있어야 합니다. + +```python +from crewai.tools import tool + + +@tool("Geolocate") +def geolocate(address: str) -> str: + """도로명 주소를 위도/경도 좌표로 변환합니다.""" + return "40.7128, -74.0060" +``` + +### 핵심 요구사항 + +어떤 방식을 사용하든, 도구는 다음을 충족해야 합니다: + +- **`name`** — 짧고 설명적인 식별자. +- **`description`** — 에이전트에게 도구를 언제, 어떻게 사용할지 알려줍니다. 에이전트가 도구를 얼마나 잘 활용하는지에 직접적으로 영향을 미치므로 명확하고 구체적으로 작성하세요. +- **`_run`** (BaseTool) 또는 **함수 본문** (@tool) 구현 — 동기 실행 로직. +- 모든 매개변수와 반환 값에 **타입 어노테이션** 사용. +- **문자열** 결과를 반환 (또는 의미 있게 문자열로 변환 가능한 값). + +### 선택사항: 비동기 지원 + +I/O 바운드 작업을 수행하는 도구의 경우 비동기 실행을 위해 `_arun`을 구현합니다: + +```python +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "도로명 주소를 위도/경도 좌표로 변환합니다." + + def _run(self, address: str) -> str: + # 동기 구현 + ... + + async def _arun(self, address: str) -> str: + # 비동기 구현 + ... +``` + +### 선택사항: `args_schema`를 통한 입력 검증 + +Pydantic 모델을 `args_schema`로 정의하면 자동 입력 검증과 명확한 에러 메시지를 받을 수 있습니다. 제공하지 않으면 CrewAI가 `_run` 메서드의 시그니처에서 추론합니다. + +```python +from pydantic import BaseModel, Field + + +class TranslateInput(BaseModel): + """TranslateTool의 입력 스키마.""" + text: str = Field(..., description="번역할 텍스트.") + target_language: str = Field( + default="en", + description="대상 언어의 ISO 639-1 언어 코드.", + ) +``` + +배포용 도구에는 명시적 스키마를 권장합니다 — 에이전트 동작이 개선되고 사용자에게 더 명확한 문서를 제공합니다. + +### 선택사항: 환경 변수 + +도구에 API 키나 기타 설정이 필요한 경우, `env_vars`로 선언하여 사용자가 무엇을 설정해야 하는지 알 수 있도록 합니다: + +```python +from crewai.tools import BaseTool, EnvVar + + +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "도로명 주소를 위도/경도 좌표로 변환합니다." + env_vars: list[EnvVar] = [ + EnvVar( + name="GEOCODING_API_KEY", + description="지오코딩 서비스 API 키.", + required=True, + ), + ] + + def _run(self, address: str) -> str: + ... +``` + +## 패키지 구조 + +프로젝트를 표준 Python 패키지로 구성합니다. 권장 레이아웃: + +``` +crewai-geolocate/ +├── pyproject.toml +├── LICENSE +├── README.md +└── src/ + └── crewai_geolocate/ + ├── __init__.py + └── tools.py +``` + +### `pyproject.toml` + +```toml +[project] +name = "crewai-geolocate" +version = "0.1.0" +description = "도로명 주소를 지오코딩하는 CrewAI 도구." +requires-python = ">=3.10" +dependencies = [ + "crewai", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" +``` + +사용자가 자동으로 호환 버전을 받을 수 있도록 `crewai`를 의존성으로 선언합니다. + +### `__init__.py` + +사용자가 직접 import할 수 있도록 도구 클래스를 re-export합니다: + +```python +from crewai_geolocate.tools import GeolocateTool + +__all__ = ["GeolocateTool"] +``` + +### 명명 규칙 + +- **패키지 이름**: `crewai-` 접두사를 사용합니다 (예: `crewai-geolocate`). PyPI에서 검색할 때 도구를 쉽게 찾을 수 있습니다. +- **모듈 이름**: 밑줄을 사용합니다 (예: `crewai_geolocate`). +- **도구 클래스 이름**: `Tool`로 끝나는 PascalCase를 사용합니다 (예: `GeolocateTool`). + +## 도구 테스트 + +게시 전에 도구가 크루 내에서 작동하는지 확인합니다: + +```python +from crewai import Agent, Crew, Task +from crewai_geolocate import GeolocateTool + +agent = Agent( + role="Location Analyst", + goal="주어진 주소의 좌표를 찾습니다.", + backstory="지리공간 데이터 전문가.", + tools=[GeolocateTool()], +) + +task = Task( + description="1600 Pennsylvania Avenue, Washington, DC의 좌표를 찾으세요.", + expected_output="해당 주소의 위도와 경도.", + agent=agent, +) + +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() +print(result) +``` + +## PyPI에 게시하기 + +도구 테스트를 완료하고 준비가 되면: + +```bash +# 패키지 빌드 +uv build + +# PyPI에 게시 +uv publish +``` + +처음 게시하는 경우 [PyPI 계정](https://pypi.org/account/register/)과 [API 토큰](https://pypi.org/help/#apitoken)이 필요합니다. + +### 게시 후 + +사용자는 다음과 같이 도구를 설치할 수 있습니다: + +```bash +pip install crewai-geolocate +``` + +또는 uv를 사용하여: + +```bash +uv add crewai-geolocate +``` + +그런 다음 크루에서 사용합니다: + +```python +from crewai_geolocate import GeolocateTool + +agent = Agent( + role="Location Analyst", + tools=[GeolocateTool()], + # ... +) +``` diff --git a/docs/v1.15.13/ko/index.mdx b/docs/v1.15.13/ko/index.mdx new file mode 100644 index 0000000000..3e65e17f5b --- /dev/null +++ b/docs/v1.15.13/ko/index.mdx @@ -0,0 +1,102 @@ +--- +title: "CrewAI 문서" +description: "협업형 AI 에이전트, 크루, 플로우를 설계하고 즉시 프로덕션에 배포하세요." +icon: "house" +mode: "wide" +--- + +
+ CrewAI +
+

신뢰할 수 있는 멀티에이전트 시스템 구축

+

+ 에이전트를 설계하고 크루를 오케스트레이션하며 guardrails, 메모리, 지식, Observability가 기본 내장된 플로우를 자동화하세요. +

+
+ + +
+ +
+ + + + CrewAI의 핵심 개념, 아키텍처, 에이전트·크루·플로우로 만들 수 있는 것들을 빠르게 파악하세요. + + + `uv` 설치, API 키 설정, 로컬 개발을 위한 CLI 초기화까지 모든 단계를 안내합니다. + + + 몇 분 만에 첫 크루를 실행하세요. 런타임, 프로젝트 구조, 개발 루프를 배울 수 있습니다. + + + +## 기본 구축 + + + + 도구, 메모리, 지식, 구조화된 출력을 갖춘 에이전트를 구성하는 방법과 베스트 프랙티스를 배워보세요. + + + start/listen/router 단계, 상태 관리, 실행 저장 및 재개 등 복잡한 워크플로우를 설계하세요. + + + guardrails, 콜백, human-in-the-loop가 포함된 순차적·계층적 프로세스를 정의하세요. + + + +## 엔터프라이즈 여정 + + + + 환경을 관리하고 안전하게 재배포하며, Enterprise 콘솔에서 실시간 실행을 모니터링하세요. + + + Gmail, Slack, Salesforce 등 다양한 서비스를 연결하고 trigger payload를 자동으로 크루와 플로우에 전달하세요. + + + 팀원을 초대하고 RBAC을 설정하며, 프로덕션 자동화에 대한 접근을 제어하세요. + + + +## 최신 소식 + + + + Gmail, Drive, Outlook, Teams, OneDrive, HubSpot 등 다수의 통합을 하나의 문서에서 확인하고, payload/crew 예제를 살펴보세요. + + + 기존 CrewAI 자동화 또는 Amazon Bedrock Agent를 크루에서 직접 호출하는 방법을 안내합니다. + + + + + examples & cookbooks 섹션에서 에이전트, 플로우, Enterprise 자동화의 엔드-투-엔드 구현을 확인해 보세요. + + +## 커뮤니티 + + + + CrewAI가 도움이 되었다면 GitHub에서 별을 남기고 빌드를 공유해주세요. + + + 질문을 올리고, 워크플로우를 공유하며, 다른 빌더와 함께 새로운 기능을 제안하세요. + + diff --git a/docs/v1.15.13/ko/installation.mdx b/docs/v1.15.13/ko/installation.mdx new file mode 100644 index 0000000000..ea33699972 --- /dev/null +++ b/docs/v1.15.13/ko/installation.mdx @@ -0,0 +1,209 @@ +--- +title: 설치 +description: CrewAI 시작하기 - 설치, 구성, 그리고 첫 번째 AI crew 구축하기 +icon: wrench +mode: "wide" +--- + +### 영상: 코딩 에이전트 스킬을 활용한 CrewAI Agents & Flows 구축 + +코딩 에이전트 스킬(Claude Code, Codex 등)을 설치하여 CrewAI로 코딩 에이전트를 빠르게 시작하세요. + +`npx skills add crewaiinc/skills` 명령어로 설치할 수 있습니다 + + + +## 비디오 튜토리얼 + +설치 과정을 단계별로 시연하는 비디오 튜토리얼을 시청하세요: + + + +## 텍스트 튜토리얼 + + + **Python 버전 요구 사항** + +CrewAI는 `Python >=3.10 및 <3.14`가 필요합니다. 버전을 확인하는 방법은 다음과 같습니다: + +```bash +python3 --version +``` + +Python을 업데이트해야 하는 경우, [python.org/downloads](https://python.org/downloads)를 방문하세요. + + + +CrewAI는 의존성 관리와 패키지 처리를 위해 `uv`를 사용합니다. 프로젝트 설정과 실행을 간소화하여 원활한 경험을 제공합니다. + +아직 `uv`를 설치하지 않았다면 **1단계**를 따라 빠르게 시스템에 설치할 수 있습니다. 이미 설치되어 있다면 **2단계**로 건너뛸 수 있습니다. + + + + - **macOS/Linux에서:** + + `curl`을 이용해 스크립트를 다운로드하고 `sh`로 실행하세요: + + ```shell + curl -LsSf https://astral.sh/uv/install.sh | sh + ``` + 시스템에 `curl`이 없다면, `wget`을 사용할 수 있습니다: + + ```shell + wget -qO- https://astral.sh/uv/install.sh | sh + ``` + + - **Windows에서:** + + `irm`으로 스크립트를 다운로드하고 `iex`로 실행하세요: + + ```shell + powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" + ``` + 문제가 발생하면 [UV 설치 가이드](https://docs.astral.sh/uv/getting-started/installation/)를 참고하세요. + + + + - 다음 명령어를 실행하여 `crewai` CLI를 설치하세요: + ```shell + uv tool install crewai + ``` + + `PATH` 경고가 발생하면 쉘을 업데이트하기 위해 아래 명령어를 실행하세요: + ```shell + uv tool update-shell + ``` + + + + Windows에서 `chroma-hnswlib==0.7.6` 빌드 오류(`fatal error C1083: Cannot open include file: 'float.h'`)가 발생하면, [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/)에서 *C++를 사용한 데스크톱 개발*을 설치하세요. + + + - `crewai`가 정상적으로 설치되었는지 확인하려면 다음을 실행하세요: + ```shell + uv tool list + ``` + - 다음과 같이 표시되어야 합니다: + ```shell + crewai v0.102.0 + - crewai + ``` + - `crewai`를 업데이트해야 하는 경우, 다음을 실행하세요: + ```shell + uv tool install crewai --upgrade + ``` + 설치가 완료되었습니다! 이제 첫 번째 crew를 만들 준비가 되었습니다! 🎉 + + + + +# CrewAI 프로젝트 생성하기 + +`crewai create crew`는 이제 JSON-first crew 프로젝트를 생성합니다. 에이전트는 `agents/*.jsonc`에, 태스크와 crew 수준 설정은 `crew.jsonc`에 두며, `crewai run`은 이 JSON 정의를 직접 로드합니다. + + + + - `crewai` CLI 명령어를 실행하세요: + ```shell + crewai create crew + ``` + + - 이 명령어를 실행하면 다음과 같은 구조로 새로운 프로젝트가 생성됩니다: + ``` + my_project/ + ├── .gitignore + ├── .env + ├── agents/ + │ └── researcher.jsonc + ├── crew.jsonc + ├── knowledge/ + ├── pyproject.toml + ├── README.md + ├── skills/ + └── tools/ + ``` + + - `crew.py`, `config/agents.yaml`, `config/tasks.yaml`을 사용하는 기존 Python/YAML 스캐폴드가 필요하다면 다음을 실행하세요: + ```shell + crewai create crew --classic + ``` + + + + + - 프로젝트에는 다음과 같은 주요 파일들이 포함되어 있습니다: + | 파일 | 용도 | + | --- | --- | + | `crew.jsonc` | crew, 태스크 순서, 프로세스, 기본 입력값 설정 | + | `agents/*.jsonc` | 각 에이전트의 역할, 목표, backstory, LLM, 도구, 동작 정의 | + | `.env` | API 키 및 환경 변수 저장 | + | `tools/` | `custom:` 도구를 위한 선택적 Python 파일 | + | `knowledge/` | 에이전트용 선택적 지식 파일 | + | `skills/` | crew에 적용할 선택적 skill 파일 | + + - `crew.jsonc`와 `agents/` 안의 파일을 편집하여 crew 동작을 정의하세요. + - 에이전트와 태스크 텍스트에 `{placeholder}`를 사용하고, `crew.jsonc`의 `inputs`에 기본값을 넣으세요. `crewai run` 실행 시 빠진 값은 CLI가 묻습니다. + - API 키와 같은 민감한 정보는 `.env` 파일에 보관하세요. + + + + + - crew를 실행하기 전에 아래 명령을 먼저 실행하세요: + ```bash + crewai install + ``` + - 추가 패키지를 설치해야 하는 경우 다음을 사용하세요: + ```shell + uv add + ``` + - crew를 실행하려면 프로젝트 루트에서 아래 명령을 실행하세요: + ```bash + crewai run + ``` + + + +## 엔터프라이즈 설치 옵션 + + +팀과 조직을 위해, CrewAI는 설치 복잡성을 없애는 엔터프라이즈 배포 옵션을 제공합니다: + +### CrewAI AMP (SaaS) + +- 설치가 전혀 필요하지 않습니다 - [app.crewai.com](https://app.crewai.com)에서 무료로 가입하세요 +- 자동 업데이트 및 유지 보수 +- 관리형 인프라 및 확장성 지원 +- 코딩 없이 Crew 생성 + +### CrewAI Factory (자가 호스팅) + +- 귀하의 인프라를 위한 컨테이너화된 배포 +- 온프레미스 배포를 포함하여 모든 하이퍼스케일러 지원 +- 기존 보안 시스템과의 통합 + + + CrewAI의 엔터프라이즈 서비스에 대해 알아보고 데모를 예약하세요 + + + +## 다음 단계 + + + + Flow를 만들고 에이전트 한 명짜리 crew를 실행해 보고서까지 만드는 방법을 따라 해 보세요. + + + 다른 개발자들과 소통하고, 도움을 받으며, CrewAI 경험을 공유하세요. + + diff --git a/docs/v1.15.13/ko/introduction.mdx b/docs/v1.15.13/ko/introduction.mdx new file mode 100644 index 0000000000..abd7090145 --- /dev/null +++ b/docs/v1.15.13/ko/introduction.mdx @@ -0,0 +1,152 @@ +--- +title: 소개 +description: 함께 협력하여 복잡한 작업을 해결하는 AI agent 팀 구축 +icon: handshake +mode: "wide" +--- + +# CrewAI란 무엇인가? + +**CrewAI는 자율 AI agent를 조직하고 복잡한 workflow를 구축하기 위한 최고의 오픈 소스 프레임워크입니다.** + +**Crews**의 협업 지능과 **Flows**의 정밀한 제어를 결합하여 개발자가 프로덕션 수준의 멀티 에이전트 시스템을 구축할 수 있도록 지원합니다. + +- **[CrewAI Flows](/ko/guides/flows/first-flow)**: AI 애플리케이션의 중추(Backbone)입니다. Flows를 사용하면 상태를 관리하고 실행을 제어하는 구조화된 이벤트 기반 workflow를 만들 수 있습니다. AI agent가 작업할 수 있는 기반을 제공합니다. +- **[CrewAI Crews](/ko/guides/crews/first-crew)**: Flow 내의 작업 단위입니다. Crews는 Flow가 위임한 특정 작업을 해결하기 위해 협력하는 자율 agent 팀입니다. + +10만 명이 넘는 개발자가 커뮤니티 과정을 통해 인증을 받았으며, CrewAI는 기업용 AI 자동화의 표준입니다. + +### 영상: 코딩 에이전트 스킬을 활용한 CrewAI Agents & Flows 구축 + +코딩 에이전트 스킬(Claude Code, Codex 등)을 설치하여 CrewAI로 코딩 에이전트를 빠르게 시작하세요. + +`npx skills add crewaiinc/skills` 명령어로 설치할 수 있습니다 + + + +## CrewAI 아키텍처 + +CrewAI의 아키텍처는 자율성과 제어의 균형을 맞추도록 설계되었습니다. + +### 1. Flows: 중추 (Backbone) + + + Flow를 애플리케이션의 "관리자" 또는 "프로세스 정의"라고 생각하세요. 단계, 로직, 그리고 시스템 내에서 데이터가 이동하는 방식을 정의합니다. + + + + CrewAI Framework Overview + + +Flows의 기능: +- **상태 관리**: 단계 및 실행 전반에 걸쳐 데이터를 유지합니다. +- **이벤트 기반 실행**: 이벤트 또는 외부 입력을 기반으로 작업을 트리거합니다. +- **제어 흐름**: 조건부 로직, 반복문, 분기를 사용합니다. + +### 2. Crews: 지능 (Intelligence) + + + Crews는 힘든 일을 처리하는 "팀"입니다. Flow 내에서 창의성과 협업이 필요한 복잡한 문제를 해결하기 위해 Crew를 트리거할 수 있습니다. + + + + CrewAI Framework Overview + + +Crews의 기능: +- **역할 수행 Agent**: 특정 목표와 도구를 가진 전문 agent입니다. +- **자율 협업**: agent들이 협력하여 작업을 해결합니다. +- **작업 위임**: agent의 능력에 따라 작업이 할당되고 실행됩니다. + +## 전체 작동 방식 + +1. **Flow**가 이벤트를 트리거하거나 프로세스를 시작합니다. +2. **Flow**가 상태를 관리하고 다음에 무엇을 할지 결정합니다. +3. **Flow**가 복잡한 작업을 **Crew**에게 위임합니다. +4. **Crew**의 agent들이 협력하여 작업을 완료합니다. +5. **Crew**가 결과를 **Flow**에 반환합니다. +6. **Flow**가 결과를 바탕으로 실행을 계속합니다. + +## 주요 기능 + + + + 장기 실행 프로세스와 복잡한 로직을 처리할 수 있는 신뢰할 수 있고 상태를 유지하는 workflow를 구축합니다. + + + 높은 수준의 목표를 달성하기 위해 계획하고, 실행하고, 협력할 수 있는 agent 팀을 배포합니다. + + + agent를 모든 API, 데이터베이스 또는 로컬 도구에 연결합니다. + + + 엔터프라이즈 배포를 위한 보안 및 규정 준수를 고려하여 설계되었습니다. + + + +## Crews vs Flows 사용 시기 + +**짧은 답변: 둘 다 사용하세요.** + +모든 프로덕션 애플리케이션의 경우, **Flow로 시작하세요**. + +- 애플리케이션의 전체 구조, 상태, 로직을 정의하려면 **Flow를 사용하세요**. +- 자율성이 필요한 특정하고 복잡한 작업을 수행하기 위해 agent 팀이 필요할 때 Flow 단계 내에서 **Crew를 사용하세요**. + +| 사용 사례 | 아키텍처 | +| :--- | :--- | +| **간단한 자동화** | Python 작업이 포함된 단일 Flow | +| **복잡한 연구** | 상태를 관리하는 Flow -> 연구를 수행하는 Crew | +| **애플리케이션 백엔드** | API 요청을 처리하는 Flow -> 콘텐츠를 생성하는 Crew -> DB에 저장하는 Flow | + +## CrewAI를 선택해야 하는 이유? + +- 🧠 **자율적 운영**: agent가 자신의 역할과 사용 가능한 도구를 바탕으로 지능적인 결정을 내립니다 +- 📝 **자연스러운 상호작용**: agent가 인간 팀원처럼 소통하고 협업합니다 +- 🛠️ **확장 가능한 설계**: 새로운 도구, 역할, 기능을 쉽게 추가할 수 있습니다 +- 🚀 **프로덕션 준비 완료**: 실제 환경에서의 신뢰성과 확장성을 고려하여 구축되었습니다 +- 🔒 **보안 중심**: 엔터프라이즈 보안 요구 사항을 고려하여 설계되었습니다 +- 💰 **비용 효율적**: 토큰 사용량과 API 호출을 최소화하도록 최적화되었습니다 + +## 지금 바로 빌드를 시작해보세요! + + + + 실행을 정밀하게 제어할 수 있는 구조화된, 이벤트 기반 workflow를 만드는 방법을 배워보세요. + + + 복잡한 문제를 함께 해결하는 협업 AI 팀을 단계별로 만드는 튜토리얼입니다. + + + + + + 개발 환경에서 CrewAI를 시작하세요. + + + Flow를 만들고 에이전트 한 명 crew를 실행해 끝까지 보고서를 생성해 보세요. + + + 다른 개발자와 소통하며, 도움을 받고 CrewAI 경험을 공유해보세요. + + diff --git a/docs/v1.15.13/ko/learn/before-and-after-kickoff-hooks.mdx b/docs/v1.15.13/ko/learn/before-and-after-kickoff-hooks.mdx new file mode 100644 index 0000000000..624a5e3a3d --- /dev/null +++ b/docs/v1.15.13/ko/learn/before-and-after-kickoff-hooks.mdx @@ -0,0 +1,61 @@ +--- +title: 킥오프 전후 후크(Before and After Kickoff Hooks) +description: CrewAI에서 킥오프 전후 후크를 사용하는 방법을 알아보세요 +mode: "wide" +--- + +CrewAI는 crew의 kickoff 전후에 코드를 실행할 수 있는 hook을 제공합니다. 이러한 hook은 입력값을 사전 처리하거나 결과를 사후 처리하는 데 유용합니다. + +## 킥오프 이전 훅 + +킥오프 이전 훅은 크루가 작업을 시작하기 전에 실행됩니다. 이 훅은 입력 딕셔너리를 받아 이를 수정한 후 크루에 전달할 수 있습니다. 이 훅을 사용하여 환경을 설정하거나, 필요한 데이터를 불러오거나, 입력값을 전처리할 수 있습니다. 입력 데이터가 크루에 의해 처리되기 전에 보완 또는 검증이 필요한 경우에 유용합니다. + +다음은 `crew.py`에서 킥오프 이전 함수를 정의하는 예시입니다: + +```python +from crewai import CrewBase +from crewai.project import before_kickoff + +@CrewBase +class MyCrew: + @before_kickoff + def prepare_data(self, inputs): + # Preprocess or modify inputs + inputs['processed'] = True + return inputs + +#... +``` + +이 예시에서, prepare_data 함수는 입력값에 입력이 이미 처리되었음을 나타내는 새로운 키-값 쌍을 추가하여 입력값을 수정합니다. + +## 킥오프 후 훅 + +킥오프 후 훅은 crew의 작업이 완료된 후에 실행됩니다. 이 훅은 crew 실행의 출력값을 담은 result 객체를 전달받습니다. 이 훅은 로깅, 데이터 변환 또는 추가 분석과 같이 결과를 후처리하는 데 이상적입니다. + +`crew.py`에서 킥오프 후 함수를 정의하는 방법은 다음과 같습니다. + +```python +from crewai import CrewBase +from crewai.project import after_kickoff + +@CrewBase +class MyCrew: + @after_kickoff + def log_results(self, result): + # Log or modify the results + print("Crew execution completed with result:", result) + return result + +# ... +``` + +`log_results` 함수에서는 crew 실행 결과가 단순히 출력됩니다. 이를 확장하여 알림 전송이나 다른 서비스와의 연동과 같은 더 복잡한 작업을 수행할 수도 있습니다. + +## 두 후크 모두 활용하기 + +두 가지 후크를 함께 사용하면 crew의 실행을 위한 포괄적인 설정과 해제 프로세스를 제공할 수 있습니다. 이들은 관심사의 분리를 통해 코드 아키텍처를 깔끔하게 유지하고, CrewAI 구현의 모듈성을 향상하는 데 특히 유용합니다. + +## 결론 + +CrewAI의 kickoff 전후 훅은 crew 실행의 생명주기에 강력하게 개입할 수 있는 방법을 제공합니다. 이러한 훅을 이해하고 활용함으로써, AI agent의 견고성과 유연성을 크게 향상시킬 수 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/bring-your-own-agent.mdx b/docs/v1.15.13/ko/learn/bring-your-own-agent.mdx new file mode 100644 index 0000000000..38f0912ce0 --- /dev/null +++ b/docs/v1.15.13/ko/learn/bring-your-own-agent.mdx @@ -0,0 +1,440 @@ +--- +title: 에이전트 직접 가져오기 +description: Crew 내에서 작동하는 자체 에이전트를 가져오는 방법을 알아보세요. +icon: robots +mode: "wide" +--- + +상호 운용성은 CrewAI의 핵심 개념입니다. 이 가이드에서는 Crew 내에서 작동하는 여러분만의 에이전트를 어떻게 도입할 수 있는지 보여줍니다. + +## 에이전트 직접 가져오기 어댑터 가이드 (Langgraph Agents, OpenAI Agents 등...) +다양한 프레임워크의 에이전트를 crew에서 작동하도록 하려면 3가지 어댑터가 필요합니다. + +1. BaseAgentAdapter +2. BaseToolAdapter +3. BaseConverter + +## BaseAgentAdapter +이 추상 클래스는 모든 agent adapter가 구현해야 하는 공통 인터페이스와 기능을 정의합니다. BaseAgent를 확장하여 CrewAI 프레임워크와의 호환성을 유지하면서 adapter별 요구 사항을 추가합니다. + +필수 메서드: + +1. `def configure_tools` +2. `def configure_structured_output` + +## 자신만의 Adapter 생성하기 +다른 프레임워크(예: LangGraph, Autogen, OpenAI Assistants)의 agent를 CrewAI에 통합하려면, `BaseAgentAdapter`를 상속하여 커스텀 adapter를 생성해야 합니다. 이 adapter는 호환성 계층 역할을 하며 CrewAI 인터페이스와 외부 agent의 특정 요구사항 사이를 변환합니다. + +커스텀 adapter를 구현하는 방법은 다음과 같습니다: + +1. **`BaseAgentAdapter` 상속하기**: + ```python + from crewai.agents.agent_adapters.base_agent_adapter import BaseAgentAdapter + from crewai.tools import BaseTool + from typing import List, Optional, Any, Dict + + class MyCustomAgentAdapter(BaseAgentAdapter): + # ... implementation details ... + ``` + +2. **`__init__` 구현하기**: + 생성자는 부모 클래스 생성자 `super().__init__(**kwargs)`를 호출하고, 외부 agent에 특화된 초기화를 수행해야 합니다. CrewAI의 `Agent` 초기화 시 사용할 수 있는 선택적 `agent_config` 딕셔너리를 이용하여 adapter와 하위 agent를 구성할 수 있습니다. + + ```python + def __init__(self, agent_config: Optional[Dict[str, Any]] = None, **kwargs: Any): + super().__init__(agent_config=agent_config, **kwargs) + # Initialize your external agent here, possibly using agent_config + # Example: self.external_agent = initialize_my_agent(agent_config) + print(f"Initializing MyCustomAgentAdapter with config: {agent_config}") + ``` + +3. **`configure_tools` 구현하기**: + 이 추상 메서드는 매우 중요합니다. CrewAI `BaseTool` 인스턴스 리스트를 받습니다. 구현 시, 이 도구들을 외부 agent 프레임워크에서 기대하는 형식으로 변환 또는 적응시켜야 합니다. 래핑하거나, 특정 속성 추출, 혹은 외부 agent 인스턴스에 등록하는 작업이 필요할 수 있습니다. + + ```python + def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None: + if tools: + adapted_tools = [] + for tool in tools: + # Adapt CrewAI BaseTool to the format your agent expects + # Example: adapted_tool = adapt_to_my_framework(tool) + # adapted_tools.append(adapted_tool) + pass # Replace with your actual adaptation logic + + # Configure the external agent with the adapted tools + # Example: self.external_agent.set_tools(adapted_tools) + print(f"Configuring tools for MyCustomAgentAdapter: {adapted_tools}") # Placeholder + else: + # Handle the case where no tools are provided + # Example: self.external_agent.set_tools([]) + print("No tools provided for MyCustomAgentAdapter.") + ``` + +4. **`configure_structured_output` 구현하기**: + CrewAI `Agent`가 구조화된 출력 요구사항(예: `output_json` 또는 `output_pydantic`)으로 구성될 때 이 메서드가 호출됩니다. adapter에서 외부 agent가 이러한 요구사항을 준수하도록 설정해야 합니다. 이는 외부 agent에 특정 파라미터를 설정하거나, 해당 모델이 요청된 형식을 지원하는지 확인하는 것이 포함될 수 있습니다. 외부 agent가 CrewAI의 기대에 맞는 방식으로 구조화된 출력을 지원하지 않을 경우, 변환 처리를 하거나 적절한 오류를 발생시켜야 할 수 있습니다. + + ```python + def configure_structured_output(self, structured_output: Any) -> None: + # Configure your external agent to produce output in the specified format + # Example: self.external_agent.set_output_format(structured_output) + self.adapted_structured_output = True # Signal that structured output is handled + print(f"Configuring structured output for MyCustomAgentAdapter: {structured_output}") + ``` + +이러한 메서드들을 구현함으로써, `MyCustomAgentAdapter`는 커스텀 agent 구현이 CrewAI crew 내에서 올바로 동작할 수 있도록 하여, task 및 도구들과 매끄럽게 상호작용할 수 있게 됩니다. 예시 주석 및 print문은 실제로 통합하려는 외부 agent 프레임워크에 맞춘 로직으로 교체해야 한다는 점을 기억하세요. + +## BaseToolAdapter 구현 +`BaseToolAdapter` 클래스는 CrewAI의 기본 `BaseTool` 객체를 외부 에이전트 프레임워크가 이해하고 활용할 수 있는 형식으로 변환하는 역할을 합니다. 각각의 에이전트 프레임워크(LangGraph, OpenAI Assistants 등)는 도구를 정의하고 처리하는 고유한 방식을 가지고 있으며, `BaseToolAdapter`는 이들 간의 변환자 역할을 합니다. + +사용자 정의 툴 어댑터를 구현하는 방법은 다음과 같습니다: + +1. **`BaseToolAdapter`를 상속하세요**: + ```python + from crewai.agents.agent_adapters.base_tool_adapter import BaseToolAdapter + from crewai.tools import BaseTool + from typing import List, Any + + class MyCustomToolAdapter(BaseToolAdapter): + # ... implementation details ... + ``` + +2. **`configure_tools` 구현**: + 이 메소드는 반드시 구현해야 하는 핵심 추상 메소드입니다. 에이전트에 제공된 CrewAI `BaseTool` 인스턴스의 리스트를 인자로 받으며, 각 리스트를 순회하면서 각 `BaseTool`을 외부 프레임워크가 기대하는 형식으로 변환하고, 변환된 도구들을 `self.converted_tools` 리스트(기본 클래스 생성자에서 초기화됨)에 담아야 합니다. + + ```python + def configure_tools(self, tools: List[BaseTool]) -> None: + """Configure and convert CrewAI tools for the specific implementation.""" + self.converted_tools = [] # Reset in case it's called multiple times + for tool in tools: + # Sanitize the tool name if required by the target framework + sanitized_name = self.sanitize_tool_name(tool.name) + + # --- Your Conversion Logic Goes Here --- + # Example: Convert BaseTool to a dictionary format for LangGraph + # converted_tool = { + # "name": sanitized_name, + # "description": tool.description, + # "parameters": tool.args_schema.schema() if tool.args_schema else {}, + # # Add any other framework-specific fields + # } + + # Example: Convert BaseTool to an OpenAI function definition + # converted_tool = { + # "type": "function", + # "function": { + # "name": sanitized_name, + # "description": tool.description, + # "parameters": tool.args_schema.schema() if tool.args_schema else {"type": "object", "properties": {}}, + # } + # } + + # --- Replace above examples with your actual adaptation --- + converted_tool = self.adapt_tool_to_my_framework(tool, sanitized_name) # Placeholder + + self.converted_tools.append(converted_tool) + print(f"Adapted tool '{tool.name}' to '{sanitized_name}' for MyCustomToolAdapter") # Placeholder + + print(f"MyCustomToolAdapter finished configuring tools: {len(self.converted_tools)} adapted.") # Placeholder + + # --- Helper method for adaptation (Example) --- + def adapt_tool_to_my_framework(self, tool: BaseTool, sanitized_name: str) -> Any: + # Replace this with the actual logic to convert a CrewAI BaseTool + # to the format needed by your specific external agent framework. + # This will vary greatly depending on the target framework. + adapted_representation = { + "framework_specific_name": sanitized_name, + "framework_specific_description": tool.description, + "inputs": tool.args_schema.schema() if tool.args_schema else None, + "implementation_reference": tool.run # Or however the framework needs to call it + } + # Also ensure the tool works both sync and async + async def async_tool_wrapper(*args, **kwargs): + output = tool.run(*args, **kwargs) + if inspect.isawaitable(output): + return await output + else: + return output + + adapted_tool = MyFrameworkTool( + name=sanitized_name, + description=tool.description, + inputs=tool.args_schema.schema() if tool.args_schema else None, + implementation_reference=async_tool_wrapper + ) + + return adapted_representation + + ``` + +3. **어댑터 사용하기**: + 일반적으로, `MyCustomAgentAdapter`의 `configure_tools` 메소드 내에서 `MyCustomToolAdapter`를 인스턴스화하여 도구를 처리하고, 외부 에이전트를 구성하기 전에 도구들을 변환합니다. + + ```python + # Inside MyCustomAgentAdapter.configure_tools + def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None: + if tools: + tool_adapter = MyCustomToolAdapter() # Instantiate your tool adapter + tool_adapter.configure_tools(tools) # Convert the tools + adapted_tools = tool_adapter.tools() # Get the converted tools + + # Now configure your external agent with the adapted_tools + # Example: self.external_agent.set_tools(adapted_tools) + print(f"Configuring external agent with adapted tools: {adapted_tools}") # Placeholder + else: + # Handle no tools case + print("No tools provided for MyCustomAgentAdapter.") + ``` + +`BaseToolAdapter`를 생성하면 도구 변환 로직을 에이전트 어댑테이션과 분리할 수 있어, 통합 작업을 더 깔끔하고 모듈화된 구조로 만들 수 있습니다. 반드시 예시 부분을 실제로 요구되는 외부 에이전트 프레임워크의 변환 로직으로 대체해야 함을 명심하세요. + +## BaseConverter +`BaseConverterAdapter`는 CrewAI의 `Task`에서 에이전트가 JSON이나 Pydantic 모델과 같이 특정 구조화된 포맷으로 최종 출력을 반환해야 할 때 중요한 역할을 합니다. 이 어댑터는 CrewAI의 구조화된 출력 요구사항과 외부 에이전트의 기능 사이를 이어주는 다리 역할을 합니다. + +주요 책임은 다음과 같습니다: +1. **에이전트의 구조화된 출력 구성:** `Task`의 요구사항(`output_json` 또는 `output_pydantic`)에 따라 연결된 `BaseAgentAdapter`(그리고 간접적으로 외부 에이전트)에게 어떤 포맷이 요구되는지 지시합니다. +2. **시스템 프롬프트 확장:** 에이전트의 시스템 프롬프트를 수정하여 필요한 구조로 출력물을 생성하는 방법에 대한 명확한 지침을 추가합니다. +3. **결과 후처리:** 에이전트로부터 받은 원시 출력을 받아, 요구되는 구조에 따라 파싱, 검증 및 포맷팅을 시도한 후, 최종적으로 문자열(예: JSON 문자열) 형태로 반환합니다. + +사용자 지정 컨버터 어댑터를 구현하는 방법은 다음과 같습니다: + +1. **`BaseConverterAdapter` 상속**: + ```python + from crewai.agents.agent_adapters.base_converter_adapter import BaseConverterAdapter + # Assuming you have your MyCustomAgentAdapter defined + # from .my_custom_agent_adapter import MyCustomAgentAdapter + from crewai.task import Task + from typing import Any + + class MyCustomConverterAdapter(BaseConverterAdapter): + # Store the expected output type (e.g., 'json', 'pydantic', 'text') + _output_type: str = 'text' + _output_schema: Any = None # Store JSON schema or Pydantic model + + # ... implementation details ... + ``` + +2. **`__init__` 구현**: + 생성자는 함께 사용할 `agent_adapter` 인스턴스를 받아야 합니다. + + ```python + def __init__(self, agent_adapter: Any): # Use your specific AgentAdapter type hint + self.agent_adapter = agent_adapter + print(f"Initializing MyCustomConverterAdapter for agent adapter: {type(agent_adapter).__name__}") + ``` + +3. **`configure_structured_output` 구현**: + 이 메서드는 CrewAI `Task` 객체를 받습니다. 작업의 `output_json` 및 `output_pydantic` 속성을 확인하여 요구되는 출력 구조를 결정해야 합니다. 해당 정보(예: `_output_type` 및 `_output_schema`)를 저장하고, 필요하다면 외부 에이전트가 구조화된 출력에 대해 별도의 설정이 필요한 경우 `self.agent_adapter`에 구성 메서드를 호출할 수 있습니다(일부는 agent adapter의 `configure_structured_output`에서 이미 부분적으로 처리되었을 수 있습니다). + + ```python + def configure_structured_output(self, task: Task) -> None: + """Configure the expected structured output based on the task.""" + if task.output_pydantic: + self._output_type = 'pydantic' + self._output_schema = task.output_pydantic + print(f"Converter: Configured for Pydantic output: {self._output_schema.__name__}") + elif task.output_json: + self._output_type = 'json' + self._output_schema = task.output_json + print(f"Converter: Configured for JSON output with schema: {self._output_schema}") + else: + self._output_type = 'text' + self._output_schema = None + print("Converter: Configured for standard text output.") + + # Optionally, inform the agent adapter if needed + # self.agent_adapter.set_output_mode(self._output_type, self._output_schema) + ``` + +4. **`enhance_system_prompt` 구현**: + 이 메서드는 에이전트의 기본 시스템 프롬프트 문자열을 받아, 현재 구성된 `_output_type` 및 `_output_schema`에 맞춘 지침을 추가해야 합니다. 목적은 에이전트를 구동하는 LLM이 올바른 포맷으로 출력을 생성하도록 안내하는 것입니다. + + ```python + def enhance_system_prompt(self, base_prompt: str) -> str: + """Enhance the system prompt with structured output instructions.""" + if self._output_type == 'text': + return base_prompt # No enhancement needed for plain text + + instructions = "\n\nYour final answer MUST be formatted as " + if self._output_type == 'json': + schema_str = json.dumps(self._output_schema, indent=2) + instructions += f"a JSON object conforming to the following schema:\n```json\n{schema_str}\n```" + elif self._output_type == 'pydantic': + schema_str = json.dumps(self._output_schema.model_json_schema(), indent=2) + instructions += f"a JSON object conforming to the Pydantic model '{self._output_schema.__name__}' with the following schema:\n```json\n{schema_str}\n```" + + instructions += "\nEnsure your entire response is ONLY the valid JSON object, without any introductory text, explanations, or concluding remarks." + + print(f"Converter: Enhancing prompt for {self._output_type} output.") + return base_prompt + instructions + ``` + *참고: 실제 프롬프트 엔지니어링은 사용하는 에이전트/LLM에 따라 조정이 필요할 수 있습니다.* + +5. **`post_process_result` 구현**: + 이 메서드는 에이전트로부터 받은 원시 문자열 출력을 받습니다. 구조화된 출력(`json` 또는 `pydantic`)이 요청된 경우, 문자열을 예상되는 포맷으로 파싱을 시도해야 합니다. 파싱 오류를 처리(예: 로그 남기기, 간단한 수정 시도, 예외 발생 등)해야 하며, 이 메서드는 **항상 문자열**을 반환해야 합니다. 중간 형식이 딕셔너리나 Pydantic 객체라도 이를 다시 JSON 문자열로 변환하여 반환해야 합니다. + + ```python + import json + from pydantic import ValidationError + + def post_process_result(self, result: str) -> str: + """Post-process the agent's result to ensure it matches the expected format.""" + print(f"Converter: Post-processing result for {self._output_type} output.") + if self._output_type == 'json': + try: + # Attempt to parse and re-serialize to ensure validity and consistent format + parsed_json = json.loads(result) + # Optional: Validate against self._output_schema if it's a JSON schema dictionary + # from jsonschema import validate + # validate(instance=parsed_json, schema=self._output_schema) + return json.dumps(parsed_json) + except json.JSONDecodeError as e: + print(f"Error: Failed to parse JSON output: {e}\nRaw output:\n{result}") + # Handle error: return raw, raise exception, or try to fix + return result # Example: return raw output on failure + # except Exception as e: # Catch validation errors if using jsonschema + # print(f"Error: JSON output failed schema validation: {e}\nRaw output:\n{result}") + # return result + elif self._output_type == 'pydantic': + try: + # Attempt to parse into the Pydantic model + model_instance = self._output_schema.model_validate_json(result) + # Return the model serialized back to JSON + return model_instance.model_dump_json() + except ValidationError as e: + print(f"Error: Failed to validate Pydantic output: {e}\nRaw output:\n{result}") + # Handle error + return result # Example: return raw output on failure + except json.JSONDecodeError as e: + print(f"Error: Failed to parse JSON for Pydantic model: {e}\nRaw output:\n{result}") + return result + else: # 'text' + return result # No processing needed for plain text + ``` + +이러한 메서드를 구현함으로써, `MyCustomConverterAdapter`는 CrewAI 작업의 구조화된 출력 요청이 통합된 외부 에이전트에서 올바르게 처리될 수 있게 하여, 사용자가 CrewAI 프레임워크 내에서 맞춤형 에이전트를 더욱 신뢰성 있고 유용하게 사용할 수 있도록 합니다. + +## 기본 제공 어댑터 + +다음 프레임워크에 대해 기본 제공 어댑터를 제공합니다: +1. LangGraph +2. OpenAI Agents + +## 적응형 에이전트로 crew 시작하기: + +```python +import json +import os +from typing import List + +from crewai_tools import SerperDevTool +from src.crewai import Agent, Crew, Task +from langchain_openai import ChatOpenAI +from pydantic import BaseModel + +from crewai.agents.agent_adapters.langgraph.langgraph_adapter import ( + LangGraphAgentAdapter, +) +from crewai.agents.agent_adapters.openai_agents.openai_adapter import OpenAIAgentAdapter + +# CrewAI Agent +code_helper_agent = Agent( + role="Code Helper", + goal="Help users solve coding problems effectively and provide clear explanations.", + backstory="You are an experienced programmer with deep knowledge across multiple programming languages and frameworks. You specialize in solving complex coding challenges and explaining solutions clearly.", + allow_delegation=False, + verbose=True, +) +# OpenAI Agent Adapter +link_finder_agent = OpenAIAgentAdapter( + role="Link Finder", + goal="Find the most relevant and high-quality resources for coding tasks.", + backstory="You are a research specialist with a talent for finding the most helpful resources. You're skilled at using search tools to discover documentation, tutorials, and examples that directly address the user's coding needs.", + tools=[SerperDevTool()], + allow_delegation=False, + verbose=True, +) + +# LangGraph Agent Adapter +reporter_agent = LangGraphAgentAdapter( + role="Reporter", + goal="Report the results of the tasks.", + backstory="You are a reporter who reports the results of the other tasks", + llm=ChatOpenAI(model="gpt-4o"), + allow_delegation=True, + verbose=True, +) + + +class Code(BaseModel): + code: str + + +task = Task( + description="Give an answer to the coding question: {task}", + expected_output="A thorough answer to the coding question: {task}", + agent=code_helper_agent, + output_json=Code, +) +task2 = Task( + description="Find links to resources that can help with coding tasks. Use the serper tool to find resources that can help.", + expected_output="A list of links to resources that can help with coding tasks", + agent=link_finder_agent, +) + + +class Report(BaseModel): + code: str + links: List[str] + + +task3 = Task( + description="Report the results of the tasks.", + expected_output="A report of the results of the tasks. this is the code produced and then the links to the resources that can help with the coding task.", + agent=reporter_agent, + output_json=Report, +) +# Use in CrewAI +crew = Crew( + agents=[code_helper_agent, link_finder_agent, reporter_agent], + tasks=[task, task2, task3], + verbose=True, +) + +result = crew.kickoff( + inputs={"task": "How do you implement an abstract class in python?"} +) + +# Print raw result first +print("Raw result:", result) + +# Handle result based on its type +if hasattr(result, "json_dict") and result.json_dict: + json_result = result.json_dict + print("\nStructured JSON result:") + print(f"{json.dumps(json_result, indent=2)}") + + # Access fields safely + if isinstance(json_result, dict): + if "code" in json_result: + print("\nCode:") + print( + json_result["code"][:200] + "..." + if len(json_result["code"]) > 200 + else json_result["code"] + ) + + if "links" in json_result: + print("\nLinks:") + for link in json_result["links"][:5]: # Print first 5 links + print(f"- {link}") + if len(json_result["links"]) > 5: + print(f"...and {len(json_result['links']) - 5} more links") +elif hasattr(result, "pydantic") and result.pydantic: + print("\nPydantic model result:") + print(result.pydantic.model_dump_json(indent=2)) +else: + # Fallback to raw output + print("\nNo structured result available, using raw output:") + print(result.raw[:500] + "..." if len(result.raw) > 500 else result.raw) + +``` \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/coding-agents.mdx b/docs/v1.15.13/ko/learn/coding-agents.mdx new file mode 100644 index 0000000000..041f80792b --- /dev/null +++ b/docs/v1.15.13/ko/learn/coding-agents.mdx @@ -0,0 +1,96 @@ +--- +title: 코딩 에이전트 +description: CrewAI 에이전트가 코드를 작성하고 실행할 수 있도록 하는 방법과, 향상된 기능을 위한 고급 기능을 알아보세요. +icon: rectangle-code +mode: "wide" +--- + +## 소개 + +CrewAI 에이전트는 이제 코드를 작성하고 실행할 수 있는 강력한 기능을 갖추게 되어 문제 해결 능력이 크게 향상되었습니다. 이 기능은 계산적 또는 프로그래밍적 해결책이 필요한 작업에 특히 유용합니다. + +## 코드 실행 활성화 + +에이전트에서 코드 실행을 활성화하려면, 에이전트를 생성할 때 `allow_code_execution` 매개변수를 `True`로 설정하면 됩니다. + +예시는 다음과 같습니다: + +```python Code +from crewai import Agent + +coding_agent = Agent( + role="Senior Python Developer", + goal="Craft well-designed and thought-out code", + backstory="You are a senior Python developer with extensive experience in software architecture and best practices.", + allow_code_execution=True +) +``` + + +`allow_code_execution` 매개변수의 기본값은 `False`임을 참고하세요. + + +## 중요한 고려 사항 + +1. **모델 선택**: 코드 실행을 활성화할 때 Claude 3.5 Sonnet 및 GPT-4와 같은 더 강력한 모델을 사용하는 것이 강력히 권장됩니다. +이러한 모델은 프로그래밍 개념에 대해 더 잘 이해하고 있으며, 올바르고 효율적인 코드를 생성할 가능성이 높습니다. + +2. **오류 처리**: 코드 실행 기능에는 오류 처리가 포함되어 있습니다. 실행된 코드에서 예외가 발생하면, 에이전트는 오류 메시지를 받아보고 코드를 수정하거나 +대체 솔루션을 제공할 수 있습니다. 기본값이 2인 `max_retry_limit` 파라미터는 작업에 대한 최대 재시도 횟수를 제어합니다. + +3. **종속성**: 코드 실행 기능을 사용하려면 `crewai_tools` 패키지를 설치해야 합니다. 설치되지 않은 경우, 에이전트는 다음과 같은 정보 메시지를 기록합니다: +"Coding tools not available. Install crewai_tools." + +## 코드 실행 프로세스 + +코드 실행이 활성화된 agent가 프로그래밍이 요구되는 작업을 만났을 때: + + + + agent는 작업을 분석하고 코드 실행이 필요하다는 것을 판단합니다. + + + 문제를 해결하는 데 필요한 Python 코드를 작성합니다. + + + 해당 코드는 내부 코드 실행 도구(`CodeInterpreterTool`)로 전송됩니다. + + + agent는 결과를 해석하여 응답에 반영하거나 추가 문제 해결에 활용합니다. + + + +## 예제 사용법 + +여기 코드 실행 기능이 있는 agent를 생성하고 이를 task에서 사용하는 자세한 예제가 있습니다: + +```python Code +from crewai import Agent, Task, Crew + +# Create an agent with code execution enabled +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task that requires code execution +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants.", + agent=coding_agent +) + +# Create a crew and add the task +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +# Execute the crew +result = analysis_crew.kickoff() + +print(result) +``` + +이 예제에서 `coding_agent`는 데이터 분석 작업을 수행하기 위해 Python 코드를 작성하고 실행할 수 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/conditional-tasks.mdx b/docs/v1.15.13/ko/learn/conditional-tasks.mdx new file mode 100644 index 0000000000..9de55e32df --- /dev/null +++ b/docs/v1.15.13/ko/learn/conditional-tasks.mdx @@ -0,0 +1,90 @@ +--- +title: 조건부 태스크 +description: crewAI kickoff에서 조건부 태스크를 사용하는 방법을 알아보세요 +icon: diagram-subtask +mode: "wide" +--- + +## 소개 + +crewAI의 조건부 작업(Conditional Tasks)은 이전 작업의 결과에 따라 동적으로 워크플로우를 조정할 수 있도록 합니다. +이 강력한 기능을 통해 crew는 선택적으로 결정을 내리고 작업을 수행할 수 있어, AI 기반 프로세스의 유연성과 효율성이 향상됩니다. + +## 예제 사용법 + +```python Code +from typing import List +from pydantic import BaseModel +from crewai import Agent, Crew +from crewai.tasks.conditional_task import ConditionalTask +from crewai.tasks.task_output import TaskOutput +from crewai.task import Task +from crewai_tools import SerperDevTool + +# Define a condition function for the conditional task +# If false, the task will be skipped, if true, then execute the task. +def is_data_missing(output: TaskOutput) -> bool: + return len(output.pydantic.events) < 10 # this will skip this task + +# Define the agents +data_fetcher_agent = Agent( + role="Data Fetcher", + goal="Fetch data online using Serper tool", + backstory="Backstory 1", + verbose=True, + tools=[SerperDevTool()] +) + +data_processor_agent = Agent( + role="Data Processor", + goal="Process fetched data", + backstory="Backstory 2", + verbose=True +) + +summary_generator_agent = Agent( + role="Summary Generator", + goal="Generate summary from fetched data", + backstory="Backstory 3", + verbose=True +) + +class EventOutput(BaseModel): + events: List[str] + +task1 = Task( + description="Fetch data about events in San Francisco using Serper tool", + expected_output="List of 10 things to do in SF this week", + agent=data_fetcher_agent, + output_pydantic=EventOutput, +) + +conditional_task = ConditionalTask( + description=""" + Check if data is missing. If we have less than 10 events, + fetch more events using Serper tool so that + we have a total of 10 events in SF this week.. + """, + expected_output="List of 10 Things to do in SF this week", + condition=is_data_missing, + agent=data_processor_agent, +) + +task3 = Task( + description="Generate summary of events in San Francisco from fetched data", + expected_output="A complete report on the customer and their customers and competitors, including their demographics, preferences, market positioning and audience engagement.", + agent=summary_generator_agent, +) + +# Create a crew with the tasks +crew = Crew( + agents=[data_fetcher_agent, data_processor_agent, summary_generator_agent], + tasks=[task1, conditional_task, task3], + verbose=True, + planning=True +) + +# Run the crew +result = crew.kickoff() +print("results", result) +``` \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/create-custom-tools.mdx b/docs/v1.15.13/ko/learn/create-custom-tools.mdx new file mode 100644 index 0000000000..3bbb844fec --- /dev/null +++ b/docs/v1.15.13/ko/learn/create-custom-tools.mdx @@ -0,0 +1,121 @@ +--- +title: 커스텀 도구 생성 +description: CrewAI 프레임워크 내에서 커스텀 도구를 제작, 사용 및 관리하는 종합 가이드로, 신규 기능과 오류 처리를 포함합니다. +icon: hammer +mode: "wide" +--- + +## CrewAI에서 툴 생성 및 활용 + +이 가이드는 CrewAI 프레임워크를 위한 커스텀 툴을 생성하는 방법과 최신 기능(툴 위임, 오류 처리, 동적 툴 호출 등)을 통합하여 이러한 툴을 효율적으로 관리하고 활용하는 방법에 대해 자세히 안내합니다. 또한 협업 툴의 중요성을 강조하며, 에이전트가 다양한 작업을 수행할 수 있도록 지원합니다. + + + **커뮤니티에 도구를 배포하고 싶으신가요?** 다른 사용자에게도 유용한 도구를 만들고 있다면, [커스텀 도구 배포하기](/ko/guides/tools/publish-custom-tools) 가이드에서 도구를 패키징하고 PyPI에 배포하는 방법을 알아보세요. + + +### `BaseTool` 서브클래싱 + +개인화된 툴을 생성하려면 `BaseTool`을 상속받고, 입력 검증을 위한 `args_schema`와 `_run` 메서드를 포함한 필요한 속성들을 정의해야 합니다. + +```python Code +from typing import Type +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class MyToolInput(BaseModel): + """Input schema for MyCustomTool.""" + argument: str = Field(..., description="Description of the argument.") + +class MyCustomTool(BaseTool): + name: str = "Name of my tool" + description: str = "What this tool does. It's vital for effective utilization." + args_schema: Type[BaseModel] = MyToolInput + + def _run(self, argument: str) -> str: + # Your tool's logic here + return "Tool's result" +``` + +### `tool` 데코레이터 사용하기 + +또는 tool 데코레이터 `@tool`을 사용할 수 있습니다. 이 방법은 함수 내에서 도구의 속성과 기능을 직접 정의할 수 있도록 하며, 귀하의 필요에 맞춘 특화된 도구를 간결하고 효율적으로 생성할 수 있는 방법을 제공합니다. + +```python Code +from crewai.tools import tool + +@tool("Tool Name") +def my_simple_tool(question: str) -> str: + """Tool description for clarity.""" + # Tool logic here + return "Tool output" +``` + +### 도구를 위한 캐시 함수 정의하기 + +도구의 성능을 캐싱으로 최적화하려면, `cache_function` 속성을 사용하여 사용자 맞춤 캐싱 전략을 정의할 수 있습니다. + +```python Code +@tool("Tool with Caching") +def cached_tool(argument: str) -> str: + """Tool functionality description.""" + return "Cacheable result" + +def my_cache_strategy(arguments: dict, result: str) -> bool: + # Define custom caching logic + return True if some_condition else False + +cached_tool.cache_function = my_cache_strategy +``` + +### 비동기 도구 생성하기 + +CrewAI는 논블로킹 I/O 작업을 위한 비동기 도구를 지원합니다. 이는 HTTP 요청, 데이터베이스 쿼리 또는 기타 I/O 바운드 작업이 필요한 경우에 유용합니다. + +#### `@tool` 데코레이터와 비동기 함수 사용하기 + +비동기 도구를 만드는 가장 간단한 방법은 `@tool` 데코레이터와 async 함수를 사용하는 것입니다: + +```python Code +import aiohttp +from crewai.tools import tool + +@tool("Async Web Fetcher") +async def fetch_webpage(url: str) -> str: + """Fetch content from a webpage asynchronously.""" + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.text() +``` + +#### 비동기 지원으로 `BaseTool` 서브클래싱하기 + +더 많은 제어를 위해 `BaseTool`을 상속하고 `_run`(동기) 및 `_arun`(비동기) 메서드를 모두 구현할 수 있습니다: + +```python Code +import requests +import aiohttp +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class WebFetcherInput(BaseModel): + """Input schema for WebFetcher.""" + url: str = Field(..., description="The URL to fetch") + +class WebFetcherTool(BaseTool): + name: str = "Web Fetcher" + description: str = "Fetches content from a URL" + args_schema: type[BaseModel] = WebFetcherInput + + def _run(self, url: str) -> str: + """Synchronous implementation.""" + return requests.get(url).text + + async def _arun(self, url: str) -> str: + """Asynchronous implementation for non-blocking I/O.""" + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.text() +``` + +이 가이드라인을 준수하고 새로운 기능과 협업 도구를 도구 생성 및 관리 프로세스에 통합함으로써, +CrewAI 프레임워크의 모든 기능을 활용할 수 있으며, AI agent의 개발 경험과 효율성을 모두 높일 수 있습니다. diff --git a/docs/v1.15.13/ko/learn/custom-llm.mdx b/docs/v1.15.13/ko/learn/custom-llm.mdx new file mode 100644 index 0000000000..6dfc3fc6ad --- /dev/null +++ b/docs/v1.15.13/ko/learn/custom-llm.mdx @@ -0,0 +1,351 @@ +--- +title: 커스텀 LLM 구현 +description: CrewAI에서 커스텀 LLM 구현을 만드는 방법을 알아보세요. +icon: code +mode: "wide" +--- + +## 개요 + +CrewAI는 `BaseLLM` 추상 기반 클래스를 통해 커스텀 LLM 구현을 지원합니다. 이를 통해 LiteLLM에 내장 지원이 없는 모든 LLM 제공자를 통합하거나, 커스텀 인증 메커니즘을 구현할 수 있습니다. + +## 빠른 시작 + +여기 최소한의 커스텀 LLM 구현 예시가 있습니다: + +```python +from crewai import BaseLLM +from typing import Any, Dict, List, Optional, Union +import requests + +class CustomLLM(BaseLLM): + def __init__(self, model: str, api_key: str, endpoint: str, temperature: Optional[float] = None): + # IMPORTANT: Call super().__init__() with required parameters + super().__init__(model=model, temperature=temperature) + + self.api_key = api_key + self.endpoint = endpoint + + def call( + self, + messages: Union[str, List[Dict[str, str]]], + tools: Optional[List[dict]] = None, + callbacks: Optional[List[Any]] = None, + available_functions: Optional[Dict[str, Any]] = None, + ) -> Union[str, Any]: + """Call the LLM with the given messages.""" + # Convert string to message format if needed + if isinstance(messages, str): + messages = [{"role": "user", "content": messages}] + + # Prepare request + payload = { + "model": self.model, + "messages": messages, + "temperature": self.temperature, + } + + # Add tools if provided and supported + if tools and self.supports_function_calling(): + payload["tools"] = tools + + # Make API call + response = requests.post( + self.endpoint, + headers={ + "Authorization": f"Bearer {self.api_key}", + "Content-Type": "application/json" + }, + json=payload, + timeout=30 + ) + response.raise_for_status() + + result = response.json() + return result["choices"][0]["message"]["content"] + + def supports_function_calling(self) -> bool: + """Override if your LLM supports function calling.""" + return True # Change to False if your LLM doesn't support tools + + def get_context_window_size(self) -> int: + """Return the context window size of your LLM.""" + return 8192 # Adjust based on your model's actual context window +``` + +## 사용자 지정 LLM 사용하기 + +```python +from crewai import Agent, Task, Crew + +# Assuming you have the CustomLLM class defined above +# Create your custom LLM +custom_llm = CustomLLM( + model="my-custom-model", + api_key="your-api-key", + endpoint="https://api.example.com/v1/chat/completions", + temperature=0.7 +) + +# Use with an agent +agent = Agent( + role="Research Assistant", + goal="Find and analyze information", + backstory="You are a research assistant.", + llm=custom_llm +) + +# Create and execute tasks +task = Task( + description="Research the latest developments in AI", + expected_output="A comprehensive summary", + agent=agent +) + +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() +``` + +## 필수 메서드 + +### 생성자: `__init__()` + +**중요**: 반드시 필수 매개변수와 함께 `super().__init__(model, temperature)`을 호출해야 합니다: + +```python +def __init__(self, model: str, api_key: str, temperature: Optional[float] = None): + # 필수: 부모 생성자를 model과 temperature로 호출 + super().__init__(model=model, temperature=temperature) + + # 사용자 정의 초기화 + self.api_key = api_key +``` + +### 추상 메서드: `call()` + +`call()` 메서드는 LLM 구현의 핵심입니다. 반드시 다음을 수행해야 합니다: + +- 메시지(문자열 또는 'role'과 'content'가 포함된 딕셔너리 리스트)를 받아들임 +- 문자열 응답을 반환함 +- 지원하는 경우 도구 및 함수 호출을 처리함 +- 오류 발생 시 적절한 예외를 발생시킴 + +### 선택적 메서드 + +```python +def supports_function_calling(self) -> bool: + """Return True if your LLM supports function calling.""" + return True # Default is True + +def supports_stop_words(self) -> bool: + """Return True if your LLM supports stop sequences.""" + return True # Default is True + +def get_context_window_size(self) -> int: + """Return the context window size.""" + return 4096 # Default is 4096 +``` + +## 공통 패턴 + +### 오류 처리 + +```python +import requests + +def call(self, messages, tools=None, callbacks=None, available_functions=None): + try: + response = requests.post( + self.endpoint, + headers={"Authorization": f"Bearer {self.api_key}"}, + json=payload, + timeout=30 + ) + response.raise_for_status() + return response.json()["choices"][0]["message"]["content"] + + except requests.Timeout: + raise TimeoutError("LLM request timed out") + except requests.RequestException as e: + raise RuntimeError(f"LLM request failed: {str(e)}") + except (KeyError, IndexError) as e: + raise ValueError(f"Invalid response format: {str(e)}") +``` + +### 커스텀 인증 + +```python +from crewai import BaseLLM +from typing import Optional + +class CustomAuthLLM(BaseLLM): + def __init__(self, model: str, auth_token: str, endpoint: str, temperature: Optional[float] = None): + super().__init__(model=model, temperature=temperature) + self.auth_token = auth_token + self.endpoint = endpoint + + def call(self, messages, tools=None, callbacks=None, available_functions=None): + headers = { + "Authorization": f"Custom {self.auth_token}", # Custom auth format + "Content-Type": "application/json" + } + # Rest of implementation... +``` + +### 스톱 워드 지원 + +CrewAI는 에이전트의 동작을 제어하기 위해 `"\nObservation:"`를 스톱 워드로 자동 추가합니다. 만약 사용 중인 LLM이 스톱 워드를 지원한다면: + +```python +def call(self, messages, tools=None, callbacks=None, available_functions=None): + payload = { + "model": self.model, + "messages": messages, + "stop": self.stop # Include stop words in API call + } + # Make API call... + +def supports_stop_words(self) -> bool: + return True # Your LLM supports stop sequences +``` + +만약 사용 중인 LLM이 스톱 워드를 기본적으로 지원하지 않는다면: + +```python +def call(self, messages, tools=None, callbacks=None, available_functions=None): + response = self._make_api_call(messages, tools) + content = response["choices"][0]["message"]["content"] + + # Manually truncate at stop words + if self.stop: + for stop_word in self.stop: + if stop_word in content: + content = content.split(stop_word)[0] + break + + return content + +def supports_stop_words(self) -> bool: + return False # Tell CrewAI we handle stop words manually +``` + +## 함수 호출 + +LLM이 함수 호출을 지원하는 경우, 전체 플로우를 구현하세요: + +```python +import json + +def call(self, messages, tools=None, callbacks=None, available_functions=None): + # Convert string to message format + if isinstance(messages, str): + messages = [{"role": "user", "content": messages}] + + # Make API call + response = self._make_api_call(messages, tools) + message = response["choices"][0]["message"] + + # Check for function calls + if "tool_calls" in message and available_functions: + return self._handle_function_calls( + message["tool_calls"], messages, tools, available_functions + ) + + return message["content"] + +def _handle_function_calls(self, tool_calls, messages, tools, available_functions): + """Handle function calling with proper message flow.""" + for tool_call in tool_calls: + function_name = tool_call["function"]["name"] + + if function_name in available_functions: + # Parse and execute function + function_args = json.loads(tool_call["function"]["arguments"]) + function_result = available_functions[function_name](**function_args) + + # Add function call and result to message history + messages.append({ + "role": "assistant", + "content": None, + "tool_calls": [tool_call] + }) + messages.append({ + "role": "tool", + "tool_call_id": tool_call["id"], + "name": function_name, + "content": str(function_result) + }) + + # Call LLM again with updated context + return self.call(messages, tools, None, available_functions) + + return "Function call failed" +``` + +## 문제 해결 + +### 일반적인 문제 + +**생성자 오류** +```python +# ❌ Wrong - missing required parameters +def __init__(self, api_key: str): + super().__init__() + +# ✅ Correct +def __init__(self, model: str, api_key: str, temperature: Optional[float] = None): + super().__init__(model=model, temperature=temperature) +``` + +**함수 호출이 작동하지 않음** +- `supports_function_calling()`이 `True`를 반환하는지 확인하세요 +- 응답에서 `tool_calls`를 처리하는지 확인하세요 +- `available_functions` 매개변수가 올바르게 사용되는지 검증하세요 + +**인증 실패** +- API 키 형식과 권한을 확인하세요 +- 인증 헤더 형식을 점검하세요 +- 엔드포인트 URL이 올바른지 확인하세요 + +**응답 파싱 오류** +- 중첩된 필드에 접근하기 전에 응답 구조를 검증하세요 +- content가 None일 수 있는 경우를 처리하세요 +- 잘못된 응답에 대한 적절한 오류 처리를 추가하세요 + +## 커스텀 LLM 테스트하기 + +```python +from crewai import Agent, Task, Crew + +def test_custom_llm(): + llm = CustomLLM( + model="test-model", + api_key="test-key", + endpoint="https://api.test.com" + ) + + # Test basic call + result = llm.call("Hello, world!") + assert isinstance(result, str) + assert len(result) > 0 + + # Test with CrewAI agent + agent = Agent( + role="Test Agent", + goal="Test custom LLM", + backstory="A test agent.", + llm=llm + ) + + task = Task( + description="Say hello", + expected_output="A greeting", + agent=agent + ) + + crew = Crew(agents=[agent], tasks=[task]) + result = crew.kickoff() + assert "hello" in result.raw.lower() +``` + +이 가이드는 CrewAI에서 커스텀 LLM을 구현하는 주요 사항을 다룹니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/custom-manager-agent.mdx b/docs/v1.15.13/ko/learn/custom-manager-agent.mdx new file mode 100644 index 0000000000..89f8471ccc --- /dev/null +++ b/docs/v1.15.13/ko/learn/custom-manager-agent.mdx @@ -0,0 +1,91 @@ +--- +title: 커스텀 매니저 에이전트 +description: CrewAI에서 커스텀 에이전트를 매니저로 설정하여 작업 관리 및 조정을 보다 세밀하게 제어하는 방법을 알아보세요. +icon: user-shield +mode: "wide" +--- + +# CrewAI에서 특정 에이전트를 매니저로 설정하기 + +CrewAI는 사용자가 crew의 매니저로 특정 에이전트를 설정할 수 있도록 하여, 작업의 관리 및 조정에 대한 더 많은 제어권을 제공합니다. +이 기능을 통해 프로젝트의 요구 사항에 더 적합하게 매니저 역할을 맞춤화할 수 있습니다. + +## `manager_agent` 속성 사용하기 + +### 커스텀 매니저 에이전트 + +`manager_agent` 속성을 사용하면 crew를 관리할 커스텀 에이전트를 정의할 수 있습니다. 이 에이전트는 전체 프로세스를 감독하여 작업이 효율적이고 최고의 기준에 맞춰 완료되도록 보장합니다. + +### 예시 + +```python Code +import os +from crewai import Agent, Task, Crew, Process + +# Define your agents +researcher = Agent( + role="Researcher", + goal="Conduct thorough research and analysis on AI and AI agents", + backstory="You're an expert researcher, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently researching for a new client.", + allow_delegation=False, +) + +writer = Agent( + role="Senior Writer", + goal="Create compelling content about AI and AI agents", + backstory="You're a senior writer, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently writing content for a new client.", + allow_delegation=False, +) + +# Define your task +task = Task( + description="Generate a list of 5 interesting ideas for an article, then write one captivating paragraph for each idea that showcases the potential of a full article on this topic. Return the list of ideas with their paragraphs and your notes.", + expected_output="5 bullet points, each with a paragraph and accompanying notes.", +) + +# Define the manager agent +manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success. Your role is to coordinate the efforts of the crew members, ensuring that each task is completed on time and to the highest standard.", + allow_delegation=True, +) + +# Instantiate your crew with a custom manager +crew = Crew( + agents=[researcher, writer], + tasks=[task], + manager_agent=manager, + process=Process.hierarchical, +) + +# Start the crew's work +result = crew.kickoff() +``` + +## 맞춤형 Manager 에이전트의 이점 + +- **향상된 제어**: 프로젝트의 구체적인 요구 사항에 맞게 관리 방식을 조정할 수 있습니다. +- **향상된 조정**: 경험 많은 에이전트를 통해 효율적인 작업 조정 및 관리가 가능합니다. +- **맞춤형 관리**: 프로젝트 목표에 부합하는 관리자 역할과 책임을 정의할 수 있습니다. + +## 매니저 LLM 설정하기 + +계층적 프로세스를 사용하고 있으며 커스텀 매니저 에이전트를 설정하지 않으려는 경우, 매니저에 사용할 언어 모델을 지정할 수 있습니다: + +```python Code +from crewai import LLM + +manager_llm = LLM(model="gpt-4o") + +crew = Crew( + agents=[researcher, writer], + tasks=[task], + process=Process.hierarchical, + manager_llm=manager_llm +) +``` + + +계층적 프로세스를 사용할 때는 `manager_agent` 또는 `manager_llm` 중 하나를 반드시 설정해야 합니다. + \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/customizing-agents.mdx b/docs/v1.15.13/ko/learn/customizing-agents.mdx new file mode 100644 index 0000000000..b05fef396a --- /dev/null +++ b/docs/v1.15.13/ko/learn/customizing-agents.mdx @@ -0,0 +1,111 @@ +--- +title: 에이전트 맞춤화 +description: CrewAI 프레임워크 내에서 특정 역할, 작업 및 고급 맞춤화를 위해 에이전트를 조정하는 종합 가이드입니다. +icon: user-pen +mode: "wide" +--- + +## 사용자 지정 가능 속성 + +효율적인 CrewAI 팀을 구성하려면 AI 에이전트를 프로젝트의 고유한 요구 사항에 맞게 동적으로 조정할 수 있어야 합니다. 이 섹션에서는 사용자 지정할 수 있는 기본 속성에 대해 다룹니다. + +### 커스터마이징을 위한 주요 속성 + +| 속성 | 설명 | +|:-----------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Role** | crew 내에서 에이전트의 직무를 지정합니다. 예: 'Analyst', 'Customer Service Rep' 등. | +| **Goal** | 에이전트의 목표를 정의하며, 이는 해당 role 및 crew의 전체 미션과 조화됩니다. | +| **Backstory** | 에이전트의 페르소나에 깊이를 더해, crew 내에서의 동기 부여와 참여도를 높입니다. | +| **Tools** *(선택 사항)* | 에이전트가 작업을 수행할 때 사용하는 기능이나 방법을 나타냅니다. 단순한 함수부터 복잡한 통합까지 포함될 수 있습니다. | +| **Cache** *(선택 사항)* | 에이전트가 tool 사용 시 캐시를 이용할지 여부를 결정합니다. | +| **Max RPM** | 분당 최대 요청 수(`max_rpm`)를 설정합니다. 외부 서비스에 제한 없는 요청을 원할 경우 `None`으로 설정할 수 있습니다. | +| **Verbose** *(선택 사항)* | 디버깅 및 최적화를 위한 상세 로그를 활성화하며, 실행 과정에 대한 인사이트를 제공합니다. | +| **Allow Delegation** *(선택 사항)* | 다른 에이전트로의 작업 위임을 제어합니다. 기본값은 `False`입니다. | +| **Max Iter** *(선택 사항)* | 무한 루프를 방지하기 위해 작업의 최대 반복 횟수(`max_iter`)를 제한합니다. 기본값은 25입니다. | +| **Max Execution Time** *(선택 사항)* | 에이전트가 작업을 완료하는 데 허용되는 최대 시간을 설정합니다. | +| **System Template** *(선택 사항)* | 에이전트의 시스템 형식을 정의합니다. | +| **Prompt Template** *(선택 사항)* | 에이전트의 프롬프트 형식을 정의합니다. | +| **Response Template** *(선택 사항)* | 에이전트의 응답 형식을 정의합니다. | +| **Use System Prompt** *(선택 사항)* | 작업 수행 중 에이전트가 system prompt를 사용할지 여부를 제어합니다. | +| **Respect Context Window** | 기본적으로 슬라이딩 context 윈도우를 활성화하여(context size를 유지) 설정합니다. | +| **Max Retry Limit** | 오류 발생 시 에이전트의 최대 재시도 횟수(`max_retry_limit`)를 설정합니다. | + +## 고급 커스터마이징 옵션 + +기본 속성 외에도, CrewAI는 에이전트의 행동과 능력을 크게 향상시킬 수 있는 더 깊은 커스터마이징을 허용합니다. + +### 언어 모델 커스터마이제이션 + +에이전트는 특정 언어 모델(`llm`)과 함수 호출 언어 모델(`function_calling_llm`)로 커스터마이즈할 수 있어, 처리 및 의사결정 능력을 고급 수준으로 제어할 수 있습니다. +`function_calling_llm`을 설정하면 기본 crew 함수 호출 언어 모델을 오버라이드할 수 있으므로, 더 높은 수준의 커스터마이제이션이 가능합니다. + +## 성능 및 디버깅 설정 + +에이전트의 성능을 조정하고 운영을 모니터링하는 것은 효율적인 작업 수행을 위해 매우 중요합니다. + +### 자세한 모드(Verbose Mode) 및 RPM 제한 + +- **자세한 모드(Verbose Mode)**: 에이전트의 동작을 자세히 기록하는 로깅을 활성화하여 디버깅과 최적화에 유용합니다. 특히, 에이전트 실행 프로세스에 대한 인사이트를 제공하여 성능 최적화에 도움이 됩니다. +- **RPM 제한**: 분당 최대 요청 수(`max_rpm`)를 설정합니다. 이 속성은 선택 사항이며, 제한이 필요 없을 경우 `None`으로 설정하면 외부 서비스에 무제한 쿼리를 허용할 수 있습니다. + +### 작업 실행을 위한 최대 반복 횟수 + +`max_iter` 속성은 사용자가 하나의 작업에 대해 agent가 수행할 수 있는 최대 반복 횟수를 정의할 수 있게 하여, 무한 루프나 지나치게 긴 실행을 방지해줍니다. +기본값은 25로 설정되어 있어 철저함과 효율성 사이의 균형을 제공합니다. agent가 이 숫자에 가까워질 때, 최선의 답변을 제공하기 위해 노력하게 됩니다. + +## 에이전트 및 도구 커스터마이징 + +에이전트는 초기화 시 속성과 도구를 정의하여 커스터마이징합니다. 도구는 에이전트의 기능에 매우 중요하며, 특정 작업을 수행할 수 있게 해줍니다. +`tools` 속성은 에이전트가 사용할 수 있는 도구의 배열이어야 하며, 기본값으로는 빈 리스트로 초기화됩니다. 도구는 새로운 요구 사항에 맞추어 에이전트 초기화 이후에도 추가하거나 수정할 수 있습니다. + +```shell +pip install 'crewai[tools]' +``` + +### 예시: 에이전트에 도구 할당하기 + +```python Code +import os +from crewai import Agent +from crewai_tools import SerperDevTool + +# Set API keys for tool initialization +os.environ["OPENAI_API_KEY"] = "Your Key" +os.environ["SERPER_API_KEY"] = "Your Key" + +# Initialize a search tool +search_tool = SerperDevTool() + +# Initialize the agent with advanced options +agent = Agent( + role='Research Analyst', + goal='Provide up-to-date market analysis', + backstory='An expert analyst with a keen eye for market trends.', + tools=[search_tool], + memory=True, # Enable memory + verbose=True, + max_rpm=None, # No limit on requests per minute + max_iter=25, # Default value for maximum iterations +) +``` + +## 위임 및 자율성 + +에이전트가 작업을 위임하거나 질문을 할 수 있는 능력을 제어하는 것은 CrewAI 프레임워크 내에서 자율성과 협업 역학을 맞춤화하는 데 매우 중요합니다. 기본적으로 +`allow_delegation` 속성은 이제 `False`로 설정되어 있어, 에이전트가 필요에 따라 도움을 요청하거나 작업을 위임하는 것이 비활성화됩니다. 이 기본 동작은 CrewAI 생태계 내에서 협동적 문제 해결과 +효율성을 촉진하기 위해 변경될 수 있습니다. 필요할 경우, 특정 운영 요구 사항에 맞게 위임을 활성화할 수 있습니다. + +### 예시: 에이전트에 대한 위임 비활성화 + +```python Code +agent = Agent( + role='Content Writer', + goal='Write engaging content on market trends', + backstory='A seasoned writer with expertise in market analysis.', + allow_delegation=True # Enabling delegation +) +``` + +## 결론 + +CrewAI에서 에이전트의 역할, 목표, 배경 이야기, 도구를 설정하고, 언어 모델 커스터마이징, 메모리, 성능 설정, 위임 선호도와 같은 고급 옵션을 함께 활용하면 복잡한 과제에 대응할 준비가 된 세밀하고 유능한 AI 팀을 구성할 수 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/dalle-image-generation.mdx b/docs/v1.15.13/ko/learn/dalle-image-generation.mdx new file mode 100644 index 0000000000..f194fe1117 --- /dev/null +++ b/docs/v1.15.13/ko/learn/dalle-image-generation.mdx @@ -0,0 +1,74 @@ +--- +title: "DALL-E를 활용한 이미지 생성" +description: "CrewAI 프로젝트에서 AI 기반 이미지 생성을 위해 DALL-E를 활용하는 방법을 알아보세요" +icon: "image" +mode: "wide" +--- + +CrewAI는 OpenAI의 DALL-E와의 통합을 지원하여, AI 에이전트가 작업의 일환으로 이미지를 생성할 수 있습니다. 이 가이드에서는 CrewAI 프로젝트에서 DALL-E 도구를 설정하고 사용하는 방법을 단계별로 안내합니다. + +## 사전 요구 사항 + +- crewAI가 설치되어 있음 (최신 버전) +- DALL-E에 접근 가능한 OpenAI API 키 + +## DALL-E 도구 설정하기 + + + + ```python + from crewai_tools import DallETool + ``` + + + + ```python + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + tools=[SerperDevTool(), DallETool()], # Add DallETool to the list of tools + allow_delegation=False, + verbose=True + ) + ``` + + + +## DALL-E 도구 사용하기 + +DALL-E 도구를 에이전트에 추가하면 텍스트 프롬프트를 기반으로 이미지를 생성할 수 있습니다. 도구는 생성된 이미지의 URL을 반환하며, 이 URL은 에이전트의 출력에 사용하거나 다른 에이전트에게 전달하여 추가 처리를 할 수 있습니다. + +### 예시 에이전트 구성 + +```yaml +role: > + LinkedIn 프로필 시니어 데이터 연구원 +goal: > + 제공된 이름 {name}과 도메인 {domain}을 기반으로 자세한 LinkedIn 프로필을 찾아냅니다 + 도메인 {domain}을 기반으로 Dall-e 이미지를 생성합니다 +backstory: > + 당신은 관련성이 높은 LinkedIn 프로필을 찾아내는 데 능숙한 숙련된 연구원입니다. + LinkedIn을 효율적으로 탐색하는 능력으로 잘 알려져 있으며, 전문적인 정보를 + 명확하고 간결하게 수집하고 제시하는 데 뛰어납니다. +``` + +### 예상 결과 + +DALL-E 도구를 사용하는 agent는 이미지를 생성하고 응답에 URL을 제공할 수 있습니다. 그런 다음 이미지를 다운로드할 수 있습니다. + + + DALL-E Image + + +## 모범 사례 + +1. **이미지 생성 프롬프트를 구체적으로 작성하세요**. 그래야 최상의 결과를 얻을 수 있습니다. +2. **생성 시간을 고려하세요** - 이미지 생성에는 시간이 걸릴 수 있으므로 작업 계획에 이를 반영하세요. +3. **사용 정책을 준수하세요** - 이미지를 생성할 때 항상 OpenAI의 사용 정책을 준수해야 합니다. + +## 문제 해결 + +1. **API 접근 확인** - OpenAI API 키가 DALL-E에 접근 권한이 있는지 확인하세요. +2. **버전 호환성** - 최신 버전의 crewAI와 crewai-tools를 사용하고 있는지 확인하세요. +3. **도구 구성** - DALL-E 도구가 agent의 도구 목록에 올바르게 추가되어 있는지 확인하세요. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/execution-hooks.mdx b/docs/v1.15.13/ko/learn/execution-hooks.mdx new file mode 100644 index 0000000000..4254f053c8 --- /dev/null +++ b/docs/v1.15.13/ko/learn/execution-hooks.mdx @@ -0,0 +1,379 @@ +--- +title: 실행 훅 개요 +description: 에이전트 작업에 대한 세밀한 제어를 위한 CrewAI 실행 훅 이해 및 사용 +mode: "wide" +--- + +실행 훅(Execution Hooks)은 CrewAI 에이전트의 런타임 동작을 세밀하게 제어할 수 있게 해줍니다. 크루 실행 전후에 실행되는 킥오프 훅과 달리, 실행 훅은 에이전트 실행 중 특정 작업을 가로채서 동작을 수정하고, 안전성 검사를 구현하며, 포괄적인 모니터링을 추가할 수 있습니다. + +## 실행 훅의 유형 + +CrewAI는 두 가지 주요 범주의 실행 훅을 제공합니다: + +### 1. [LLM 호출 훅](/learn/llm-hooks) + +언어 모델 상호작용을 제어하고 모니터링합니다: +- **LLM 호출 전**: 프롬프트 수정, 입력 검증, 승인 게이트 구현 +- **LLM 호출 후**: 응답 변환, 출력 정제, 대화 기록 업데이트 + +**사용 사례:** +- 반복 제한 +- 비용 추적 및 토큰 사용량 모니터링 +- 응답 정제 및 콘텐츠 필터링 +- LLM 호출에 대한 사람의 승인 +- 안전 가이드라인 또는 컨텍스트 추가 +- 디버그 로깅 및 요청/응답 검사 + +[LLM 훅 문서 보기 →](/learn/llm-hooks) + +### 2. [도구 호출 훅](/learn/tool-hooks) + +도구 실행을 제어하고 모니터링합니다: +- **도구 호출 전**: 입력 수정, 매개변수 검증, 위험한 작업 차단 +- **도구 호출 후**: 결과 변환, 출력 정제, 실행 세부사항 로깅 + +**사용 사례:** +- 파괴적인 작업에 대한 안전 가드레일 +- 민감한 작업에 대한 사람의 승인 +- 입력 검증 및 정제 +- 결과 캐싱 및 속도 제한 +- 도구 사용 분석 +- 디버그 로깅 및 모니터링 + +[도구 훅 문서 보기 →](/learn/tool-hooks) + +## 훅 등록 방법 + +### 1. 데코레이터 기반 훅 (권장) + +훅을 등록하는 가장 깔끔하고 파이썬스러운 방법: + +```python +from crewai.hooks import before_llm_call, after_llm_call, before_tool_call, after_tool_call + +@before_llm_call +def limit_iterations(context): + """반복 횟수를 제한하여 무한 루프를 방지합니다.""" + if context.iterations > 10: + return False # 실행 차단 + return None + +@after_llm_call +def sanitize_response(context): + """LLM 응답에서 민감한 데이터를 제거합니다.""" + if "API_KEY" in context.response: + return context.response.replace("API_KEY", "[수정됨]") + return None + +@before_tool_call +def block_dangerous_tools(context): + """파괴적인 작업을 차단합니다.""" + if context.tool_name == "delete_database": + return False # 실행 차단 + return None + +@after_tool_call +def log_tool_result(context): + """도구 실행을 로깅합니다.""" + print(f"도구 {context.tool_name} 완료") + return None +``` + +### 2. 크루 범위 훅 + +특정 크루 인스턴스에만 훅을 적용합니다: + +```python +from crewai import CrewBase +from crewai.project import crew +from crewai.hooks import before_llm_call_crew, after_tool_call_crew + +@CrewBase +class MyProjCrew: + @before_llm_call_crew + def validate_inputs(self, context): + # 이 크루에만 적용됩니다 + print(f"{self.__class__.__name__}에서 LLM 호출") + return None + + @after_tool_call_crew + def log_results(self, context): + # 크루별 로깅 + print(f"도구 결과: {context.tool_result[:50]}...") + return None + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential + ) +``` + +## 훅 실행 흐름 + +### LLM 호출 흐름 + +``` +에이전트가 LLM을 호출해야 함 + ↓ +[LLM 호출 전 훅 실행] + ├→ 훅 1: 반복 횟수 검증 + ├→ 훅 2: 안전 컨텍스트 추가 + └→ 훅 3: 요청 로깅 + ↓ +훅이 False를 반환하는 경우: + ├→ LLM 호출 차단 + └→ ValueError 발생 + ↓ +모든 훅이 True/None을 반환하는 경우: + ├→ LLM 호출 진행 + └→ 응답 생성 + ↓ +[LLM 호출 후 훅 실행] + ├→ 훅 1: 응답 정제 + ├→ 훅 2: 응답 로깅 + └→ 훅 3: 메트릭 업데이트 + ↓ +최종 응답 반환 +``` + +### 도구 호출 흐름 + +``` +에이전트가 도구를 실행해야 함 + ↓ +[도구 호출 전 훅 실행] + ├→ 훅 1: 도구 허용 여부 확인 + ├→ 훅 2: 입력 검증 + └→ 훅 3: 필요시 승인 요청 + ↓ +훅이 False를 반환하는 경우: + ├→ 도구 실행 차단 + └→ 오류 메시지 반환 + ↓ +모든 훅이 True/None을 반환하는 경우: + ├→ 도구 실행 진행 + └→ 결과 생성 + ↓ +[도구 호출 후 훅 실행] + ├→ 훅 1: 결과 정제 + ├→ 훅 2: 결과 캐싱 + └→ 훅 3: 메트릭 로깅 + ↓ +최종 결과 반환 +``` + +## 훅 컨텍스트 객체 + +### LLMCallHookContext + +LLM 실행 상태에 대한 액세스를 제공합니다: + +```python +class LLMCallHookContext: + executor: CrewAgentExecutor # 전체 실행자 액세스 + messages: list # 변경 가능한 메시지 목록 + agent: Agent # 현재 에이전트 + task: Task # 현재 작업 + crew: Crew # 크루 인스턴스 + llm: BaseLLM # LLM 인스턴스 + iterations: int # 현재 반복 횟수 + response: str | None # LLM 응답 (후 훅용) +``` + +### ToolCallHookContext + +도구 실행 상태에 대한 액세스를 제공합니다: + +```python +class ToolCallHookContext: + tool_name: str # 호출되는 도구 + tool_input: dict # 변경 가능한 입력 매개변수 + tool: CrewStructuredTool # 도구 인스턴스 + agent: Agent | None # 실행 중인 에이전트 + task: Task | None # 현재 작업 + crew: Crew | None # 크루 인스턴스 + tool_result: str | None # 도구 결과 (후 훅용) +``` + +## 일반적인 패턴 + +### 안전 및 검증 + +```python +@before_tool_call +def safety_check(context): + """파괴적인 작업을 차단합니다.""" + dangerous = ['delete_file', 'drop_table', 'system_shutdown'] + if context.tool_name in dangerous: + print(f"🛑 차단됨: {context.tool_name}") + return False + return None + +@before_llm_call +def iteration_limit(context): + """무한 루프를 방지합니다.""" + if context.iterations > 15: + print("⛔ 최대 반복 횟수 초과") + return False + return None +``` + +### 사람의 개입 + +```python +@before_tool_call +def require_approval(context): + """민감한 작업에 대한 승인을 요구합니다.""" + sensitive = ['send_email', 'make_payment', 'post_message'] + + if context.tool_name in sensitive: + response = context.request_human_input( + prompt=f"{context.tool_name} 승인하시겠습니까?", + default_message="승인하려면 'yes'를 입력하세요:" + ) + + if response.lower() != 'yes': + return False + + return None +``` + +### 모니터링 및 분석 + +```python +from collections import defaultdict +import time + +metrics = defaultdict(lambda: {'count': 0, 'total_time': 0}) + +@before_tool_call +def start_timer(context): + context.tool_input['_start'] = time.time() + return None + +@after_tool_call +def track_metrics(context): + start = context.tool_input.get('_start', time.time()) + duration = time.time() - start + + metrics[context.tool_name]['count'] += 1 + metrics[context.tool_name]['total_time'] += duration + + return None +``` + +## 훅 관리 + +### 모든 훅 지우기 + +```python +from crewai.hooks import clear_all_global_hooks + +# 모든 훅을 한 번에 지웁니다 +result = clear_all_global_hooks() +print(f"{result['total']} 훅이 지워졌습니다") +``` + +### 특정 훅 유형 지우기 + +```python +from crewai.hooks import ( + clear_before_llm_call_hooks, + clear_after_llm_call_hooks, + clear_before_tool_call_hooks, + clear_after_tool_call_hooks +) + +# 특정 유형 지우기 +llm_before_count = clear_before_llm_call_hooks() +tool_after_count = clear_after_tool_call_hooks() +``` + +## 모범 사례 + +### 1. 훅을 집중적으로 유지 +각 훅은 단일하고 명확한 책임을 가져야 합니다. + +### 2. 오류를 우아하게 처리 +```python +@before_llm_call +def safe_hook(context): + try: + if some_condition: + return False + except Exception as e: + print(f"훅 오류: {e}") + return None # 오류에도 불구하고 실행 허용 +``` + +### 3. 컨텍스트를 제자리에서 수정 +```python +# ✅ 올바름 - 제자리에서 수정 +@before_llm_call +def add_context(context): + context.messages.append({"role": "system", "content": "간결하게"}) + +# ❌ 잘못됨 - 참조를 교체 +@before_llm_call +def wrong_approach(context): + context.messages = [{"role": "system", "content": "간결하게"}] +``` + +### 4. 타입 힌트 사용 +```python +from crewai.hooks import LLMCallHookContext, ToolCallHookContext + +def my_llm_hook(context: LLMCallHookContext) -> bool | None: + return None + +def my_tool_hook(context: ToolCallHookContext) -> str | None: + return None +``` + +### 5. 테스트에서 정리 +```python +import pytest +from crewai.hooks import clear_all_global_hooks + +@pytest.fixture(autouse=True) +def clean_hooks(): + """각 테스트 전에 훅을 재설정합니다.""" + yield + clear_all_global_hooks() +``` + +## 어떤 훅을 사용해야 할까요 + +### LLM 훅을 사용하는 경우: +- 반복 제한 구현 +- 프롬프트에 컨텍스트 또는 안전 가이드라인 추가 +- 토큰 사용량 및 비용 추적 +- 응답 정제 또는 변환 +- LLM 호출에 대한 승인 게이트 구현 +- 프롬프트/응답 상호작용 디버깅 + +### 도구 훅을 사용하는 경우: +- 위험하거나 파괴적인 작업 차단 +- 실행 전 도구 입력 검증 +- 민감한 작업에 대한 승인 게이트 구현 +- 도구 결과 캐싱 +- 도구 사용 및 성능 추적 +- 도구 출력 정제 +- 도구 호출 속도 제한 + +### 둘 다 사용하는 경우: +모든 에이전트 작업을 모니터링해야 하는 포괄적인 관찰성, 안전 또는 승인 시스템을 구축하는 경우. + +## 관련 문서 + +- [LLM 호출 훅 →](/learn/llm-hooks) - 상세한 LLM 훅 문서 +- [도구 호출 훅 →](/learn/tool-hooks) - 상세한 도구 훅 문서 +- [킥오프 전후 훅 →](/learn/before-and-after-kickoff-hooks) - 크루 생명주기 훅 +- [사람의 개입 →](/learn/human-in-the-loop) - 사람 입력 패턴 + +## 결론 + +실행 훅은 에이전트 런타임 동작에 대한 강력한 제어를 제공합니다. 이를 사용하여 안전 가드레일, 승인 워크플로우, 포괄적인 모니터링 및 사용자 정의 비즈니스 로직을 구현하세요. 적절한 오류 처리, 타입 안전성 및 성능 고려사항과 결합하면, 훅을 통해 프로덕션 준비가 된 안전하고 관찰 가능한 에이전트 시스템을 구축할 수 있습니다. diff --git a/docs/v1.15.13/ko/learn/force-tool-output-as-result.mdx b/docs/v1.15.13/ko/learn/force-tool-output-as-result.mdx new file mode 100644 index 0000000000..1a1da0a5f5 --- /dev/null +++ b/docs/v1.15.13/ko/learn/force-tool-output-as-result.mdx @@ -0,0 +1,51 @@ +--- +title: 도구 출력 결과로 강제 지정하기 +description: CrewAI에서 에이전트의 작업에서 도구 출력을 결과로 강제 지정하는 방법을 알아봅니다. +icon: wrench-simple +mode: "wide" +--- + +## 소개 + +CrewAI에서는 도구의 출력을 에이전트 작업의 결과로 강제로 사용할 수 있습니다. +이 기능은 작업 실행 중에 에이전트가 출력을 수정하지 못하도록 하고, 도구의 출력이 반드시 캡처되어 작업 결과로 반환되도록 보장하고 싶을 때 유용합니다. + +## 도구 출력을 결과로 강제 지정하기 + +도구의 출력을 에이전트 작업의 결과로 강제 지정하려면, 에이전트에 도구를 추가할 때 `result_as_answer` 매개변수를 `True`로 설정해야 합니다. +이 매개변수는 도구의 출력이 에이전트에 의해 수정되지 않고 작업 결과로 캡처되어 반환되도록 보장합니다. + +다음은 에이전트 작업의 결과로 도구 출력을 강제 지정하는 방법의 예시입니다: + +```python Code +from crewai.agent import Agent +from my_tool import MyCustomTool + +# Create a coding agent with the custom tool +coding_agent = Agent( + role="Data Scientist", + goal="Produce amazing reports on AI", + backstory="You work with data and AI", + tools=[MyCustomTool(result_as_answer=True)], + ) + +# Assuming the tool's execution and result population occurs within the system +task_result = coding_agent.execute_task(task) +``` + +## 워크플로우 실행 + + + + 에이전트는 제공된 도구를 사용하여 작업을 수행합니다. + + + 도구가 출력을 생성하며, 이는 작업 결과로 캡처됩니다. + + + 에이전트는 도구에서 학습하고 반영할 수 있지만, 출력은 수정되지 않습니다. + + + 도구 출력은 어떠한 수정 없이 작업 결과로 반환됩니다. + + \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/hierarchical-process.mdx b/docs/v1.15.13/ko/learn/hierarchical-process.mdx new file mode 100644 index 0000000000..e659bd8d2e --- /dev/null +++ b/docs/v1.15.13/ko/learn/hierarchical-process.mdx @@ -0,0 +1,110 @@ +--- +title: 계층적 프로세스 +description: 최신 코딩 관행 및 기능을 반영하여 CrewAI 프로젝트 내에서 계층적 프로세스를 이해하고 적용하는 종합 가이드입니다. +icon: sitemap +mode: "wide" +--- + +## 소개 + +CrewAI의 계층적 프로세스는 효율적인 작업 위임 및 실행을 위해 전통적인 조직의 계층 구조를 모방하는 구조화된 작업 관리 방식을 도입합니다. +이러한 체계적인 워크플로우는 작업이 최적의 효율성과 정확성으로 처리될 수 있도록 하여 프로젝트 성과를 향상시킵니다. + + + 계층적 프로세스는 GPT-4와 같은 고급 모델을 활용하도록 설계되었으며, 복잡한 작업을 보다 효율적으로 처리하는 동시에 토큰 사용을 최적화합니다. + + +## 계층적 프로세스 개요 + +기본적으로 CrewAI에서 task는 순차적인 프로세스를 통해 관리됩니다. 그러나 계층적 접근 방식을 채택하면 명확한 계층 구조의 task 관리를 할 수 있습니다. +이 방식에서는 'manager' agent가 workflow를 조정하고, task를 위임하며, 결과를 검증하여 효율적이고 원활한 실행을 가능하게 합니다. 이 manager agent는 이제 CrewAI에서 자동으로 생성되거나 사용자가 명시적으로 설정할 수 있습니다. + +### 주요 기능 + +- **작업 위임**: 매니저 에이전트가 역할과 역량에 따라 crew 멤버에게 작업을 할당합니다. +- **결과 검증**: 매니저가 결과물을 평가하여 요구되는 기준을 충족하는지 확인합니다. +- **효율적인 워크플로우**: 기업 구조를 모방하여 체계적인 작업 관리 방식을 제공합니다. +- **시스템 프롬프트 처리**: 시스템이 사전 정의된 prompt를 사용할지 옵션으로 지정할 수 있습니다. +- **불용어 제어**: 불용어 사용 여부를 옵션으로 지정할 수 있으며, o1 모델 등 다양한 모델을 지원합니다. +- **컨텍스트 윈도우 존중**: 중요한 컨텍스트를 우선시하며, 컨텍스트 윈도우를 존중하는 것이 기본 동작입니다. +- **위임 제어**: 사용자에게 명확한 제어권을 주기 위해 기본적으로 위임이 비활성화되어 있습니다. +- **분당 최대 요청 수**: 분당 최대 요청 수를 설정할 수 있는 구성 옵션입니다. +- **최대 반복 횟수**: 최종 답변을 얻기 위한 최대 반복 횟수를 제한합니다. + +## 계층적 프로세스 구현하기 + +계층적 프로세스를 활용하려면, 프로세스 속성을 반드시 `Process.hierarchical`로 명시적으로 설정해야 합니다. 기본 동작은 `Process.sequential`입니다. +매니저가 지정된 crew를 정의하고, 명확한 명령 체계를 구축하세요. + + + 도구는 agent 수준에서 할당하여, 매니저의 지시에 따라 지정된 agent가 작업 위임 및 실행을 원활히 수행할 수 있도록 하십시오. + 도구는 작업 수준에서도 지정할 수 있어, 작업 수행 시 도구 가용성을 정밀하게 제어할 수 있습니다. + + + + 계층적 프로세스에서는 `manager_llm` 파라미터 설정이 매우 중요합니다. + 시스템이 올바르게 작동하려면 매니저 LLM이 반드시 설정되어야 하며, 이를 통해 맞춤형 의사결정이 가능합니다. + + +```python Code +from crewai import Crew, Process, Agent + +# Agents are defined with attributes for backstory, cache, and verbose mode +researcher = Agent( + role='Researcher', + goal='Conduct in-depth analysis', + backstory='Experienced data analyst with a knack for uncovering hidden trends.', +) +writer = Agent( + role='Writer', + goal='Create engaging content', + backstory='Creative writer passionate about storytelling in technical domains.', +) + +# Establishing the crew with a hierarchical process and additional configurations +project_crew = Crew( + tasks=[...], # Tasks to be delegated and executed under the manager's supervision + agents=[researcher, writer], + manager_llm="gpt-4o", # Specify which LLM the manager should use + process=Process.hierarchical, + planning=True, +) +``` + +### 커스텀 매니저 에이전트 사용하기 + +또 다른 방법으로, 프로젝트의 관리 요구 사항에 맞게 맞춤형 속성을 가진 커스텀 매니저 에이전트를 생성할 수 있습니다. 이를 통해 매니저의 동작 및 기능을 보다 세밀하게 제어할 수 있습니다. + +```python +# Define a custom manager agent +manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success.", + allow_delegation=True, +) + +# Use the custom manager in your crew +project_crew = Crew( + tasks=[...], + agents=[researcher, writer], + manager_agent=manager, # Use your custom manager agent + process=Process.hierarchical, + planning=True, +) +``` + + + 매니저 에이전트 생성 및 맞춤화에 대한 자세한 내용은 [커스텀 매니저 에이전트 문서](/ko/learn/custom-manager-agent)를 참고하세요. + + +### 워크플로우 실행 + +1. **작업 할당**: 매니저는 각 에이전트의 역량과 사용 가능한 도구를 고려하여 전략적으로 작업을 할당합니다. +2. **실행 및 검토**: 에이전트는 비동기 실행 옵션과 콜백 함수로 작업을 완료하여 워크플로우를 효율적으로 진행할 수 있습니다. +3. **순차적 작업 진행**: 계층적 프로세스임에도 불구하고, 매니저의 감독 하에 작업은 원활한 진행을 위해 논리적인 순서를 따릅니다. + +## 결론 + +CrewAI에서 계층적 프로세스를 올바른 구성과 시스템 기능에 대한 이해와 함께 도입하면, 조직적이고 효율적인 프로젝트 관리가 가능합니다. +고급 기능과 커스터마이징을 활용하여 워크플로우를 특정 요구에 맞게 맞춤화함으로써, 최적의 작업 실행과 프로젝트 성공을 보장할 수 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/human-feedback-in-flows.mdx b/docs/v1.15.13/ko/learn/human-feedback-in-flows.mdx new file mode 100644 index 0000000000..a6305ca8a7 --- /dev/null +++ b/docs/v1.15.13/ko/learn/human-feedback-in-flows.mdx @@ -0,0 +1,697 @@ +--- +title: Flow에서 인간 피드백 +description: "@human_feedback 데코레이터를 사용하여 CrewAI Flow에 인간 피드백을 직접 통합하는 방법을 알아보세요" +icon: user-check +mode: "wide" +--- + +## 개요 + + +`@human_feedback` 데코레이터는 **CrewAI 버전 1.8.0 이상**이 필요합니다. 이 기능을 사용하기 전에 설치를 업데이트하세요. + + +`@human_feedback` 데코레이터는 CrewAI Flow 내에서 직접 human-in-the-loop(HITL) 워크플로우를 가능하게 합니다. Flow 실행을 일시 중지하고, 인간에게 검토를 위해 출력을 제시하고, 피드백을 수집하고, 선택적으로 피드백 결과에 따라 다른 리스너로 라우팅할 수 있습니다. + +이는 특히 다음과 같은 경우에 유용합니다: + +- **품질 보증**: AI가 생성한 콘텐츠를 다운스트림에서 사용하기 전에 검토 +- **결정 게이트**: 자동화된 워크플로우에서 인간이 중요한 결정을 내리도록 허용 +- **승인 워크플로우**: 승인/거부/수정 패턴 구현 +- **대화형 개선**: 출력을 반복적으로 개선하기 위해 피드백 수집 + +```mermaid +flowchart LR + A[Flow 메서드] --> B[출력 생성됨] + B --> C[인간이 검토] + C --> D{피드백} + D -->|emit 지정됨| E[LLM이 Outcome으로 매핑] + D -->|emit 없음| F[HumanFeedbackResult] + E --> G["@listen('approved')"] + E --> H["@listen('rejected')"] + F --> I[다음 리스너] +``` + +## 빠른 시작 + +Flow에 인간 피드백을 추가하는 가장 간단한 방법은 다음과 같습니다: + +```python Code +from crewai.flow.flow import Flow, start, listen +from crewai.flow.human_feedback import human_feedback + +class SimpleReviewFlow(Flow): + @start() + @human_feedback(message="이 콘텐츠를 검토해 주세요:") + def generate_content(self): + return "검토가 필요한 AI 생성 콘텐츠입니다." + + @listen(generate_content) + def process_feedback(self, result): + print(f"콘텐츠: {result.output}") + print(f"인간의 의견: {result.feedback}") + +flow = SimpleReviewFlow() +flow.kickoff() +``` + +이 Flow를 실행하면: +1. `generate_content`를 실행하고 문자열을 반환합니다 +2. 요청 메시지와 함께 사용자에게 출력을 표시합니다 +3. 사용자가 피드백을 입력할 때까지 대기합니다 (또는 Enter를 눌러 건너뜁니다) +4. `HumanFeedbackResult` 객체를 `process_feedback`에 전달합니다 + +## @human_feedback 데코레이터 + +### 매개변수 + +| 매개변수 | 타입 | 필수 | 설명 | +|----------|------|------|------| +| `message` | `str` | 예 | 메서드 출력과 함께 인간에게 표시되는 메시지 | +| `emit` | `Sequence[str]` | 아니오 | 가능한 outcome 목록. 피드백이 이 중 하나로 매핑되어 `@listen` 데코레이터를 트리거합니다 | +| `llm` | `str \| BaseLLM` | `emit` 지정 시 | 피드백을 해석하고 outcome에 매핑하는 데 사용되는 LLM | +| `default_outcome` | `str` | 아니오 | 피드백이 제공되지 않을 때 사용할 outcome. `emit`에 있어야 합니다 | +| `metadata` | `dict` | 아니오 | 엔터프라이즈 통합을 위한 추가 데이터 | +| `provider` | `HumanFeedbackProvider` | 아니오 | 비동기/논블로킹 피드백을 위한 커스텀 프로바이더. [비동기 인간 피드백](#비동기-인간-피드백-논블로킹) 참조 | +| `learn` | `bool` | 아니오 | HITL 학습 활성화: 피드백에서 교훈을 추출하고 향후 출력을 사전 검토합니다. 기본값 `False`. [피드백에서 학습하기](#피드백에서-학습하기) 참조 | +| `learn_limit` | `int` | 아니오 | 사전 검토를 위해 불러올 최대 과거 교훈 수. 기본값 `5` | + +### 기본 사용법 (라우팅 없음) + +`emit`을 지정하지 않으면, 데코레이터는 단순히 피드백을 수집하고 다음 리스너에 `HumanFeedbackResult`를 전달합니다: + +```python Code +@start() +@human_feedback(message="이 분석에 대해 어떻게 생각하시나요?") +def analyze_data(self): + return "분석 결과: 매출 15% 증가, 비용 8% 감소" + +@listen(analyze_data) +def handle_feedback(self, result): + # result는 HumanFeedbackResult입니다 + print(f"분석: {result.output}") + print(f"피드백: {result.feedback}") +``` + +### emit을 사용한 라우팅 + +`emit`을 지정하면, 데코레이터는 라우터가 됩니다. 인간의 자유 형식 피드백이 LLM에 의해 해석되어 지정된 outcome 중 하나로 매핑됩니다: + +```python Code +from crewai.flow.flow import Flow, start, listen, or_ +from crewai.flow.human_feedback import human_feedback + +class ReviewFlow(Flow): + @start() + def generate_content(self): + return "블로그 게시물 초안 내용..." + + @human_feedback( + message="이 콘텐츠의 출판을 승인하시겠습니까?", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + @listen(or_("generate_content", "needs_revision")) + def review_content(self): + return "블로그 게시물 초안 내용..." + + @listen("approved") + def publish(self, result): + print(f"출판 중! 사용자 의견: {result.feedback}") + + @listen("rejected") + def discard(self, result): + print(f"폐기됨. 이유: {result.feedback}") +``` + +사용자가 "더 자세한 내용이 필요합니다"와 같이 말하면, LLM이 이를 `"needs_revision"`으로 매핑하고, `or_()`를 통해 `review_content`가 다시 트리거됩니다 — 수정 루프가 생성됩니다. outcome이 `"approved"` 또는 `"rejected"`가 될 때까지 루프가 계속됩니다. + + +LLM은 가능한 경우 구조화된 출력(function calling)을 사용하여 응답이 지정된 outcome 중 하나임을 보장합니다. 이로 인해 라우팅이 신뢰할 수 있고 예측 가능해집니다. + + + +`@start()` 메서드는 flow 시작 시 한 번만 실행됩니다. 수정 루프가 필요한 경우, start 메서드를 review 메서드와 분리하고 review 메서드에 `@listen(or_("trigger", "revision_outcome"))`를 사용하여 self-loop을 활성화하세요. + + +## HumanFeedbackResult + +`HumanFeedbackResult` 데이터클래스는 인간 피드백 상호작용에 대한 모든 정보를 포함합니다: + +```python Code +from crewai.flow.human_feedback import HumanFeedbackResult + +@dataclass +class HumanFeedbackResult: + output: Any # 인간에게 표시된 원래 메서드 출력 + feedback: str # 인간의 원시 피드백 텍스트 + outcome: str | None # 매핑된 outcome (emit이 지정된 경우) + timestamp: datetime # 피드백이 수신된 시간 + method_name: str # 데코레이터된 메서드의 이름 + metadata: dict # 데코레이터에 전달된 모든 메타데이터 +``` + +### 리스너에서 접근하기 + +`emit`이 있는 `@human_feedback` 메서드에 의해 리스너가 트리거되면, `HumanFeedbackResult`를 받습니다: + +```python Code +@listen("approved") +def on_approval(self, result: HumanFeedbackResult): + print(f"원래 출력: {result.output}") + print(f"사용자 피드백: {result.feedback}") + print(f"Outcome: {result.outcome}") # "approved" + print(f"수신 시간: {result.timestamp}") +``` + +## 피드백 히스토리 접근하기 + +`Flow` 클래스는 인간 피드백에 접근하기 위한 두 가지 속성을 제공합니다: + +### last_human_feedback + +가장 최근의 `HumanFeedbackResult`를 반환합니다: + +```python Code +@listen(some_method) +def check_feedback(self): + if self.last_human_feedback: + print(f"마지막 피드백: {self.last_human_feedback.feedback}") +``` + +### human_feedback_history + +Flow 동안 수집된 모든 `HumanFeedbackResult` 객체의 리스트입니다: + +```python Code +@listen(final_step) +def summarize(self): + print(f"수집된 총 피드백: {len(self.human_feedback_history)}") + for i, fb in enumerate(self.human_feedback_history): + print(f"{i+1}. {fb.method_name}: {fb.outcome or '라우팅 없음'}") +``` + + +각 `HumanFeedbackResult`는 `human_feedback_history`에 추가되므로, 여러 피드백 단계가 서로 덮어쓰지 않습니다. 이 리스트를 사용하여 Flow 동안 수집된 모든 피드백에 접근하세요. + + +## 완전한 예제: 콘텐츠 승인 워크플로우 + +콘텐츠 검토 및 승인 워크플로우를 구현하는 전체 예제입니다: + + + +```python Code +from crewai.flow.flow import Flow, start, listen, or_ +from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult +from pydantic import BaseModel + + +class ContentState(BaseModel): + draft: str = "" + revision_count: int = 0 + status: str = "pending" + + +class ContentApprovalFlow(Flow[ContentState]): + """콘텐츠를 생성하고 승인될 때까지 반복하는 Flow.""" + + @start() + def generate_draft(self): + self.state.draft = "# AI 안전\n\nAI 안전에 대한 초안..." + return self.state.draft + + @human_feedback( + message="이 초안을 검토해 주세요. 승인, 거부 또는 변경이 필요한 사항을 설명해 주세요:", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + @listen(or_("generate_draft", "needs_revision")) + def review_draft(self): + self.state.revision_count += 1 + return f"{self.state.draft} (v{self.state.revision_count})" + + @listen("approved") + def publish_content(self, result: HumanFeedbackResult): + self.state.status = "published" + print(f"콘텐츠 승인 및 게시! 리뷰어 의견: {result.feedback}") + return "published" + + @listen("rejected") + def handle_rejection(self, result: HumanFeedbackResult): + self.state.status = "rejected" + print(f"콘텐츠 거부됨. 이유: {result.feedback}") + return "rejected" + + +flow = ContentApprovalFlow() +result = flow.kickoff() +print(f"\nFlow 완료. 상태: {flow.state.status}, 검토 횟수: {flow.state.revision_count}") +``` + +```text Output +================================================== +OUTPUT FOR REVIEW: +================================================== +# AI 안전 + +AI 안전에 대한 초안... (v1) +================================================== + +이 초안을 검토해 주세요. 승인, 거부 또는 변경이 필요한 사항을 설명해 주세요: +(Press Enter to skip, or type your feedback) + +Your feedback: 더 자세한 내용이 필요합니다 + +================================================== +OUTPUT FOR REVIEW: +================================================== +# AI 안전 + +AI 안전에 대한 초안... (v2) +================================================== + +이 초안을 검토해 주세요. 승인, 거부 또는 변경이 필요한 사항을 설명해 주세요: +(Press Enter to skip, or type your feedback) + +Your feedback: 좋아 보입니다, 승인! + +콘텐츠 승인 및 게시! 리뷰어 의견: 좋아 보입니다, 승인! + +Flow 완료. 상태: published, 검토 횟수: 2 +``` + + + +## 다른 데코레이터와 결합하기 + +`@human_feedback` 데코레이터는 `@start()`, `@listen()`, `or_()`와 함께 작동합니다. 데코레이터 순서는 두 가지 모두 동작합니다—프레임워크가 양방향으로 속성을 전파합니다—하지만 권장 패턴은 다음과 같습니다: + +```python Code +# Flow 시작 시 일회성 검토 (self-loop 없음) +@start() +@human_feedback(message="이것을 검토해 주세요:", emit=["approved", "rejected"], llm="gpt-4o-mini") +def my_start_method(self): + return "content" + +# 리스너에서 선형 검토 (self-loop 없음) +@listen(other_method) +@human_feedback(message="이것도 검토해 주세요:", emit=["good", "bad"], llm="gpt-4o-mini") +def my_listener(self, data): + return f"processed: {data}" + +# Self-loop: 수정을 위해 반복할 수 있는 검토 +@human_feedback(message="승인 또는 수정 요청?", emit=["approved", "revise"], llm="gpt-4o-mini") +@listen(or_("upstream_method", "revise")) +def review_with_loop(self): + return "content for review" +``` + +### Self-loop 패턴 + +수정 루프를 만들려면 `or_()`를 사용하여 검토 메서드가 **상위 트리거**와 **자체 수정 outcome**을 모두 리스닝해야 합니다: + +```python Code +@start() +def generate(self): + return "initial draft" + +@human_feedback( + message="승인하시겠습니까, 아니면 변경을 요청하시겠습니까?", + emit=["revise", "approved"], + llm="gpt-4o-mini", + default_outcome="approved", +) +@listen(or_("generate", "revise")) +def review(self): + return "content" + +@listen("approved") +def publish(self): + return "published" +``` + +outcome이 `"revise"`이면 flow가 `review`로 다시 라우팅됩니다 (`or_()`를 통해 `"revise"`를 리스닝하기 때문). outcome이 `"approved"`이면 flow가 `publish`로 계속됩니다. flow 엔진이 라우터를 "한 번만 실행" 규칙에서 제외하여 각 루프 반복마다 재실행할 수 있기 때문에 이 패턴이 동작합니다. + +### 체인된 라우터 + +한 라우터의 outcome으로 트리거된 리스너가 그 자체로 라우터가 될 수 있습니다: + +```python Code +@start() +@human_feedback(message="첫 번째 검토:", emit=["approved", "rejected"], llm="gpt-4o-mini") +def draft(self): + return "draft content" + +@listen("approved") +@human_feedback(message="최종 검토:", emit=["publish", "revise"], llm="gpt-4o-mini") +def final_review(self, prev): + return "final content" + +@listen("publish") +def on_publish(self, prev): + return "published" +``` + +### 제한 사항 + +- **`@start()` 메서드는 한 번만 실행**: `@start()` 메서드는 self-loop할 수 없습니다. 수정 주기가 필요하면 별도의 `@start()` 메서드를 진입점으로 사용하고 `@listen()` 메서드에 `@human_feedback`를 배치하세요. +- **동일 메서드에 `@start()` + `@listen()` 불가**: 이는 Flow 프레임워크 제약입니다. 메서드는 시작점이거나 리스너여야 하며, 둘 다일 수 없습니다. + +## 모범 사례 + +### 1. 명확한 요청 메시지 작성 + +`message` 매개변수는 인간이 보는 것입니다. 실행 가능하게 만드세요: + +```python Code +# ✅ 좋음 - 명확하고 실행 가능 +@human_feedback(message="이 요약이 핵심 포인트를 정확하게 캡처했나요? '예'로 답하거나 무엇이 빠졌는지 설명해 주세요:") + +# ❌ 나쁨 - 모호함 +@human_feedback(message="이것을 검토해 주세요:") +``` + +### 2. 의미 있는 Outcome 선택 + +`emit`을 사용할 때, 인간의 응답에 자연스럽게 매핑되는 outcome을 선택하세요: + +```python Code +# ✅ 좋음 - 자연어 outcome +emit=["approved", "rejected", "needs_more_detail"] + +# ❌ 나쁨 - 기술적이거나 불명확 +emit=["state_1", "state_2", "state_3"] +``` + +### 3. 항상 기본 Outcome 제공 + +사용자가 입력 없이 Enter를 누르는 경우를 처리하기 위해 `default_outcome`을 사용하세요: + +```python Code +@human_feedback( + message="승인하시겠습니까? (수정 요청하려면 Enter 누르세요)", + emit=["approved", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", # 안전한 기본값 +) +``` + +### 4. 감사 추적을 위한 피드백 히스토리 사용 + +감사 로그를 생성하기 위해 `human_feedback_history`에 접근하세요: + +```python Code +@listen(final_step) +def create_audit_log(self): + log = [] + for fb in self.human_feedback_history: + log.append({ + "step": fb.method_name, + "outcome": fb.outcome, + "feedback": fb.feedback, + "timestamp": fb.timestamp.isoformat(), + }) + return log +``` + +### 5. 라우팅된 피드백과 라우팅되지 않은 피드백 모두 처리 + +Flow를 설계할 때, 라우팅이 필요한지 고려하세요: + +| 시나리오 | 사용 | +|----------|------| +| 간단한 검토, 피드백 텍스트만 필요 | `emit` 없음 | +| 응답에 따라 다른 경로로 분기 필요 | `emit` 사용 | +| 승인/거부/수정이 있는 승인 게이트 | `emit` 사용 | +| 로깅만을 위한 코멘트 수집 | `emit` 없음 | + +## 비동기 인간 피드백 (논블로킹) + +기본적으로 `@human_feedback`은 콘솔 입력을 기다리며 실행을 차단합니다. 프로덕션 애플리케이션에서는 Slack, 이메일, 웹훅 또는 API와 같은 외부 시스템과 통합되는 **비동기/논블로킹** 피드백이 필요할 수 있습니다. + +### Provider 추상화 + +커스텀 피드백 수집 전략을 지정하려면 `provider` 매개변수를 사용하세요: + +```python Code +from crewai.flow import Flow, start, human_feedback, HumanFeedbackProvider, HumanFeedbackPending, PendingFeedbackContext + +class WebhookProvider(HumanFeedbackProvider): + """웹훅 콜백을 기다리며 Flow를 일시 중지하는 Provider.""" + + def __init__(self, webhook_url: str): + self.webhook_url = webhook_url + + def request_feedback(self, context: PendingFeedbackContext, flow: Flow) -> str: + # 외부 시스템에 알림 (예: Slack 메시지 전송, 티켓 생성) + self.send_notification(context) + + # 실행 일시 중지 - 프레임워크가 자동으로 영속성 처리 + raise HumanFeedbackPending( + context=context, + callback_info={"webhook_url": f"{self.webhook_url}/{context.flow_id}"} + ) + +class ReviewFlow(Flow): + @start() + @human_feedback( + message="이 콘텐츠를 검토해 주세요:", + emit=["approved", "rejected"], + llm="gpt-4o-mini", + provider=WebhookProvider("https://myapp.com/api"), + ) + def generate_content(self): + return "AI가 생성한 콘텐츠..." + + @listen("approved") + def publish(self, result): + return "출판됨!" +``` + + +Flow 프레임워크는 `HumanFeedbackPending`이 발생하면 **자동으로 상태를 영속화**합니다. Provider는 외부 시스템에 알리고 예외를 발생시키기만 하면 됩니다—수동 영속성 호출이 필요하지 않습니다. + + +### 일시 중지된 Flow 처리 + +비동기 provider를 사용하면 `kickoff()`는 예외를 발생시키는 대신 `HumanFeedbackPending` 객체를 반환합니다: + +```python Code +flow = ReviewFlow() +result = flow.kickoff() + +if isinstance(result, HumanFeedbackPending): + # Flow가 일시 중지됨, 상태가 자동으로 영속화됨 + print(f"피드백 대기 중: {result.callback_info['webhook_url']}") + print(f"Flow ID: {result.context.flow_id}") +else: + # 정상 완료 + print(f"Flow 완료: {result}") +``` + +### 일시 중지된 Flow 재개 + +피드백이 도착하면 (예: 웹훅을 통해) Flow를 재개합니다: + +```python Code +# 동기 핸들러: +def handle_feedback_webhook(flow_id: str, feedback: str): + flow = ReviewFlow.from_pending(flow_id) + result = flow.resume(feedback) + return result + +# 비동기 핸들러 (FastAPI, aiohttp 등): +async def handle_feedback_webhook(flow_id: str, feedback: str): + flow = ReviewFlow.from_pending(flow_id) + result = await flow.resume_async(feedback) + return result +``` + +### 주요 타입 + +| 타입 | 설명 | +|------|------| +| `HumanFeedbackProvider` | 커스텀 피드백 provider를 위한 프로토콜 | +| `PendingFeedbackContext` | 일시 중지된 Flow를 재개하는 데 필요한 모든 정보 포함 | +| `HumanFeedbackPending` | Flow가 피드백을 위해 일시 중지되면 `kickoff()`에서 반환됨 | +| `ConsoleProvider` | 기본 블로킹 콘솔 입력 provider | + +### PendingFeedbackContext + +컨텍스트는 재개에 필요한 모든 것을 포함합니다: + +```python Code +@dataclass +class PendingFeedbackContext: + flow_id: str # 이 Flow 실행의 고유 식별자 + flow_class: str # 정규화된 클래스 이름 + method_name: str # 피드백을 트리거한 메서드 + method_output: Any # 인간에게 표시된 출력 + message: str # 요청 메시지 + emit: list[str] | None # 라우팅을 위한 가능한 outcome + default_outcome: str | None + metadata: dict # 커스텀 메타데이터 + llm: str | None # outcome 매핑을 위한 LLM + requested_at: datetime +``` + +### 완전한 비동기 Flow 예제 + +```python Code +from crewai.flow import ( + Flow, start, listen, human_feedback, + HumanFeedbackProvider, HumanFeedbackPending, PendingFeedbackContext +) + +class SlackNotificationProvider(HumanFeedbackProvider): + """Slack 알림을 보내고 비동기 피드백을 위해 일시 중지하는 Provider.""" + + def __init__(self, channel: str): + self.channel = channel + + def request_feedback(self, context: PendingFeedbackContext, flow: Flow) -> str: + # Slack 알림 전송 (직접 구현) + slack_thread_id = self.post_to_slack( + channel=self.channel, + message=f"검토 필요:\n\n{context.method_output}\n\n{context.message}", + ) + + # 실행 일시 중지 - 프레임워크가 자동으로 영속성 처리 + raise HumanFeedbackPending( + context=context, + callback_info={ + "slack_channel": self.channel, + "thread_id": slack_thread_id, + } + ) + +class ContentPipeline(Flow): + @start() + @human_feedback( + message="이 콘텐츠의 출판을 승인하시겠습니까?", + emit=["approved", "rejected"], + llm="gpt-4o-mini", + default_outcome="rejected", + provider=SlackNotificationProvider("#content-reviews"), + ) + def generate_content(self): + return "AI가 생성한 블로그 게시물 콘텐츠..." + + @listen("approved") + def publish(self, result): + print(f"출판 중! 검토자 의견: {result.feedback}") + return {"status": "published"} + + @listen("rejected") + def archive(self, result): + print(f"보관됨. 이유: {result.feedback}") + return {"status": "archived"} + + +# Flow 시작 (Slack 응답을 기다리며 일시 중지) +def start_content_pipeline(): + flow = ContentPipeline() + result = flow.kickoff() + + if isinstance(result, HumanFeedbackPending): + return {"status": "pending", "flow_id": result.context.flow_id} + + return result + + +# Slack 웹훅이 실행될 때 재개 (동기 핸들러) +def on_slack_feedback(flow_id: str, slack_message: str): + flow = ContentPipeline.from_pending(flow_id) + result = flow.resume(slack_message) + return result + + +# 핸들러가 비동기인 경우 (FastAPI, aiohttp, Slack Bolt 비동기 등) +async def on_slack_feedback_async(flow_id: str, slack_message: str): + flow = ContentPipeline.from_pending(flow_id) + result = await flow.resume_async(slack_message) + return result +``` + + +비동기 웹 프레임워크(FastAPI, aiohttp, Slack Bolt 비동기 모드)를 사용하는 경우 `flow.resume()` 대신 `await flow.resume_async()`를 사용하세요. 실행 중인 이벤트 루프 내에서 `resume()`을 호출하면 `RuntimeError`가 발생합니다. + + +### 비동기 피드백 모범 사례 + +1. **반환 타입 확인**: `kickoff()`는 일시 중지되면 `HumanFeedbackPending`을 반환합니다—try/except가 필요하지 않습니다 +2. **올바른 resume 메서드 사용**: 동기 코드에서는 `resume()`, 비동기 코드에서는 `await resume_async()` 사용 +3. **콜백 정보 저장**: `callback_info`를 사용하여 웹훅 URL, 티켓 ID 등을 저장 +4. **멱등성 구현**: 안전을 위해 resume 핸들러는 멱등해야 합니다 +5. **자동 영속성**: `HumanFeedbackPending`이 발생하면 상태가 자동으로 저장되며 기본적으로 `SQLiteFlowPersistence` 사용 +6. **커스텀 영속성**: 필요한 경우 `from_pending()`에 커스텀 영속성 인스턴스 전달 + +## 피드백에서 학습하기 + +`learn=True` 매개변수는 인간 검토자와 메모리 시스템 간의 피드백 루프를 활성화합니다. 활성화되면 시스템은 과거 인간의 수정 사항에서 학습하여 출력을 점진적으로 개선합니다. + +### 작동 방식 + +1. **피드백 후**: LLM이 출력 + 피드백에서 일반화 가능한 교훈을 추출하고 `source="hitl"`로 메모리에 저장합니다. 피드백이 단순한 승인(예: "좋아 보입니다")인 경우 아무것도 저장하지 않습니다. +2. **다음 검토 전**: 과거 HITL 교훈을 메모리에서 불러와 LLM이 인간이 보기 전에 출력을 개선하는 데 적용합니다. + +시간이 지남에 따라 각 수정 사항이 향후 검토에 반영되므로 인간은 점진적으로 더 나은 사전 검토된 출력을 보게 됩니다. + +### 예제 + +```python Code +class ArticleReviewFlow(Flow): + @start() + def generate_article(self): + return self.crew.kickoff(inputs={"topic": "AI Safety"}).raw + + @human_feedback( + message="이 글 초안을 검토해 주세요:", + emit=["approved", "needs_revision"], + llm="gpt-4o-mini", + learn=True, + ) + @listen(or_("generate_article", "needs_revision")) + def review_article(self): + return self.last_human_feedback.output if self.last_human_feedback else "article draft" + + @listen("approved") + def publish(self): + print(f"Publishing: {self.last_human_feedback.output}") +``` + +**첫 번째 실행**: 인간이 원시 출력을 보고 "사실에 대한 주장에는 항상 인용을 포함하세요."라고 말합니다. 교훈이 추출되어 메모리에 저장됩니다. + +**두 번째 실행**: 시스템이 인용 교훈을 불러와 출력을 사전 검토하여 인용을 추가한 후 개선된 버전을 표시합니다. 인간의 역할이 "모든 것을 수정"에서 "시스템이 놓친 것을 찾기"로 전환됩니다. + +### 구성 + +| 매개변수 | 기본값 | 설명 | +|-----------|--------|------| +| `learn` | `False` | HITL 학습 활성화 | +| `learn_limit` | `5` | 사전 검토를 위해 불러올 최대 과거 교훈 수 | + +### 주요 설계 결정 + +- **모든 것에 동일한 LLM 사용**: 데코레이터의 `llm` 매개변수는 outcome 매핑, 교훈 추출, 사전 검토에 공유됩니다. 여러 모델을 구성할 필요가 없습니다. +- **구조화된 출력**: 추출과 사전 검토 모두 LLM이 지원하는 경우 Pydantic 모델과 함께 function calling을 사용하고, 그렇지 않으면 텍스트 파싱으로 폴백합니다. +- **논블로킹 저장**: 교훈은 백그라운드 스레드에서 실행되는 `remember_many()`를 통해 저장됩니다 -- Flow는 즉시 계속됩니다. +- **우아한 저하**: 추출 중 LLM이 실패하면 아무것도 저장하지 않습니다. 사전 검토 중 실패하면 원시 출력이 표시됩니다. 어느 쪽의 실패도 Flow를 차단하지 않습니다. +- **범위/카테고리 불필요**: 교훈을 저장할 때 `source`만 전달됩니다. 인코딩 파이프라인이 범위, 카테고리, 중요도를 자동으로 추론합니다. + + +`learn=True`는 Flow에 메모리가 사용 가능해야 합니다. Flow는 기본적으로 자동으로 메모리를 얻지만, `_skip_auto_memory`로 비활성화한 경우 HITL 학습은 조용히 건너뜁니다. + + + +## 관련 문서 + +- [Flow 개요](/ko/concepts/flows) - CrewAI Flow에 대해 알아보기 +- [Flow 상태 관리](/ko/guides/flows/mastering-flow-state) - Flow에서 상태 관리하기 +- [Flow 영속성](/ko/concepts/flows#persistence) - Flow 상태 영속화 +- [@router를 사용한 라우팅](/ko/concepts/flows#router) - 조건부 라우팅에 대해 더 알아보기 +- [실행 시 인간 입력](/ko/learn/human-input-on-execution) - 태스크 수준 인간 입력 +- [메모리](/ko/concepts/memory) - HITL 학습에서 사용되는 통합 메모리 시스템 diff --git a/docs/v1.15.13/ko/learn/human-in-the-loop.mdx b/docs/v1.15.13/ko/learn/human-in-the-loop.mdx new file mode 100644 index 0000000000..702b71c942 --- /dev/null +++ b/docs/v1.15.13/ko/learn/human-in-the-loop.mdx @@ -0,0 +1,120 @@ +--- +title: "Human-in-the-Loop (HITL) 워크플로우" +description: "CrewAI에서 Human-in-the-Loop 워크플로우를 구현하여 의사결정을 향상시키는 방법을 알아보세요" +icon: "user-check" +mode: "wide" +--- + +휴먼 인 더 루프(HITL, Human-in-the-Loop)는 인공지능과 인간의 전문 지식을 결합하여 의사결정을 강화하고 작업 결과를 향상시키는 강력한 접근 방식입니다. CrewAI는 필요에 따라 HITL을 구현하는 여러 가지 방법을 제공합니다. + +## HITL 접근 방식 선택 + +CrewAI는 human-in-the-loop 워크플로우를 구현하기 위한 두 가지 주요 접근 방식을 제공합니다: + +| 접근 방식 | 적합한 용도 | 통합 | 버전 | +|----------|----------|-------------|---------| +| **Flow 기반** (`@human_feedback` 데코레이터) | 로컬 개발, 콘솔 기반 검토, 동기식 워크플로우 | [Flow에서 인간 피드백](/ko/learn/human-feedback-in-flows) | **1.8.0+** | +| **Webhook 기반** (Enterprise) | 프로덕션 배포, 비동기 워크플로우, 외부 통합 (Slack, Teams 등) | 이 가이드 | - | + + +Flow를 구축하면서 피드백을 기반으로 라우팅하는 인간 검토 단계를 추가하려면 `@human_feedback` 데코레이터에 대한 [Flow에서 인간 피드백](/ko/learn/human-feedback-in-flows) 가이드를 참조하세요. + + +## Webhook 기반 HITL 워크플로우 설정 + + + + human input이 활성화된 상태로 작업을 설정하세요: + + Crew Human Input + + + + + crew를 시작할 때, human input을 위한 webhook URL을 포함하세요: + + Crew Webhook URL + + + + + crew가 human input이 필요한 작업을 완료하면, 다음 내용을 포함하는 webhook 알림을 받게 됩니다: + - 실행 ID + - 작업 ID + - 작업 출력 + + + + 시스템이 `Pending Human Input` 상태에서 일시정지됩니다. 작업 출력을 신중하게 검토하세요. + + + + 다음 정보를 포함하여 crew의 resume endpoint를 호출하세요: + + Crew Resume Endpoint + + + + **중요: Webhook URL을 다시 제공해야 합니다**: + kickoff 호출에서 사용한 것과 동일한 webhook URL(`taskWebhookUrl`, `stepWebhookUrl`, `crewWebhookUrl`)을 resume 호출에서 **반드시** 제공해야 합니다. Webhook 설정은 kickoff에서 자동으로 전달되지 **않으므로**, 작업 완료, 에이전트 단계, crew 완료에 대한 알림을 계속 받으려면 resume 요청에 명시적으로 포함해야 합니다. + + + Webhook을 포함한 resume 호출 예시: + ```bash + curl -X POST {BASE_URL}/resume \ + -H "Authorization: Bearer YOUR_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "execution_id": "abcd1234-5678-90ef-ghij-klmnopqrstuv", + "task_id": "research_task", + "human_feedback": "훌륭한 작업입니다! 더 자세한 내용을 추가해주세요.", + "is_approve": true, + "taskWebhookUrl": "https://your-server.com/webhooks/task", + "stepWebhookUrl": "https://your-server.com/webhooks/step", + "crewWebhookUrl": "https://your-server.com/webhooks/crew" + }' + ``` + + + **피드백이 작업 실행에 미치는 영향**: + 피드백의 전체 내용이 추가 컨텍스트로서 이후 작업 실행에 통합되므로, 피드백 제공 시 신중을 기하는 것이 매우 중요합니다. + + 즉: + - 피드백에 포함된 모든 정보가 작업의 컨텍스트의 일부가 됩니다. + - 관련 없는 세부 정보는 작업에 부정적인 영향을 미칠 수 있습니다. + - 간결하고 관련성 높은 피드백이 작업의 집중력과 효율성을 유지하는 데 도움이 됩니다. + - 제출 전에 피드백을 항상 꼼꼼히 검토하여 작업 실행을 긍정적으로 이끌 수 있는 정보만 포함되어 있는지 확인하세요. + + + 부정적인 피드백을 제공할 경우: + - crew는 피드백에서 얻은 추가 컨텍스트로 작업을 재시도합니다. + - 추가 검토를 위한 또 다른 webhook 알림을 받게 됩니다. + - 만족할 때까지 4-6단계를 반복하세요. + + + + 긍정적인 피드백을 제출하면 실행이 다음 단계로 진행됩니다. + + + +## 모범 사례 + +- **구체적으로 작성하세요**: 해당 작업에 직접적으로 관련된 명확하고 실행 가능한 피드백을 제공하세요 +- **관련성을 유지하세요**: 작업 수행 개선에 도움이 되는 정보만 포함하세요 +- **시기적절하게 응답하세요**: 워크플로우 지연을 방지하기 위해 HITL 프롬프트에 신속하게 응답하세요 +- **신중하게 검토하세요**: 제출 전 피드백을 다시 확인하여 정확성을 확보하세요 + +## 일반적인 사용 사례 + +HITL 워크플로우는 다음과 같은 경우에 특히 유용합니다: +- 품질 보증 및 검증 +- 복잡한 의사결정 시나리오 +- 민감하거나 고위험 작업 +- 인간의 판단이 필요한 창의적 과제 +- 컴플라이언스 및 규제 검토 + +## Enterprise 기능 + + + CrewAI Enterprise는 플랫폼 내 검토, 응답자 할당, 권한, 에스컬레이션 정책, SLA 관리, 동적 라우팅 및 전체 분석을 갖춘 Flow용 포괄적인 HITL 관리 시스템을 제공합니다. [자세히 알아보기 →](https://docs-platform.crewai.com/platform/ko/features/flow-hitl-management) + diff --git a/docs/v1.15.13/ko/learn/human-input-on-execution.mdx b/docs/v1.15.13/ko/learn/human-input-on-execution.mdx new file mode 100644 index 0000000000..4eb4bca3cb --- /dev/null +++ b/docs/v1.15.13/ko/learn/human-input-on-execution.mdx @@ -0,0 +1,99 @@ +--- +title: 실행 중 인간 입력 +description: 복잡한 의사결정 과정에서 실행 중 CrewAI와 인간 입력을 통합하고, 에이전트의 속성과 도구의 모든 기능을 활용하는 방법. +icon: user-plus +mode: "wide" +--- + +## 에이전트 실행에서의 인간 입력 + +인간 입력은 여러 에이전트 실행 시나리오에서 매우 중요하며, 에이전트가 필요할 때 추가 정보나 설명을 요청할 수 있게 해줍니다. +이 기능은 특히 복잡한 의사결정 과정이나 에이전트가 작업을 효과적으로 완료하기 위해 더 많은 세부 정보가 필요할 때 유용하게 사용됩니다. + +## CrewAI에서 인간 입력 사용하기 + +에이전트 실행에 인간 입력을 통합하려면, 태스크 정의에서 `human_input` 플래그를 설정하세요. 이 기능이 활성화되면 에이전트는 최종 답변을 제공하기 전에 사용자에게 입력을 요청합니다. +이 입력은 추가적인 컨텍스트를 제공하거나, 모호성을 해소하거나, 에이전트의 출력을 검증하는 데 사용할 수 있습니다. + +### 예시: + +```shell +pip install crewai +``` + +```python Code +import os +from crewai import Agent, Task, Crew +from crewai_tools import SerperDevTool + +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key +os.environ["OPENAI_API_KEY"] = "Your Key" + +# Loading Tools +search_tool = SerperDevTool() + +# Define your agents with roles, goals, tools, and additional attributes +researcher = Agent( + role='Senior Research Analyst', + goal='Uncover cutting-edge developments in AI and data science', + backstory=( + "You are a Senior Research Analyst at a leading tech think tank. " + "Your expertise lies in identifying emerging trends and technologies in AI and data science. " + "You have a knack for dissecting complex data and presenting actionable insights." + ), + verbose=True, + allow_delegation=False, + tools=[search_tool] +) +writer = Agent( + role='Tech Content Strategist', + goal='Craft compelling content on tech advancements', + backstory=( + "You are a renowned Tech Content Strategist, known for your insightful and engaging articles on technology and innovation. " + "With a deep understanding of the tech industry, you transform complex concepts into compelling narratives." + ), + verbose=True, + allow_delegation=True, + tools=[search_tool], + cache=False, # Disable cache for this agent +) + +# Create tasks for your agents +task1 = Task( + description=( + "Conduct a comprehensive analysis of the latest advancements in AI in 2025. " + "Identify key trends, breakthrough technologies, and potential industry impacts. " + "Compile your findings in a detailed report. " + "Make sure to check with a human if the draft is good before finalizing your answer." + ), + expected_output='A comprehensive full report on the latest AI advancements in 2025, leave nothing out', + agent=researcher, + human_input=True +) + +task2 = Task( + description=( + "Using the insights from the researcher\'s report, develop an engaging blog post that highlights the most significant AI advancements. " + "Your post should be informative yet accessible, catering to a tech-savvy audience. " + "Aim for a narrative that captures the essence of these breakthroughs and their implications for the future." + ), + expected_output='A compelling 3 paragraphs blog post formatted as markdown about the latest AI advancements in 2025', + agent=writer, + human_input=True +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[researcher, writer], + tasks=[task1, task2], + verbose=True, + memory=True, + planning=True # Enable planning feature for the crew +) + +# Get your crew to work! +result = crew.kickoff() + +print("######################") +print(result) +``` diff --git a/docs/v1.15.13/ko/learn/kickoff-async.mdx b/docs/v1.15.13/ko/learn/kickoff-async.mdx new file mode 100644 index 0000000000..46292b36ec --- /dev/null +++ b/docs/v1.15.13/ko/learn/kickoff-async.mdx @@ -0,0 +1,306 @@ +--- +title: Crew 비동기 시작 +description: Crew를 비동기로 시작하기 +icon: rocket-launch +mode: "wide" +--- + +## 소개 + +CrewAI는 crew를 비동기적으로 시작할 수 있는 기능을 제공합니다. 이를 통해 crew 실행을 블로킹(blocking) 없이 시작할 수 있습니다. +이 기능은 여러 개의 crew를 동시에 실행하거나 crew가 실행되는 동안 다른 작업을 수행해야 할 때 특히 유용합니다. + +CrewAI는 비동기 실행을 위해 두 가지 접근 방식을 제공합니다: + +| 메서드 | 타입 | 설명 | +|--------|------|-------------| +| `akickoff()` | 네이티브 async | 전체 실행 체인에서 진정한 async/await 사용 | +| `kickoff_async()` | 스레드 기반 | 동기 실행을 `asyncio.to_thread`로 래핑 | + + +고동시성 워크로드의 경우 `akickoff()`가 권장됩니다. 이는 작업 실행, 메모리 작업, 지식 검색에 네이티브 async를 사용합니다. + + +## `akickoff()`를 사용한 네이티브 비동기 실행 + +`akickoff()` 메서드는 작업 실행, 메모리 작업, 지식 쿼리를 포함한 전체 실행 체인에서 async/await를 사용하여 진정한 네이티브 비동기 실행을 제공합니다. + +### 메서드 시그니처 + +```python Code +async def akickoff(self, inputs: dict) -> CrewOutput: +``` + +### 매개변수 + +- `inputs` (dict): 작업에 필요한 입력 데이터를 포함하는 딕셔너리입니다. + +### 반환 + +- `CrewOutput`: crew 실행 결과를 나타내는 객체입니다. + +### 예시: 네이티브 비동기 Crew 실행 + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +# 에이전트 생성 +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# 작업 생성 +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +# Crew 생성 +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +# 네이티브 비동기 실행 +async def main(): + result = await analysis_crew.akickoff(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + +asyncio.run(main()) +``` + +### 예시: 여러 네이티브 비동기 Crew + +`asyncio.gather()`를 사용하여 네이티브 async로 여러 crew를 동시에 실행: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +task_1 = Task( + description="Analyze the first dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +task_2 = Task( + description="Analyze the second dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +crew_1 = Crew(agents=[coding_agent], tasks=[task_1]) +crew_2 = Crew(agents=[coding_agent], tasks=[task_2]) + +async def main(): + results = await asyncio.gather( + crew_1.akickoff(inputs={"ages": [25, 30, 35, 40, 45]}), + crew_2.akickoff(inputs={"ages": [20, 22, 24, 28, 30]}) + ) + + for i, result in enumerate(results, 1): + print(f"Crew {i} Result:", result) + +asyncio.run(main()) +``` + +### 예시: 여러 입력에 대한 네이티브 비동기 + +`akickoff_for_each()`를 사용하여 네이티브 async로 여러 입력에 대해 crew를 동시에 실행: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +async def main(): + datasets = [ + {"ages": [25, 30, 35, 40, 45]}, + {"ages": [20, 22, 24, 28, 30]}, + {"ages": [30, 35, 40, 45, 50]} + ] + + results = await analysis_crew.akickoff_for_each(datasets) + + for i, result in enumerate(results, 1): + print(f"Dataset {i} Result:", result) + +asyncio.run(main()) +``` + +## `kickoff_async()`를 사용한 스레드 기반 비동기 + +`kickoff_async()` 메서드는 동기 `kickoff()`를 스레드로 래핑하여 비동기 실행을 제공합니다. 이는 더 간단한 비동기 통합이나 하위 호환성에 유용합니다. + +### 메서드 시그니처 + +```python Code +async def kickoff_async(self, inputs: dict) -> CrewOutput: +``` + +### 매개변수 + +- `inputs` (dict): 작업에 필요한 입력 데이터를 포함하는 딕셔너리입니다. + +### 반환 + +- `CrewOutput`: crew 실행 결과를 나타내는 객체입니다. + +### 예시: 스레드 기반 비동기 실행 + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +async def async_crew_execution(): + result = await analysis_crew.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + +asyncio.run(async_crew_execution()) +``` + +### 예시: 여러 스레드 기반 비동기 Crew + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +task_1 = Task( + description="Analyze the first dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +task_2 = Task( + description="Analyze the second dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +crew_1 = Crew(agents=[coding_agent], tasks=[task_1]) +crew_2 = Crew(agents=[coding_agent], tasks=[task_2]) + +async def async_multiple_crews(): + result_1 = crew_1.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + result_2 = crew_2.kickoff_async(inputs={"ages": [20, 22, 24, 28, 30]}) + + results = await asyncio.gather(result_1, result_2) + + for i, result in enumerate(results, 1): + print(f"Crew {i} Result:", result) + +asyncio.run(async_multiple_crews()) +``` + +## 비동기 스트리밍 + +두 비동기 메서드 모두 crew에 `stream=True`가 설정된 경우 스트리밍을 지원합니다: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +agent = Agent( + role="Researcher", + goal="Research and summarize topics", + backstory="You are an expert researcher." +) + +task = Task( + description="Research the topic: {topic}", + agent=agent, + expected_output="A comprehensive summary of the topic." +) + +crew = Crew( + agents=[agent], + tasks=[task], + stream=True # 스트리밍 활성화 +) + +async def main(): + streaming_output = await crew.akickoff(inputs={"topic": "AI trends in 2024"}) + + # 스트리밍 청크에 대한 비동기 반복 + async for chunk in streaming_output: + print(f"Chunk: {chunk.content}") + + # 스트리밍 완료 후 최종 결과 접근 + result = streaming_output.result + print(f"Final result: {result.raw}") + +asyncio.run(main()) +``` + +## 잠재적 사용 사례 + +- **병렬 콘텐츠 생성**: 여러 개의 독립적인 crew를 비동기적으로 시작하여, 각 crew가 다른 주제에 대한 콘텐츠 생성을 담당합니다. 예를 들어, 한 crew는 AI 트렌드에 대한 기사 조사 및 초안을 작성하는 반면, 또 다른 crew는 신제품 출시와 관련된 소셜 미디어 게시물을 생성할 수 있습니다. + +- **동시 시장 조사 작업**: 여러 crew를 비동기적으로 시작하여 시장 조사를 병렬로 수행합니다. 한 crew는 업계 동향을 분석하고, 또 다른 crew는 경쟁사 전략을 조사하며, 또 다른 crew는 소비자 감정을 평가할 수 있습니다. + +- **독립적인 여행 계획 모듈**: 각각 독립적으로 여행의 다양한 측면을 계획하도록 crew를 따로 실행합니다. 한 crew는 항공편 옵션을, 다른 crew는 숙박을, 세 번째 crew는 활동 계획을 담당할 수 있습니다. + +## `akickoff()`와 `kickoff_async()` 선택하기 + +| 기능 | `akickoff()` | `kickoff_async()` | +|---------|--------------|-------------------| +| 실행 모델 | 네이티브 async/await | 스레드 기반 래퍼 | +| 작업 실행 | `aexecute_sync()`로 비동기 | 스레드 풀에서 동기 | +| 메모리 작업 | 비동기 | 스레드 풀에서 동기 | +| 지식 검색 | 비동기 | 스레드 풀에서 동기 | +| 적합한 용도 | 고동시성, I/O 바운드 워크로드 | 간단한 비동기 통합 | +| 스트리밍 지원 | 예 | 예 | diff --git a/docs/v1.15.13/ko/learn/kickoff-for-each.mdx b/docs/v1.15.13/ko/learn/kickoff-for-each.mdx new file mode 100644 index 0000000000..4f10abb378 --- /dev/null +++ b/docs/v1.15.13/ko/learn/kickoff-for-each.mdx @@ -0,0 +1,54 @@ +--- +title: 각 항목에 대한 Kickoff Crew +description: 목록의 각 항목에 대한 Kickoff Crew +icon: at +mode: "wide" +--- + +## 소개 + +CrewAI는 목록의 각 항목에 대해 crew를 시작할 수 있는 기능을 제공하여, 목록의 각 항목에 대해 crew를 실행할 수 있게 합니다. +이 기능은 여러 항목에 대해 동일한 작업 세트를 수행해야 할 때 특히 유용합니다. + +## 각 항목에 대해 크루 시작하기 + +리스트의 각 항목에 대해 크루를 시작하려면 `kickoff_for_each()` 메서드를 사용하세요. +이 메서드는 리스트의 각 항목에 대해 크루를 실행하여 여러 항목을 효율적으로 처리할 수 있도록 합니다. + +아래는 리스트의 각 항목에 대해 크루를 시작하는 방법의 예시입니다: + +```python Code +from crewai import Crew, Agent, Task + +# Create an agent with code execution enabled +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task that requires code execution +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age calculated from the dataset" +) + +# Create a crew and add the task +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task], + verbose=True, + memory=False +) + +datasets = [ + { "ages": [25, 30, 35, 40, 45] }, + { "ages": [20, 25, 30, 35, 40] }, + { "ages": [30, 35, 40, 45, 50] } +] + +# Execute the crew +result = analysis_crew.kickoff_for_each(inputs=datasets) +``` \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/llm-connections.mdx b/docs/v1.15.13/ko/learn/llm-connections.mdx new file mode 100644 index 0000000000..6976ab8e03 --- /dev/null +++ b/docs/v1.15.13/ko/learn/llm-connections.mdx @@ -0,0 +1,214 @@ +--- +title: 모든 LLM에 연결하기 +description: LiteLLM을 사용하여 CrewAI를 다양한 대형 언어 모델(LLM)과 통합하는 방법에 대한 종합적인 가이드로, 지원되는 제공자와 구성 옵션을 포함합니다. +icon: brain-circuit +mode: "wide" +--- + +## CrewAI를 LLM에 연결하기 + +CrewAI는 가장 인기 있는 제공자(OpenAI, Anthropic, Google Gemini, Azure, AWS Bedrock)에 대해 네이티브 SDK 통합을 통해 LLM에 연결하며, 그 외 모든 제공자에 대해서는 LiteLLM을 유연한 폴백으로 사용합니다. + + + 기본적으로 CrewAI는 `gpt-4o-mini` 모델을 사용합니다. 이는 `OPENAI_MODEL_NAME` 환경 변수에 의해 결정되며, 설정되지 않은 경우 기본값은 "gpt-4o-mini"입니다. + 본 가이드에 설명된 대로 다른 모델이나 공급자를 사용하도록 에이전트를 쉽게 설정할 수 있습니다. + + +## 지원되는 프로바이더 + +LiteLLM은 다음을 포함하되 이에 국한되지 않는 다양한 프로바이더를 지원합니다: + +- OpenAI +- Anthropic +- Google (Vertex AI, Gemini) +- Azure OpenAI +- AWS (Bedrock, SageMaker) +- Cohere +- VoyageAI +- Hugging Face +- Ollama +- Mistral AI +- Replicate +- Together AI +- AI21 +- Cloudflare Workers AI +- DeepInfra +- Groq +- SambaNova +- Nebius AI Studio +- [NVIDIA NIMs](https://docs.api.nvidia.com/nim/reference/models-1) +- 그리고 더 많은 프로바이더! + +지원되는 프로바이더의 전체 및 최신 목록은 [LiteLLM 프로바이더 문서](https://docs.litellm.ai/docs/providers)를 참조하세요. + + + 네이티브 통합에서 지원하지 않는 제공자를 사용하려면 LiteLLM을 프로젝트에 의존성으로 추가하세요: + ```bash + uv add 'crewai[litellm]' + ``` + 네이티브 제공자(OpenAI, Anthropic, Google Gemini, Azure, AWS Bedrock)는 자체 SDK extras를 사용합니다 — [공급자 구성 예시](/ko/concepts/llms#공급자-구성-예시)를 참조하세요. + + +## LLM 변경하기 + +CrewAI agent에서 다른 LLM을 사용하려면 여러 가지 방법이 있습니다: + + + + agent를 초기화할 때 모델 이름을 문자열로 전달하세요: + + ```python Code + from crewai import Agent + + # OpenAI의 GPT-4 사용 + openai_agent = Agent( + role='OpenAI Expert', + goal='Provide insights using GPT-4', + backstory="An AI assistant powered by OpenAI's latest model.", + llm='gpt-4' + ) + + # Anthropic의 Claude 사용 + claude_agent = Agent( + role='Anthropic Expert', + goal='Analyze data using Claude', + backstory="An AI assistant leveraging Anthropic's language model.", + llm='claude-2' + ) + ``` + + + + 더 자세한 설정을 위해 LLM 클래스를 사용하세요: + + ```python Code + from crewai import Agent, LLM + + llm = LLM( + model="gpt-4", + temperature=0.7, + base_url="https://api.openai.com/v1", + api_key="your-api-key-here" + ) + + agent = Agent( + role='Customized LLM Expert', + goal='Provide tailored responses', + backstory="An AI assistant with custom LLM settings.", + llm=llm + ) + ``` + + + + +## 구성 옵션 + +에이전트를 위해 LLM을 구성할 때 다양한 매개변수를 사용할 수 있습니다: + +| 매개변수 | 유형 | 설명 | +|:----------|:-----:|:-------------| +| **model** | `str` | 사용할 모델의 이름 (예: "gpt-4", "claude-2") | +| **temperature** | `float` | 출력의 무작위성 제어 (0.0 ~ 1.0) | +| **max_tokens** | `int` | 생성할 최대 토큰 수 | +| **top_p** | `float` | 출력 다양성 제어 (0.0 ~ 1.0) | +| **frequency_penalty** | `float` | 지금까지의 텍스트에서 빈도에 따라 새로운 토큰에 패널티 부여 | +| **presence_penalty** | `float` | 지금까지의 텍스트에 이미 존재하는지에 따라 새로운 토큰에 패널티 부여 | +| **stop** | `str`, `List[str]` | 생성을 중단할 시퀀스(들) | +| **base_url** | `str` | API 엔드포인트의 기본 URL | +| **api_key** | `str` | 인증용 API 키 | + +매개변수와 그 설명의 전체 목록은 LLM 클래스 문서를 참고하십시오. + +## OpenAI 호환 LLM에 연결하기 + +OpenAI 호환 LLM에 연결하려면 환경 변수를 사용하거나 LLM 클래스에서 특정 속성을 설정할 수 있습니다: + + + + + ```python Generic + import os + + os.environ["OPENAI_API_KEY"] = "your-api-key" + os.environ["OPENAI_API_BASE"] = "https://api.your-provider.com/v1" + os.environ["OPENAI_MODEL_NAME"] = "your-model-name" + ``` + + ```python Google + import os + + # Gemini의 OpenAI 호환 API 예시입니다. + os.environ["OPENAI_API_KEY"] = "your-gemini-key" # AIza...로 시작해야 합니다. + os.environ["OPENAI_API_BASE"] = "https://generativelanguage.googleapis.com/v1beta/openai/" + os.environ["OPENAI_MODEL_NAME"] = "openai/gemini-2.0-flash" # Gemini 모델을 여기에 추가하세요. openai/ 하위에 위치. + ``` + + + + + ```python Generic + llm = LLM( + model="custom-model-name", + api_key="your-api-key", + base_url="https://api.your-provider.com/v1" + ) + agent = Agent(llm=llm, ...) + ``` + + ```python Google + # Gemini의 OpenAI 호환 API 예시 + llm = LLM( + model="openai/gemini-2.0-flash", + base_url="https://generativelanguage.googleapis.com/v1beta/openai/", + api_key="your-gemini-key", # AIza...로 시작해야 합니다. + ) + agent = Agent(llm=llm, ...) + ``` + + + + +## Ollama와 함께 로컬 모델 사용하기 + +Ollama에서 제공하는 로컬 모델의 경우: + + + + [여기를 클릭하여 Ollama를 다운로드 및 설치하세요](https://ollama.com/download) + + + 예를 들어, `ollama pull llama3.2`를 실행하여 모델을 다운로드합니다. + + + + ```python Code + agent = Agent( + role='Local AI Expert', + goal='Process information using a local model', + backstory="An AI assistant running on local hardware.", + llm=LLM(model="ollama/llama3.2", base_url="http://localhost:11434") + ) + ``` + + + + +## 기본 API URL 변경하기 + +어떤 LLM provider든 `base_url` 파라미터를 설정하여 기본 API URL을 변경할 수 있습니다: + +```python Code +llm = LLM( + model="custom-model-name", + base_url="https://api.your-provider.com/v1", + api_key="your-api-key" +) +agent = Agent(llm=llm, ...) +``` + +이 기능은 OpenAI 호환 API를 사용할 때나 선택한 provider에 대해 다른 endpoint를 지정해야 할 때 특히 유용합니다. + +## 결론 + +LiteLLM을 활용함으로써 CrewAI는 다양한 LLM과의 원활한 통합을 제공합니다. 이러한 유연성 덕분에 성능, 비용 효율성 또는 로컬 배포 등 귀하의 특정 요구 사항에 가장 적합한 모델을 선택할 수 있습니다. 지원되는 모델과 구성 옵션에 대한 최신 정보는 반드시 [LiteLLM 문서](https://docs.litellm.ai/docs/)를 참고하시기 바랍니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/llm-hooks.mdx b/docs/v1.15.13/ko/learn/llm-hooks.mdx new file mode 100644 index 0000000000..92a4e3cead --- /dev/null +++ b/docs/v1.15.13/ko/learn/llm-hooks.mdx @@ -0,0 +1,412 @@ +--- +title: LLM 호출 훅 +description: CrewAI에서 언어 모델 상호작용을 가로채고, 수정하고, 제어하는 LLM 호출 훅 사용 방법 배우기 +mode: "wide" +--- + +LLM 호출 훅(LLM Call Hooks)은 에이전트 실행 중 언어 모델 상호작용에 대한 세밀한 제어를 제공합니다. 이러한 훅을 사용하면 LLM 호출을 가로채고, 프롬프트를 수정하고, 응답을 변환하고, 승인 게이트를 구현하고, 사용자 정의 로깅 또는 모니터링을 추가할 수 있습니다. + +## 개요 + +LLM 훅은 두 가지 중요한 시점에 실행됩니다: +- **LLM 호출 전**: 메시지 수정, 입력 검증 또는 실행 차단 +- **LLM 호출 후**: 응답 변환, 출력 정제 또는 대화 기록 수정 + +## 훅 타입 + +### LLM 호출 전 훅 + +모든 LLM 호출 전에 실행되며, 다음을 수행할 수 있습니다: +- LLM에 전송되는 메시지 검사 및 수정 +- 조건에 따라 LLM 실행 차단 +- 속도 제한 또는 승인 게이트 구현 +- 컨텍스트 또는 시스템 메시지 추가 +- 요청 세부사항 로깅 + +**시그니처:** +```python +def before_hook(context: LLMCallHookContext) -> bool | None: + # 실행을 차단하려면 False 반환 + # 실행을 허용하려면 True 또는 None 반환 + ... +``` + +### LLM 호출 후 훅 + +모든 LLM 호출 후에 실행되며, 다음을 수행할 수 있습니다: +- LLM 응답 수정 또는 정제 +- 메타데이터 또는 서식 추가 +- 응답 세부사항 로깅 +- 대화 기록 업데이트 +- 콘텐츠 필터링 구현 + +**시그니처:** +```python +def after_hook(context: LLMCallHookContext) -> str | None: + # 수정된 응답 문자열 반환 + # 원본 응답을 유지하려면 None 반환 + ... +``` + +## LLM 훅 컨텍스트 + +`LLMCallHookContext` 객체는 실행 상태에 대한 포괄적인 액세스를 제공합니다: + +```python +class LLMCallHookContext: + executor: CrewAgentExecutor # 전체 실행자 참조 + messages: list # 변경 가능한 메시지 목록 + agent: Agent # 현재 에이전트 + task: Task # 현재 작업 + crew: Crew # 크루 인스턴스 + llm: BaseLLM # LLM 인스턴스 + iterations: int # 현재 반복 횟수 + response: str | None # LLM 응답 (후 훅용) +``` + +### 메시지 수정 + +**중요:** 항상 메시지를 제자리에서 수정하세요: + +```python +# ✅ 올바름 - 제자리에서 수정 +def add_context(context: LLMCallHookContext) -> None: + context.messages.append({"role": "system", "content": "간결하게 작성하세요"}) + +# ❌ 잘못됨 - 리스트 참조를 교체 +def wrong_approach(context: LLMCallHookContext) -> None: + context.messages = [{"role": "system", "content": "간결하게 작성하세요"}] +``` + +## 등록 방법 + +### 1. 데코레이터 기반 등록 (권장) + +더 깔끔한 구문을 위해 데코레이터를 사용합니다: + +```python +from crewai.hooks import before_llm_call, after_llm_call + +@before_llm_call +def validate_iteration_count(context): + """반복 횟수를 검증합니다.""" + if context.iterations > 10: + print("⚠️ 최대 반복 횟수 초과") + return False # 실행 차단 + return None + +@after_llm_call +def sanitize_response(context): + """민감한 데이터를 제거합니다.""" + if context.response and "API_KEY" in context.response: + return context.response.replace("API_KEY", "[수정됨]") + return None +``` + +### 2. 크루 범위 훅 + +특정 크루 인스턴스에 대한 훅을 등록합니다: + +```python +from crewai import CrewBase +from crewai.project import crew +from crewai.hooks import before_llm_call_crew, after_llm_call_crew + +@CrewBase +class MyProjCrew: + @before_llm_call_crew + def validate_inputs(self, context): + # 이 크루에만 적용됩니다 + if context.iterations == 0: + print(f"작업 시작: {context.task.description}") + return None + + @after_llm_call_crew + def log_responses(self, context): + # 크루별 응답 로깅 + print(f"응답 길이: {len(context.response)}") + return None + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +## 일반적인 사용 사례 + +### 1. 반복 제한 + +```python +@before_llm_call +def limit_iterations(context: LLMCallHookContext) -> bool | None: + """무한 루프를 방지하기 위해 반복을 제한합니다.""" + max_iterations = 15 + if context.iterations > max_iterations: + print(f"⛔ 차단됨: {max_iterations}회 반복 초과") + return False # 실행 차단 + return None +``` + +### 2. 사람의 승인 게이트 + +```python +@before_llm_call +def require_approval(context: LLMCallHookContext) -> bool | None: + """특정 반복 후 승인을 요구합니다.""" + if context.iterations > 5: + response = context.request_human_input( + prompt=f"반복 {context.iterations}: LLM 호출을 승인하시겠습니까?", + default_message="승인하려면 Enter를 누르고, 차단하려면 'no'를 입력하세요:" + ) + if response.lower() == "no": + print("🚫 사용자에 의해 LLM 호출이 차단되었습니다") + return False + return None +``` + +### 3. 시스템 컨텍스트 추가 + +```python +@before_llm_call +def add_guardrails(context: LLMCallHookContext) -> None: + """모든 LLM 호출에 안전 가이드라인을 추가합니다.""" + context.messages.append({ + "role": "system", + "content": "응답이 사실에 기반하고 가능한 경우 출처를 인용하도록 하세요." + }) + return None +``` + +### 4. 응답 정제 + +```python +@after_llm_call +def sanitize_sensitive_data(context: LLMCallHookContext) -> str | None: + """민감한 데이터 패턴을 제거합니다.""" + if not context.response: + return None + + import re + sanitized = context.response + sanitized = re.sub(r'\b\d{3}-\d{2}-\d{4}\b', '[주민번호-수정됨]', sanitized) + sanitized = re.sub(r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', '[카드번호-수정됨]', sanitized) + + return sanitized +``` + +### 5. 비용 추적 + +```python +import tiktoken + +@before_llm_call +def track_token_usage(context: LLMCallHookContext) -> None: + """입력 토큰을 추적합니다.""" + encoding = tiktoken.get_encoding("cl100k_base") + total_tokens = sum( + len(encoding.encode(msg.get("content", ""))) + for msg in context.messages + ) + print(f"📊 입력 토큰: ~{total_tokens}") + return None + +@after_llm_call +def track_response_tokens(context: LLMCallHookContext) -> None: + """응답 토큰을 추적합니다.""" + if context.response: + encoding = tiktoken.get_encoding("cl100k_base") + tokens = len(encoding.encode(context.response)) + print(f"📊 응답 토큰: ~{tokens}") + return None +``` + +### 6. 디버그 로깅 + +```python +@before_llm_call +def debug_request(context: LLMCallHookContext) -> None: + """LLM 요청을 디버그합니다.""" + print(f""" + 🔍 LLM 호출 디버그: + - 에이전트: {context.agent.role} + - 작업: {context.task.description[:50]}... + - 반복: {context.iterations} + - 메시지 수: {len(context.messages)} + - 마지막 메시지: {context.messages[-1] if context.messages else 'None'} + """) + return None + +@after_llm_call +def debug_response(context: LLMCallHookContext) -> None: + """LLM 응답을 디버그합니다.""" + if context.response: + print(f"✅ 응답 미리보기: {context.response[:100]}...") + return None +``` + +## 훅 관리 + +### 훅 등록 해제 + +```python +from crewai.hooks import ( + unregister_before_llm_call_hook, + unregister_after_llm_call_hook +) + +# 특정 훅 등록 해제 +def my_hook(context): + ... + +register_before_llm_call_hook(my_hook) +# 나중에... +unregister_before_llm_call_hook(my_hook) # 찾으면 True 반환 +``` + +### 훅 지우기 + +```python +from crewai.hooks import ( + clear_before_llm_call_hooks, + clear_after_llm_call_hooks, + clear_all_llm_call_hooks +) + +# 특정 훅 타입 지우기 +count = clear_before_llm_call_hooks() +print(f"{count}개의 전(before) 훅이 지워졌습니다") + +# 모든 LLM 훅 지우기 +before_count, after_count = clear_all_llm_call_hooks() +print(f"{before_count}개의 전(before) 훅과 {after_count}개의 후(after) 훅이 지워졌습니다") +``` + +## 고급 패턴 + +### 조건부 훅 실행 + +```python +@before_llm_call +def conditional_blocking(context: LLMCallHookContext) -> bool | None: + """특정 조건에서만 차단합니다.""" + # 특정 에이전트에 대해서만 차단 + if context.agent.role == "researcher" and context.iterations > 10: + return False + + # 특정 작업에 대해서만 차단 + if "민감한" in context.task.description.lower() and context.iterations > 5: + return False + + return None +``` + +### 컨텍스트 인식 수정 + +```python +@before_llm_call +def adaptive_prompting(context: LLMCallHookContext) -> None: + """반복에 따라 다른 컨텍스트를 추가합니다.""" + if context.iterations == 0: + context.messages.append({ + "role": "system", + "content": "높은 수준의 개요부터 시작하세요." + }) + elif context.iterations > 3: + context.messages.append({ + "role": "system", + "content": "구체적인 세부사항에 집중하고 예제를 제공하세요." + }) + return None +``` + +### 훅 체이닝 + +```python +# 여러 훅은 등록 순서대로 실행됩니다 + +@before_llm_call +def first_hook(context): + print("1. 첫 번째 훅 실행됨") + return None + +@before_llm_call +def second_hook(context): + print("2. 두 번째 훅 실행됨") + return None + +@before_llm_call +def blocking_hook(context): + if context.iterations > 10: + print("3. 차단 훅 - 실행 중지") + return False # 후속 훅은 실행되지 않습니다 + print("3. 차단 훅 - 실행 허용") + return None +``` + +## 모범 사례 + +1. **훅을 집중적으로 유지**: 각 훅은 단일 책임을 가져야 합니다 +2. **무거운 계산 피하기**: 훅은 모든 LLM 호출마다 실행됩니다 +3. **오류를 우아하게 처리**: try-except를 사용하여 훅 실패로 인한 실행 중단 방지 +4. **타입 힌트 사용**: 더 나은 IDE 지원을 위해 `LLMCallHookContext` 활용 +5. **훅 동작 문서화**: 특히 차단 조건에 대해 +6. **훅을 독립적으로 테스트**: 프로덕션에서 사용하기 전에 단위 테스트 +7. **테스트에서 훅 지우기**: 테스트 실행 간 `clear_all_llm_call_hooks()` 사용 +8. **제자리에서 수정**: 항상 `context.messages`를 제자리에서 수정하고 교체하지 마세요 + +## 오류 처리 + +```python +@before_llm_call +def safe_hook(context: LLMCallHookContext) -> bool | None: + try: + # 훅 로직 + if some_condition: + return False + except Exception as e: + print(f"⚠️ 훅 오류: {e}") + # 결정: 오류 발생 시 허용 또는 차단 + return None # 오류에도 불구하고 실행 허용 +``` + +## 타입 안전성 + +```python +from crewai.hooks import LLMCallHookContext, BeforeLLMCallHookType, AfterLLMCallHookType + +# 명시적 타입 주석 +def my_before_hook(context: LLMCallHookContext) -> bool | None: + return None + +def my_after_hook(context: LLMCallHookContext) -> str | None: + return None + +# 타입 안전 등록 +register_before_llm_call_hook(my_before_hook) +register_after_llm_call_hook(my_after_hook) +``` + +## 문제 해결 + +### 훅이 실행되지 않음 +- 크루 실행 전에 훅이 등록되었는지 확인 +- 이전 훅이 `False`를 반환했는지 확인 (후속 훅 차단) +- 훅 시그니처가 예상 타입과 일치하는지 확인 + +### 메시지 수정이 지속되지 않음 +- 제자리 수정 사용: `context.messages.append()` +- 리스트를 교체하지 마세요: `context.messages = []` + +### 응답 수정이 작동하지 않음 +- 후 훅에서 수정된 문자열을 반환 +- `None`을 반환하면 원본 응답이 유지됩니다 + +## 결론 + +LLM 호출 훅은 CrewAI에서 언어 모델 상호작용을 제어하고 모니터링하는 강력한 기능을 제공합니다. 이를 사용하여 안전 가드레일, 승인 게이트, 로깅, 비용 추적 및 응답 정제를 구현하세요. 적절한 오류 처리 및 타입 안전성과 결합하면, 훅을 통해 강력하고 프로덕션 준비가 된 에이전트 시스템을 구축할 수 있습니다. + diff --git a/docs/v1.15.13/ko/learn/llm-selection-guide.mdx b/docs/v1.15.13/ko/learn/llm-selection-guide.mdx new file mode 100644 index 0000000000..a67c3ba008 --- /dev/null +++ b/docs/v1.15.13/ko/learn/llm-selection-guide.mdx @@ -0,0 +1,815 @@ +--- +title: "전략적 LLM 선택 가이드" +description: "CrewAI AI 에이전트를 위한 적합한 LLM 선택 및 효과적인 작업과 에이전트 정의 작성에 대한 전략적 프레임워크" +icon: "brain-circuit" +mode: "wide" +--- + +## CrewAI의 LLM 선택 접근 방식 + +처방적인 모델 추천보다는, **사고 프레임워크**를 제안하여 특정 사용 사례, 제약 조건, 요구 사항에 따라 정보에 입각한 결정을 내릴 수 있도록 돕고자 합니다. LLM 환경은 빠르게 변화하고 있으며, 새로운 모델이 정기적으로 등장하고 기존 모델도 자주 업데이트되고 있습니다. 가장 중요한 것은 어떤 특정 모델이 제공되는지와 상관없이 평가를 위한 체계적인 접근법을 개발하는 것입니다. + + + 이 가이드는 LLM 환경이 빠르게 변화하고 있기 때문에 특정 모델 추천보다는 전략적 + 사고에 초점을 맞추고 있습니다. + + +## 빠른 결정 프레임워크 + + + + 먼저, 작업이 실제로 무엇을 요구하는지 깊이 이해하세요. 필요한 인지 복잡성, + 요구되는 추론의 깊이, 기대되는 출력 형식, 모델이 처리해야 할 맥락의 양을 + 고려합니다. 이러한 기본 분석이 이후의 모든 결정을 안내할 것입니다. + + + 요구 사항을 이해한 후, 이를 모델의 강점에 매핑하세요. 서로 다른 모델 계열은 + 작업 유형에 따라 특화되어 있습니다. 일부는 추론 및 분석에 최적화되어 있고, + 일부는 창의성이나 콘텐츠 생성, 또 다른 일부는 속도와 효율성에 최적화되어 + 있습니다. + + + 예산 제한, 지연 시간 요구사항, 데이터 프라이버시 필요성, 인프라 역량 등 실제 + 운영상의 제약 조건을 반영하세요. 이론적으로 가장 좋은 모델이 실제로는 최선의 + 선택이 아닐 수 있습니다. + + + 신뢰할 수 있고 잘 이해된 모델로 시작하여, 특정 사용 사례에서 실제 성능을 + 바탕으로 최적화하세요. 실제 결과는 이론적 벤치마크와 다를 수 있으므로, + 경험적 테스트가 매우 중요합니다. + + + +## 코어 선택 프레임워크 + +### a. Task-First Thinking + +LLM을 선택할 때 가장 중요한 단계는 실제로 여러분의 작업이 무엇을 요구하는지 이해하는 것입니다. 너무 자주 팀들은 특정 요구 사항을 면밀하게 분석하지 않고, 일반적인 평판이나 벤치마크 점수를 기반으로 모델을 선택합니다. 이런 접근 방식은 단순한 작업에 비싸고 복잡한 모델을 과도하게 적용하거나, 정교한 업무에 필요한 기능이 부족한 모델을 선택하게 만들어 결과적으로 과소 성능 문제를 야기합니다. + + + + - **Simple Tasks**는 대부분의 일상적인 AI 작업을 대표하며, 기본 명령 수행, 간단한 데이터 처리, 단순한 포맷팅 작업 등을 포함합니다. 이러한 작업은 일반적으로 명확한 입력과 출력을 가지고 있으며 모호성이 거의 없습니다. 인지적 부하는 낮고, 모델은 복잡한 추론보다는 명확한 지시에 따라 움직이면 됩니다. + + - **Complex Tasks**는 다단계 추론, 전략적 사고, 모호하거나 불완전한 정보를 처리하는 능력을 필요로 합니다. 여러 데이터 소스를 분석하거나, 포괄적 전략을 개발하거나, 더 작은 구성 요소로 분해해야 하는 문제 해결 작업 등이 이에 해당합니다. 모델은 여러 추론 단계를 거치는 동안 맥락을 유지해야 하며, 명시적으로 언급되지 않은 내용을 추론해야 할 때가 많습니다. + + - **Creative Tasks**는 새롭고, 흥미로우며, 맥락에 적합한 콘텐츠를 생성하는 데 중점을 둔 새로운 인지적 능력을 요구합니다. 여기에는 스토리텔링, 마케팅 카피 작성, 창의적 문제 해결이 포함됩니다. 모델은 뉘앙스, 톤, 대상 청중을 이해하고, 공식적이지 않고 진정성 있고 흥미로운 콘텐츠를 제작해야 합니다. + + + + + - **Structured Data** 작업은 포맷 규칙 준수의 정확성과 일관성을 요구합니다. JSON, XML, 데이터베이스 포맷 등을 다루는 경우, 모델은 구문적으로 올바른 출력을 안정적으로 생성할 수 있어야 하며, 이는 프로그램적으로 처리 가능해야 합니다. 이런 작업에는 엄격한 검증 요구 사항이 있으며 포맷 에러에 대한 허용 오차가 매우 적기 때문에, 창의성보다는 신뢰성이 더 중요합니다. + + - **Creative Content** 출력은 기술적 역량과 창의적 감각의 균형을 필요로 합니다. 모델은 대상 청중, 톤, 브랜드 보이스를 이해하고, 독자의 관심을 끌며 특정 커뮤니케이션 목표를 달성하는 콘텐츠를 제작할 수 있어야 합니다. 이 영역의 품질은 주관적인 경우가 많으며, 다양한 맥락과 목적에 맞게 글쓰기 스타일을 조정할 수 있는 모델이 필요합니다. + + - **Technical Content**는 구조화된 데이터와 창의적 콘텐츠의 중간에 위치하며, 정확성과 명확성을 모두 필요로 합니다. 문서화, 코드 생성, 기술 분석 등은 정밀하면서도 포괄적으로 작성되어야 하며, 대상이 되는 청중에게 효과적으로 전달되어야 합니다. 모델은 복잡한 기술 개념을 이해하고 이를 명확하게 설명할 수 있어야 합니다. + + + + + - **Short Context** 시나리오는 모델이 한정된 정보를 신속하게 처리해야 하는 즉각적이고 집중된 업무를 포함합니다. 이는 대체로 속도와 효율성이 심도 있는 이해보다 더 중요한 거래성 상호작용에서 주로 발생합니다. 모델은 긴 대화 내역이나 대용량 문서를 유지할 필요가 없습니다. + + - **Long Context** 요구 사항은 방대한 문서 작업, 장기간 대화, 복잡한 다중 파트 작업을 처리할 때 발생합니다. 모델은 수천 토큰에 걸쳐 일관성을 유지해야 하며, 앞선 정보를 정확히 참조할 수 있어야 합니다. 이는 문서 분석, 포괄적 연구, 정교한 대화 시스템에 매우 중요한 기능입니다. + + - **Very Long Context** 시나리오는 현재 가능한 한계를 뛰어넘는 경우로, 대규모 문서 처리, 광범위한 연구 종합, 복잡한 다중 세션 상호작용 등이 있습니다. 이러한 활용 사례는 확장된 컨텍스트 처리를 위해 특별히 설계된 모델이 필요하며, 종종 컨텍스트 길이와 처리 속도 간의 절충이 발생합니다. + + + + +### b. 모델 역량 매핑 + +모델 역량을 이해하기 위해서는 마케팅 주장이나 벤치마크 점수 너머를 바라보고, 다양한 모델 구조와 학습 접근법의 근본적인 강점과 한계를 파악해야 합니다. + + + + Reasoning 모델은 복잡하고 다단계의 사고가 필요한 작업을 위해 특별히 설계된 특수 카테고리를 나타냅니다. 이러한 모델은 문제를 신중하게 분석하거나 전략적으로 계획을 세우거나 체계적으로 문제를 분해해야 하는 경우에 뛰어납니다. 일반적으로 chain-of-thought reasoning 혹은 tree-of-thought processing과 같은 기법을 사용하여 복잡한 문제를 단계별로 해결합니다. + + Reasoning 모델의 강점은 확장된 reasoning 체인에서 논리적 일관성을 유지하고, 복잡한 문제를 관리 가능한 구성 요소로 나눌 수 있다는 점에 있습니다. 전략적 계획, 복잡한 분석, 그리고 응답 속도보다 reasoning의 질이 더 중요한 상황에서 특히 가치가 있습니다. + + 하지만 reasoning 모델은 속도와 비용 면에서 트레이드오프가 따르는 경우가 많습니다. 또한 그들의 고도화된 reasoning 역량이 필요 없는 창의적인 작업이나 간단한 작업에는 덜 적합할 수 있습니다. 체계적이고 단계적인 분석이 요구되는 진정한 복잡성이 관련된 작업에서 이러한 모델을 고려하십시오. + + + + + General purpose 모델은 LLM 선택에서 가장 균형 잡힌 접근 방식을 제공하며, 특정 영역에 극단적으로 특화되지 않으면서도 다양한 작업에 대해 견고한 성능을 제공합니다. 이러한 모델은 다양한 데이터셋으로 학습되었으며, 특정 도메인에서의 최고 성능보다는 다재다능함에 최적화되어 있습니다. + + General purpose 모델의 주요 장점은 다양한 유형의 작업에서 예측 가능한 신뢰성과 일관성입니다. 조사, 분석, 콘텐츠 제작, 데이터 처리 등 대부분의 표준 비즈니스 작업을 충분히 처리할 수 있습니다. 이로 인해 다양한 워크플로우 전반에서 일관된 성능이 필요한 팀에 매우 적합한 선택이 됩니다. + + General purpose 모델은 특정 도메인에서 특화된 대안들이 보여주는 최고 성능에는 미치지 않을 수 있지만, 운영의 단순성과 모델 관리의 복잡성 감소라는 이점이 있습니다. 신규 프로젝트의 시작점으로 가장 좋은 선택인 경우가 많으며, 팀이 구체적인 필요를 이해하고 나서 특화 모델로 최적화할 수 있습니다. + + + + + Fast and efficient 모델은 고도화된 reasoning 역량보다 속도, 비용 효율, 리소스 효율성을 우선순위에 둡니다. 이러한 모델은 빠른 응답성과 낮은 운영비용이 중요하고, 미묘한 이해나 복잡한 reasoning이 덜 요구되는 고처리량 시나리오에 최적화되어 있습니다. + + 이러한 모델은 일상적인 운영, 간단한 데이터 처리, 함수 호출, 대용량 작업 등 인지적 요구가 비교적 단순한 시나리오에서 뛰어납니다. 많은 요청을 신속하게 처리해야 하거나 예산 제약 내에서 운영되어야 하는 애플리케이션에 특히 유용합니다. + + 효율적인 모델에서 가장 중요한 고려사항은 그들의 역량이 귀하의 작업 요구와 일치하는지 확인하는 것입니다. 많은 일상적 작업은 효과적으로 처리할 수 있지만, Nuanced한 이해, 복잡한 reasoning, 혹은 고도화된 콘텐츠 생성이 필요한 작업에는 어려움을 겪을 수 있습니다. 정교함보다 속도와 비용이 더 중요한 명확하고 일상적인 작업에 가장 적합합니다. + + + + + Creative 모델은 콘텐츠 생성, 글쓰기 품질, 창의적 사고가 요구되는 작업에 특별히 최적화되어 있습니다. 이러한 모델은 뉘앙스, 톤, 스타일을 이해하면서도 자연스럽고 진정성 있게 느껴지는 매력적이고 맥락에 맞는 콘텐츠를 생성하는 데 뛰어납니다. + + Creative 모델의 강점은 다양한 대상에 맞춰 글쓰기 스타일을 조정하고, 일관된 목소리와 톤을 유지하며, 독자를 효과적으로 사로잡는 콘텐츠를 생성할 수 있다는 점입니다. 스토리텔링, 마케팅 카피, 브랜드 커뮤니케이션 등 창의성과 몰입이 주요 목적이 되는 콘텐츠 작업에서 더 우수한 성과를 보입니다. + + Creative 모델을 선택할 때는 단순한 텍스트 생성 능력뿐 아니라, 대상, 맥락, 목적에 대한 이해력도 함께 고려해야 합니다. 최상의 creative 모델은 특정 브랜드 목소리에 맞게 출력 내용을 조정하고, 다양한 대상 그룹을 타깃팅하며, 긴 콘텐츠에서도 일관성을 유지할 수 있습니다. + + + + + Open source 모델은 비용 통제, 맞춤화 가능성, 데이터 프라이버시, 배포 유연성 측면에서 독특한 이점을 제공합니다. 이러한 모델은 로컬이나 사설 인프라에서 운용이 가능하여 데이터 처리 및 모델 동작에 대해 완전한 통제권을 제공합니다. + + Open source 모델의 주요 이점으로는 토큰당 비용의 제거, 특정 용도에 맞춘 파인튜닝 가능성, 완전한 데이터 프라이버시, 외부 API 제공자에 대한 의존성 해소가 있습니다. 특히 엄격한 데이터 프라이버시 요구사항, 예산 제약, 특정 맞춤화 필요가 있는 조직에 매우 유용합니다. + + 그러나 open source 모델은 효과적으로 배포 및 유지관리하기 위해 더 많은 기술 전문성이 필요합니다. 팀에서는 인프라 비용, 모델 관리 복잡성, 지속적인 모델 업데이트 및 최적화를 위한 지속적인 노력을 고려해야 합니다. 기술적 오버헤드를 감안하면 전체 소유 비용이 클라우드 기반 대안보다 높을 수 있습니다. + + + + +## 전략적 구성 패턴 + +### a. 멀티-모델 접근 방식 + + + 동일 crew 내에서 다양한 목적에 맞는 서로 다른 모델을 사용해 성능과 비용을 모두 + 최적화할 수 있습니다. + + +가장 정교하게 구현된 CrewAI의 경우, 여러 개의 모델을 전략적으로 활용하여 각 agent의 역할과 요구 사항에 맞는 모델을 지정합니다. 이 접근 방식은 각 작업 유형에 가장 적합한 모델을 사용함으로써 성능과 비용을 모두 최적화할 수 있게 해줍니다. + +planning agent는 복잡한 전략적 사고와 다단계 분석을 처리할 수 있는 reasoning 모델을 활용할 때 이점을 얻습니다. 이 agent들은 운영의 “두뇌” 역할을 하며, 전략 수립과 다른 agent들의 작업을 조정합니다. 반면 content agent는 글의 품질과 독자 참여에 뛰어난 creative 모델을 통해 최고의 성능을 발휘합니다. 일상적인 작업과 운영을 담당하는 processing agent는 속도와 비용 효율을 우선시하는 효율적인 모델을 사용할 수 있습니다. + +**예시: Research and Analysis Crew** + +```python +from crewai import Agent, Task, Crew, LLM + +# High-capability reasoning model for strategic planning +manager_llm = LLM(model="gemini-2.5-flash-preview-05-20", temperature=0.1) + +# Creative model for content generation +content_llm = LLM(model="claude-3-5-sonnet-20241022", temperature=0.7) + +# Efficient model for data processing +processing_llm = LLM(model="gpt-4o-mini", temperature=0) + +research_manager = Agent( + role="Research Strategy Manager", + goal="Develop comprehensive research strategies and coordinate team efforts", + backstory="Expert research strategist with deep analytical capabilities", + llm=manager_llm, # High-capability model for complex reasoning + verbose=True +) + +content_writer = Agent( + role="Research Content Writer", + goal="Transform research findings into compelling, well-structured reports", + backstory="Skilled writer who excels at making complex topics accessible", + llm=content_llm, # Creative model for engaging content + verbose=True +) + +data_processor = Agent( + role="Data Analysis Specialist", + goal="Extract and organize key data points from research sources", + backstory="Detail-oriented analyst focused on accuracy and efficiency", + llm=processing_llm, # Fast, cost-effective model for routine tasks + verbose=True +) + +crew = Crew( + agents=[research_manager, content_writer, data_processor], + tasks=[...], # Your specific tasks + manager_llm=manager_llm, # Manager uses the reasoning model + verbose=True +) +``` + +성공적인 멀티-모델 구현의 핵심은 서로 다른 agent들이 어떻게 상호작용하는지를 이해하고, 모델의 역량이 agent의 책임에 부합하는지 확인하는 것입니다. 이를 위해 신중한 기획이 필요하지만, 그 결과로 산출물의 품질과 운영 효율성 모두에서 큰 개선을 이끌어낼 수 있습니다. + +### b. 구성요소별 선택 + + + + Manager LLM은 계층적 CrewAI 프로세스에서 중요한 역할을 하며, 여러 에이전트와 작업을 조정하는 중심점으로 작동합니다. 이 모델은 위임, 작업 우선순위 지정, 여러 동시 작업 간의 컨텍스트 유지에 뛰어나야 합니다. + + 효과적인 Manager LLM은 올바른 위임 결정을 내리기 위한 강력한 추론 능력, 예측 가능한 조정을 보장하는 일관된 성능, 여러 에이전트의 상태를 동시에 추적하기 위한 탁월한 컨텍스트 관리가 필요합니다. 이 모델은 다양한 에이전트의 역량과 한계를 이해하고, 효율성과 품질을 최적화하기 위해 작업 할당을 최적화해야 합니다. + + Manager LLM은 모든 작업에 관여하기 때문에 비용 고려가 특히 중요합니다. 모델은 효과적인 조정을 위한 충분한 역량을 제공하면서도, 잦은 사용에도 비용 효율적이어야 합니다. 이는 종종 가장 정교한 모델의 높은 가격 없이도 충분한 추론 능력을 제공하는 모델을 찾는 것을 의미합니다. + + + + + Function calling LLM은 모든 에이전트 간 도구 사용을 처리하므로, 외부 도구와 API에 크게 의존하는 crew에서 매우 중요합니다. 이 모델은 도구의 역량을 이해하고, 파라미터를 정확하게 추출하며, 도구 응답을 효과적으로 처리하는 데 특화되어야 합니다. + + Function calling LLM에서 가장 중요한 특성은 창의성이나 정교한 추론력보다는 정확성과 신뢰성입니다. 모델은 자연어 요청에서 올바른 파라미터를 일관되게 추출하고, 도구 응답을 적절히 처리해야 합니다. 도구 사용은 여러 번의 왕복 작업이 수반될 수 있으므로 속도도 중요합니다. + + 많은 팀들은, 창의적이거나 추론에 특화된 모델보다는, 특화된 function calling 모델이나 도구 지원이 강력한 범용 모델이 이 역할에 더 적합하다는 것을 발견합니다. 핵심은 모델이 자연어 지침과 구조화된 도구 호출 간의 간극을 신뢰성 있게 연결할 수 있도록 하는 것입니다. + + + + + 개별 에이전트는 특정 요구가 일반적인 crew 요구와 크게 다를 때, crew 단위 LLM 설정을 재정의할 수 있습니다. 이 기능을 통해 대부분의 에이전트에는 운영 단순성을 유지하면서, 미세한 최적화가 가능합니다. + + 에이전트별 재정의를 고려해야 하는 경우는 에이전트의 역할이 다른 crew 구성원과 본질적으로 다른 역량을 요구할 때입니다. 예를 들어, 창의적 글쓰기에 특화된 에이전트는 콘텐츠 생성에 최적화된 모델이 도움이 될 수 있고, 데이터 분석 에이전트는 추론에 중점을 둔 모델로 더 나은 성과를 거둘 수 있습니다. + + 에이전트별 재정의를 적용할 때의 과제는 최적화와 운영 복잡도 간의 균형을 유지하는 것입니다. 모델이 하나 추가될 때마다 배포, 모니터링, 비용 관리의 복잡성이 늘어납니다. 따라서 팀은 성능 향상 효과가 추가 복잡성을 정당화할 수 있는 에이전트에만 재정의를 집중해야 합니다. + + + + +## 작업 정의 프레임워크 + +### a. 복잡성보다 명확성에 집중하기 + +CrewAI 출력의 품질을 결정하는 데 있어 모델 선택보다 효과적인 작업 정의가 더 중요한 경우가 많습니다. 잘 정의된 작업은 명확한 방향과 맥락을 제공하여 심지어 보통 수준의 모델도 좋은 성능을 낼 수 있게 해주지만, 잘못 정의된 작업은 고도화된 모델조차 만족스럽지 않은 결과를 만들 수 있습니다. + + + + 최고의 작업 설명은 적절한 세부 정보 제공과 명확성 유지를 균형 있게 조화시킵니다. 작업의 구체적인 목표를 성공이 어떤 모습인지에 대한 모호함 없이 명확하게 정의해야 하며, 접근 방식이나 방법론을 충분히 설명하여 에이전트가 어떻게 진행해야 하는지 이해할 수 있도록 해야 합니다. + + 효과적인 작업 설명은 에이전트가 더 넓은 목적과 그들이 반드시 지켜야 할 제한사항을 이해할 수 있도록 관련 맥락 및 제약 조건을 포함합니다. 복잡한 작업을 체계적으로 실행할 수 있는 집중된 단계로 분할하여, 여러 측면이 뒤섞이고 접근하기 어려운 압도적인 목표로 제시하지 않습니다. + + 일반적인 실수로는 목표가 너무 모호하다거나, 필요한 맥락을 제공하지 않는다거나, 성공 기준이 불분명하다거나, 관련 없는 여러 작업을 하나의 설명으로 결합하는 경우가 있습니다. 목표는 단일의 명확한 목적에 집중하며, 에이전트가 성공할 수 있을 정도로 충분한 정보를 제공하는 것입니다. + + + + + 예상 산출물 가이드라인은 작업 정의와 에이전트 간의 계약 역할을 하며, 산출물이 어떤 모습이어야 하며 어떻게 평가될 것인지 명확하게 지정합니다. 이러한 가이드라인은 필요한 형식과 구조뿐만 아니라 산출물이 완전하다고 간주되기 위해 반드시 포함되어야 하는 핵심 요소도 설명해야 합니다. + + 최고의 산출물 가이드라인은 품질 지표에 대한 구체적인 예시를 제공하고, 완료 기준을 에이전트와 인간 평가자 모두가 작업의 성공적 완료 여부를 평가할 수 있을 만큼 명확하게 정의합니다. 이는 모호함을 줄이고 여러 작업 실행 간 일관된 결과를 보장하는 데 도움이 됩니다. + + 어떤 작업에나 적용할 수 있을 정도로 일반적인 산출물 설명, 에이전트가 구조를 추측해야 하는 형식 명세 누락, 평가가 어려운 불분명한 품질 기준, 에이전트가 기대치를 이해하도록 도와주는 예시 또는 템플릿 미제공 등은 피해야 합니다. + + + + +### b. 작업 순서 지정 전략 + + + + 작업이 이전 산출물에 기반을 두거나, 정보가 한 작업에서 다른 작업으로 흐르거나, 품질이 선행 작업의 완료에 의존할 때 순차적 작업 의존성이 필수적입니다. 이 접근 방식은 각 작업이 성공적으로 수행되는 데 필요한 정보와 맥락에 접근할 수 있도록 보장합니다. + + 순차적 의존성을 효과적으로 구현하기 위해서는 context 파라미터를 사용하여 관련 작업을 연쇄시키고, 작업의 진행을 통해 점진적으로 복잡성을 구축하며, 각 작업이 다음 작업에 의미 있는 입력값이 될 수 있는 산출물을 생성하도록 해야 합니다. 목표는 의존된 작업 간의 논리적 흐름을 유지하면서 불필요한 병목을 피하는 것입니다. + + 순차적 의존성은 한 작업에서 다른 작업으로 명확한 논리적 진행이 있고, 한 작업의 산출물이 다음 작업의 품질이나 실행 가능성을 실제로 향상시킬 때 가장 효과적입니다. 그러나 적절히 관리되지 않을 경우 병목 현상이 발생할 수 있으니, 반드시 진정으로 필요한 의존성과 단순히 편의상 설정된 의존성을 구분해야 합니다. + + + + + 병렬 실행은 작업 간에 상호 독립적이거나, 시간 효율성이 중요하거나, 서로 다른 전문 분야가 협업 없이 각자의 역량을 발휘할 수 있을 때 가치가 있습니다. 이 방식은 전체 실행 시간을 크게 줄일 수 있으며, 각 전문 에이전트가 자신의 강점을 동시에 발휘할 수 있습니다. + + 성공적인 병렬 실행을 위해서는 실제로 독립적으로 수행이 가능한 작업을 식별하고, 관련되지만 분리된 작업 스트림을 효과적으로 그룹화하며, 병렬로 진행된 작업을 최종 결과물로 통합해야 할 때 결과 통합을 계획해야 합니다. 핵심은 병렬 작업이 전체 품질을 저하하는 충돌이나 중복을 만들지 않도록 하는 것입니다. + + 여러 개의 독립적인 연구 스트림이나 서로 의존하지 않는 다양한 분석, 동시에 개발이 가능한 콘텐츠 생성 작업이 있을 때 병렬 실행을 고려하십시오. 다만, 자원 할당에 주의하고, 병렬 실행이 모델의 가용 용량이나 예산을 초과하지 않도록 해야 합니다. + + + + +## LLM 성능을 위한 에이전트 구성 최적화 + +### a. 역할 기반 LLM 선택 + + + 일반적인 에이전트 역할은 올바른 LLM을 선택할 수 없게 만듭니다. 구체적인 역할은 + 목표에 맞춘 모델 최적화를 가능하게 합니다. + + +에이전트 역할의 구체성은 최적의 성능을 위해 어떤 LLM의 능력이 가장 중요한지를 직접적으로 결정합니다. 이는 에이전트의 책임에 정확히 맞는 모델 강점을 연결할 수 있는 전략적 기회를 만듭니다. + +**일반 역할 vs. 구체적 역할이 LLM 선택에 미치는 영향:** + +역할을 정의할 때 에이전트가 다룰 작업에 가장 가치 있는 특정 도메인 지식, 작업 방식, 의사결정 프레임워크를 고려하세요. 역할 정의가 더 구체적이고 상황에 맞을수록 모델이 그 역할을 효과적으로 구현할 수 있습니다. + +```python +# ✅ 특정 역할 - 명확한 LLM 요구 +specific_agent = Agent( + role="SaaS Revenue Operations Analyst", # 명확한 도메인 전문성 필요 + goal="Analyze recurring revenue metrics and identify growth opportunities", + backstory="Specialist in SaaS business models with deep understanding of ARR, churn, and expansion revenue", + llm=LLM(model="gpt-4o") # 복잡한 분석에 적합한 reasoning 모델 +) +``` + +**역할-모델 매핑 전략:** + +- **"Research Analyst"** → 복잡한 분석을 위한 reasoning 모델 (GPT-4o, Claude Sonnet) +- **"Content Editor"** → 작문 품질을 위한 creative 모델 (Claude, GPT-4o) +- **"Data Processor"** → 구조화된 태스크를 위한 효율적인 모델 (GPT-4o-mini, Gemini Flash) +- **"API Coordinator"** → 도구 사용을 위한 function-calling 최적화 모델 (GPT-4o, Claude) + +### b. 모델 컨텍스트 증폭기로서의 백스토리 + + + 전략적으로 구성된 백스토리는 도메인 특화 컨텍스트를 제공하여 일반적인 + 프롬프트로는 달성할 수 없는 수준으로 선택한 LLM의 효율성을 획기적으로 + 높여줍니다. + + +잘 설계된 백스토리는 LLM을 단순한 범용 모델에서 전문적인 전문가로 탈바꿈시켜 줍니다. 이는 비용 최적화 관점에서 특히 중요합니다. 효율적인 모델이라도 컨텍스트가 잘 구축되면, 적절한 컨텍스트 없이 고가의 모델보다 더 뛰어난 성능을 발휘할 수 있습니다. + +**컨텍스트 기반 퍼포먼스 예시:** + +```python +# Context amplifies model effectiveness +domain_expert = Agent( + role="B2B SaaS Marketing Strategist", + goal="Develop comprehensive go-to-market strategies for enterprise software", + backstory=""" + You have 10+ years of experience scaling B2B SaaS companies from Series A to IPO. + You understand the nuances of enterprise sales cycles, the importance of product-market + fit in different verticals, and how to balance growth metrics with unit economics. + You've worked with companies like Salesforce, HubSpot, and emerging unicorns, giving + you perspective on both established and disruptive go-to-market strategies. + """, + llm=LLM(model="claude-3-5-sonnet", temperature=0.3) # Balanced creativity with domain knowledge +) + +# This context enables Claude to perform like a domain expert +# Without it, even it would produce generic marketing advice +``` + +**LLM 성능을 높여주는 백스토리 요소:** + +- **도메인 경험**: "10년 이상의 엔터프라이즈 SaaS 영업 경력" +- **특정 전문성**: "시리즈 B+ 라운드의 기술 실사 전문" +- **업무 스타일**: "명확한 문서화와 데이터 기반 의사결정을 선호" +- **품질 기준**: "출처 인용과 분석 근거 제시를 중시" + +### c. 총체적 Agent-LLM 최적화 + +가장 효과적인 agent 구성은 역할 특이성, 백스토리 깊이, 그리고 LLM 선택 간의 시너지를 창출합니다. 각 요소는 서로를 강화하여 모델 성능을 극대화합니다. + +**최적화 프레임워크:** + +```python +# Example: Technical Documentation Agent +tech_writer = Agent( + role="API Documentation Specialist", # Specific role for clear LLM requirements + goal="Create comprehensive, developer-friendly API documentation", + backstory=""" + You're a technical writer with 8+ years documenting REST APIs, GraphQL endpoints, + and SDK integration guides. You've worked with developer tools companies and + understand what developers need: clear examples, comprehensive error handling, + and practical use cases. You prioritize accuracy and usability over marketing fluff. + """, + llm=LLM( + model="claude-3-5-sonnet", # Excellent for technical writing + temperature=0.1 # Low temperature for accuracy + ), + tools=[code_analyzer_tool, api_scanner_tool], + verbose=True +) +``` + +**정렬 체크리스트:** + +- ✅ **역할 특이성**: 명확한 도메인과 책임 +- ✅ **LLM 적합도**: 모델의 강점이 역할 요구사항과 일치 +- ✅ **백스토리 깊이**: LLM이 활용할 수 있는 도메인 맥락 제공 +- ✅ **도구 통합**: 도구가 agent의 특수 기능을 지원 +- ✅ **파라미터 튜닝**: 온도 및 설정이 역할에 최적화 + +핵심은 모든 구성 선택이 LLM 선택 전략을 강화하여 성능을 극대화하면서 비용을 최적화하는 agent를 만드는 것입니다. + +## 실무 구현 체크리스트 + +전략적 프레임워크를 반복하는 대신, CrewAI에서 LLM 선택 결정을 실행하는 데 사용할 수 있는 전술적 체크리스트를 제공합니다: + + + + **검토할 사항:** + - 모든 agent가 기본적으로 동일한 LLM을 사용하고 있습니까? + - 어떤 agent가 가장 복잡한 reasoning 작업을 처리합니까? + - 어떤 agent가 주로 데이터 처리 또는 포매팅을 담당합니까? + - 도구에 크게 의존하는 agent가 있습니까? + + **Action**: 현재 agent 역할을 문서화하고 최적화 기회를 식별하세요. + + + + + **기본값 설정:** + ```python + # crew에 신뢰할 수 있는 기본값으로 시작합니다 + default_crew_llm = LLM(model="gpt-4o-mini") # 비용 효율적인 기준점 + + crew = Crew( + agents=[...], + tasks=[...], + memory=True + ) + ``` + + **Action**: 개별 agent 최적화 전에 crew의 기본 LLM을 설정하세요. + + + + + **핵심 agent 식별 및 업그레이드:** + ```python + # Manager 또는 coordination agent + manager_agent = Agent( + role="Project Manager", + llm=LLM(model="gemini-2.5-flash-preview-05-20"), # 조율을 위한 프리미엄 + # ... 나머지 설정 + ) + + # Creative 또는 고객 대응 agent + content_agent = Agent( + role="Content Creator", + llm=LLM(model="claude-3-5-sonnet"), # 글쓰기에 최적 + # ... 나머지 설정 + ) + ``` + + **Action**: 복잡도의 80%를 처리하는 agent 20%를 업그레이드하세요. + + + + + **agent를 프로덕션에 배포한 후:** + - [CrewAI AMP platform](https://app.crewai.com)을 활용하여 모델 선택을 A/B 테스트하세요 + - 실제 입력으로 여러 번 반복 테스트하여 일관성과 성능을 측정하세요 + - 최적화된 셋업 전반의 비용과 성능을 비교하세요 + - 팀과 결과를 공유하여 협업 의사결정을 지원하세요 + + **Action**: 테스트 플랫폼을 활용해 추측이 아닌 데이터 기반 검증을 실행하세요. + + + + +### 다양한 모델 유형을 사용할 시기 + + + + reasoning 모델은 진정한 다단계 논리적 사고, 전략적 계획 수립, 또는 체계적인 분석이 필요한 고수준의 의사결정이 요구되는 작업에서 필수적입니다. 이러한 모델은 문제를 구성 요소로 분해하고 체계적으로 분석해야 할 때, 단순한 패턴 매칭이나 지시 사항 이행만으로는 해결할 수 없는 경우에 뛰어난 성능을 발휘합니다. + + 예를 들어, 비즈니스 전략 개발, 여러 출처에서 인사이트를 도출해야 하는 복잡한 데이터 분석, 각 단계가 이전 분석을 기반으로 해야 하는 다단계 문제 해결, 다양한 변수 및 이들의 상호작용을 고려해야 하는 전략적 계획 수립 업무에 reasoning 모델을 고려해 보세요. + + 그러나 reasoning 모델은 일반적으로 더 높은 비용과 느린 응답 시간을 수반하므로, 복잡한 사고가 필요한 작업에서 실질적인 가치를 제공할 때에만 사용하는 것이 좋으며, 복잡한 reasoning이 필요하지 않은 단순한 작업에는 권장되지 않습니다. + + + + + creative 모델은 콘텐츠 생성이 주요 결과물이고 콘텐츠의 품질, 스타일, 참여도가 성공에 직접적으로 영향을 미칠 때 유용합니다. 이 모델들은 글의 질과 스타일이 매우 중요하거나, 창의적인 아이디어 창출 또는 브레인스토밍이 필요하거나, 브랜드의 목소리와 톤이 중요한 경우에 특히 뛰어납니다. + + creative 모델은 블로그 포스트 작성 및 기사 생성, 독자를 끌어들이고 설득해야 하는 마케팅 카피, 창의적인 스토리텔링 및 내러티브 개발, 목소리와 톤이 중요한 브랜드 커뮤니케이션 등에 적합합니다. 이 모델은 일반 목적 모델보다 뉘앙스와 맥락을 더 잘 이해할 수 있습니다. + + creative 모델은 정밀성과 사실적 정확성이 스타일이나 참여도보다 더 중요한 기술적 또는 분석적 작업에는 덜 적합할 수 있습니다. 결과물의 창의적·의사소통적 측면이 성공의 주요 요인일 때 사용하는 것이 가장 좋습니다. + + + + + efficient 모델은 빠른 속도와 비용 최적화가 우선순위인 고빈도, 반복 작업에 이상적입니다. 이러한 모델은 작업의 매개변수가 명확하고 잘 정의되어 있으며, 복잡한 reasoning이나 창의적인 능력이 필요하지 않을 때 가장 잘 작동합니다. + + efficient 모델은 데이터 처리 및 변환 작업, 단순한 서식 지정 및 정리 작업, 정밀성이 중요하고 복잡함보다는 정확성이 필요한 함수 호출 및 도구 사용, 1회 작업당 비용이 중대한 고볼륨 작업에 적합합니다. + + efficient 모델에서는 해당 모델의 역량이 작업 요구 사항과 일치하는지 확인하는 것이 핵심입니다. 다양한 반복 작업을 효과적으로 처리할 수 있지만, 뉘앙스 이해, 복잡한 reasoning, 고도화된 콘텐츠 생성이 필요한 작업에서는 한계가 있을 수 있습니다. + + + + + open source 모델은 예산 제약이 크거나, 데이터 프라이버시 요구 사항이 있거나, 맞춤화가 중요하거나, 운영·컴플라이언스 목적상 로컬 배포가 필요한 경우에 매력적인 선택이 됩니다. + + 예를 들어, 데이터 프라이버시가 최우선인 사내 도구, 외부 API를 사용할 수 없는 프라이버시 민감형 애플리케이션, 토큰 단위 가격이 부담스러운 비용 최적화 배포, 모델 수정 또는 파인튜닝이 필요한 상황에서 open source 모델을 고려해 보세요. + + 단, open source 모델은 효과적으로 배포하고 유지하기 위해 더 많은 기술 전문성이 요구됩니다. 인프라, 기술적 오버헤드, 지속적인 유지보수를 포함한 전체 소유 비용을 종합적으로 평가해야 합니다. + + + + +## CrewAI 모델 선택에서 흔히 발생하는 실수 + + + + **문제점**: 각 agent의 역할과 책임과 상관없이 모든 agent에 동일한 LLM을 사용하는 것. 대부분 기본적으로 선택되는 접근 방식이지만, 최적의 결과가 나오지 않는 경우가 많음. + + **실제 예시**: 전략 기획 매니저와 데이터 추출 agent 모두에게 GPT-4o를 사용하는 경우. 매니저는 높은 추론 성능이 필요해 프리미엄 모델이 적합하나, 데이터 추출 업무는 저렴한 GPT-4o-mini만으로도 충분한 성능을 낼 수 있음. + + **CrewAI 솔루션**: agent별 LLM 설정을 활용해, agent의 역할에 맞는 모델 역량을 매칭: + ```python + # 전략 agent는 프리미엄 모델 사용 + manager = Agent(role="Strategy Manager", llm=LLM(model="gpt-4o")) + + # 처리 agent는 효율적인 모델 사용 + processor = Agent(role="Data Processor", llm=LLM(model="gpt-4o-mini")) + ``` + + + + + **문제점**: CrewAI의 LLM 계층 구조(crew LLM, manager LLM, agent LLM)를 이해하지 못해 설정이 충돌하거나 적절히 조정되지 않음. + + **실제 예시**: crew에는 Claude를, agent에는 GPT 모델을 설정해 일관성 없는 동작과 불필요한 모델 전환 오버헤드가 발생하는 경우. + + **CrewAI 솔루션**: LLM 계층 구조를 전략적으로 설계: + ```python + crew = Crew( + agents=[agent1, agent2], + tasks=[task1, task2], + manager_llm=LLM(model="gpt-4o"), # crew 조정용 + process=Process.hierarchical # manager_llm 사용 시 + ) + + # agent는 특별히 지정하지 않으면 crew LLM을 상속받음 + agent1 = Agent(llm=LLM(model="claude-3-5-sonnet")) # 특정 요구에 따라 오버라이드 + ``` + + + + + **문제점**: 기능 위주(함수 호출, 툴 활용 등) CrewAI workflow에서 필요한 함수 호출 성능을 무시한 채, 일반적인 모델 특성(예: 창의성)만을 보고 모델을 선택하는 실수. + + **실제 예시**: 주로 API 호출, 검색 툴, 구조화 데이터 처리가 필요한 agent에 창의성 위주의 모델을 선택해, 도구 파라미터 추출과 신뢰성 있는 함수 호출에 실패하는 경우. + + **CrewAI 솔루션**: 도구 중심 agent는 함수 호출 성능 위주로 모델을 선택: + ```python + # 다양한 도구를 사용하는 agent의 경우 + tool_agent = Agent( + role="API Integration Specialist", + tools=[search_tool, api_tool, data_tool], + llm=LLM(model="gpt-4o"), # 함수 호출에 우수 + # OR + llm=LLM(model="claude-3-5-sonnet") # 도구 사용에 강점 + ) + ``` + + + + + **문제점**: 실제 CrewAI workflow 및 업무 테스트 없이 이론상 성능만으로 복잡하게 모델을 선정하고 구성하는 실수. + + **실제 예시**: 업무 유형별로 복잡한 모델 전환 로직을 구현하지만, 실제 성능 향상이 운영 복잡성을 정당화하지 못하는 경우. + + **CrewAI 솔루션**: 단순한 구조로 시작해서, 실제 성능 데이터를 바탕으로 점진적으로 최적화: + ```python + # 이렇게 시작 + crew = Crew(agents=[...], tasks=[...], llm=LLM(model="gpt-4o-mini")) + + # 성능을 테스트하고, 필요에 따라 특정 agent만 최적화 + # Enterprise 플랫폼 테스트를 통해 개선 사항 검증 + ``` + + + + + **문제점**: 모델의 컨텍스트 윈도(window)와 CrewAI의 메모리, agent 간 컨텍스트 공유 방식을 고려하지 않는 실수. + + **실제 예시**: 여러 차례 반복되는 업무나 agent 간 활발한 소통이 필요한 crew에 대화 내역을 오래 유지해야 하는데, 짧은 컨텍스트 모델을 사용한 경우. + + **CrewAI 솔루션**: crew의 소통 패턴에 맞춰 컨텍스트 처리 능력을 갖춘 모델을 선택. + + + + +## 테스트 및 반복 전략 + + + + 신뢰할 수 있고, 잘 알려져 있으며, 널리 지원되는 범용 모델로 시작하세요. + 이것은 최적화된 특수한 필요에 집중하기 전에 귀하의 특정 요구사항과 성능 + 기대치를 이해할 수 있는 안정적인 기초를 제공합니다. + + + 일반적인 벤치마크에만 의존하지 말고, 귀하의 특정 사용 사례와 비즈니스 요구에 + 부합하는 지표를 개발하세요. 이론적 성능 지표가 아니라 성공에 직접적으로 + 영향을 미치는 결과 측정에 집중하세요. + + + 이론적 고려사항이나 일반적인 권장사항이 아니라, 귀하의 특정 상황에서 관찰된 + 성능에 따라 모델을 변경하세요. 실제 성능은 벤치마크 결과나 일반적인 평판과는 + 크게 다를 수 있습니다. + + + 모델 비용, 개발 시간, 유지 보수 오버헤드, 운영 복잡성 등 소유에 드는 전체 + 비용을 평가하세요. 토큰당 가장 저렴한 모델이 모든 요소를 고려했을 때 반드시 + 가장 비용 효율적이지는 않을 수 있습니다. + + + + + 먼저 귀하의 요구사항을 이해하는 데 집중한 후, 그 요구와 가장 잘 맞는 모델을 + 선택하세요. 최상의 LLM 선택은 운영상의 제약 조건 내에서 꾸준히 원하는 결과를 + 제공하는 것입니다. + + +### 엔터프라이즈급 모델 검증 + +LLM 선택을 최적화하고자 하는 팀을 위해 **CrewAI AMP 플랫폼**은 기본적인 CLI 테스트를 훨씬 능가하는 정교한 테스트 기능을 제공합니다. 이 플랫폼은 데이터 기반의 LLM 전략 의사결정을 지원하는 종합적인 모델 평가를 가능하게 합니다. + + + ![엔터프라이즈 테스트 인터페이스](/images/enterprise/enterprise-testing.png) + + +**고급 테스트 기능:** + +- **다중 모델 비교**: 동일한 작업과 입력에 대해 여러 LLM을 동시에 테스트할 수 있습니다. GPT-4o, Claude, Llama, Groq, Cerebras 및 기타 선도적인 모델의 성능을 병렬로 비교하여 특정 사용 사례에 가장 적합한 모델을 식별할 수 있습니다. + +- **통계적 엄밀성**: 일관된 입력값으로 여러 번 테스트를 구성하여 신뢰성과 성능 편차를 측정할 수 있습니다. 이를 통해 단순히 잘하는 모델이 아닌, 여러 번 실행해도 안정적으로 동작하는 모델을 식별할 수 있습니다. + +- **실제 환경 검증**: 합성 벤치마크가 아닌 실제 crew 입력값과 시나리오를 사용할 수 있습니다. 플랫폼을 통해 산업 환경, 회사 정보, 실제 사용 사례 등 특정 맥락에 맞는 테스트가 가능하여 보다 정확한 평가가 이뤄집니다. + +- **종합 분석 도구**: 테스트한 모든 모델의 세부 성능 지표, 실행 시간, 비용 분석을 확인할 수 있습니다. 이로써 모델의 일반적인 평판이나 이론적 능력에 기대지 않고 데이터 기반으로 의사결정을 내릴 수 있습니다. + +- **팀 협업**: 팀 내에서 테스트 결과와 모델 성능 데이터를 공유할 수 있어, 협업적 의사결정과 프로젝트 전반에서 일관된 모델 선택 전략을 수립할 수 있습니다. + +지금 [app.crewai.com](https://app.crewai.com)에서 시작하세요! + + + Enterprise 플랫폼은 모델 선택을 단순한 추측이 아닌 데이터 기반 프로세스로 + 혁신하여, 본 가이드의 원칙을 실제 사용 사례와 요구 사항에 맞게 검증할 수 + 있도록 해줍니다. + + +## 주요 원칙 요약 + + + + 이론적 능력이나 일반적인 평판이 아니라, 작업에 실제로 필요한 것에 따라 모델을 선택하세요. + + +{" "} + + 최적의 성능을 위해 모델의 강점을 agent의 역할 및 책임과 일치시키세요. + + +{" "} + + 관련 구성 요소와 워크플로 전반에 걸쳐 일관된 모델 선택 전략을 유지하세요. + + +{" "} + + 벤치마크에만 의존하지 말고 실제 사용을 통해 선택을 검증하세요. + + +{" "} + + 단순하게 시작하고 실제 성능과 필요에 따라 최적화하세요. + + + + 성능 요구사항과 비용 및 복잡성 제약을 균형 있게 맞추세요. + + + + + 기억하세요: 최고의 LLM 선택이란 운영상의 제약 내에서 일관되게 필요한 결과를 + 제공하는 모델입니다. 먼저 요구사항을 정확히 이해하는 데 집중한 후, 그에 가장 + 잘 맞는 모델을 선택하세요. + + +## 현재 모델 현황 (2025년 6월) + + + **특정 시점의 스냅샷**: 아래 모델 순위는 2025년 6월 기준으로, [LMSys + Arena](https://arena.lmsys.org/), [Artificial + Analysis](https://artificialanalysis.ai/) 및 기타 주요 벤치마크에서 집계된 + 최신 리더보드 결과입니다. LLM의 성능, 가용성, 가격은 빠르게 변동됩니다. 항상 + 귀하의 특정 사용 사례와 데이터로 직접 평가를 진행하시기 바랍니다. + + +### 카테고리별 주요 모델 + +아래 표는 다양한 카테고리에서 현재 최고의 성능을 보이는 대표적인 모델들을 보여주며, CrewAI 에이전트에 적합한 모델 선택에 대한 가이드를 제공합니다: + + + 이 표와 지표는 각 카테고리에서 선별된 주요 모델을 보여주기 위한 것으로, 전체를 + 포괄하지 않습니다. 여기 소개되지 않은 훌륭한 모델들도 많이 존재합니다. 이 표의 + 목적은 완전한 목록을 제공하는 것이 아니라, 어떤 능력을 갖춘 모델을 찾아야 + 하는지 예시를 제시하는 것입니다. + + + + + **매니저 LLM 및 복잡한 분석에 최적** + + | Model | Intelligence Score | Cost ($/M tokens) | Speed | Best Use in CrewAI | + |:------|:------------------|:------------------|:------|:------------------| + | **o3** | 70 | $17.50 | 빠름 | 복잡한 멀티 에이전트 조정용 매니저 LLM | + | **Gemini 2.5 Pro** | 69 | $3.44 | 빠름 | 전략 기획 에이전트, 연구 조정 | + | **DeepSeek R1** | 68 | $0.96 | 보통 | 예산을 중시하는 팀을 위한 비용 효율적 reasoning | + | **Claude 4 Sonnet** | 53 | $6.00 | 빠름 | 세밀한 이해가 필요한 분석 에이전트 | + | **Qwen3 235B (Reasoning)** | 62 | $2.63 | 보통 | reasoning 작업을 위한 오픈소스 대안 | + + 이 모델들은 다단계 reasoning에 뛰어나며, 전략을 개발하거나 다른 에이전트를 조정하거나 복잡한 정보를 분석해야 하는 에이전트에 이상적입니다. + + + + + **개발 및 도구 중심의 워크플로우에 최적** + + | Model | Coding Performance | Tool Use Score | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:------------------|:---------------|:------------------|:------------------| + | **Claude 4 Sonnet** | 우수 | 72.7% | $6.00 | 주력 코딩 에이전트, 기술 문서화 | + | **Claude 4 Opus** | 우수 | 72.5% | $30.00 | 복잡한 소프트웨어 아키텍처, 코드 리뷰 | + | **DeepSeek V3** | 매우 좋음 | 높음 | $0.48 | 일상적 개발을 위한 비용 효율적 코딩 | + | **Qwen2.5 Coder 32B** | 매우 좋음 | 보통 | $0.15 | 예산 친화적 코딩 에이전트 | + | **Llama 3.1 405B** | 좋음 | 81.1% | $3.50 | 도구 사용이 많은 워크플로우를 위한 function calling LLM | + + 이 모델들은 코드 생성, 디버깅, 기술 문제 해결에 최적화되어 있어, 개발 중심 팀에 적합합니다. + + + + + **대량 처리 및 실시간 애플리케이션에 최적** + + | Model | Speed (tokens/s) | Latency (TTFT) | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:-----------------|:---------------|:------------------|:------------------| + | **Llama 4 Scout** | 2,600 | 0.33s | $0.27 | 대량 처리 에이전트 | + | **Gemini 2.5 Flash** | 376 | 0.30s | $0.26 | 실시간 응답 에이전트 | + | **DeepSeek R1 Distill** | 383 | 가변 | $0.04 | 비용 최적화 고속 처리 | + | **Llama 3.3 70B** | 2,500 | 0.52s | $0.60 | 균형 잡힌 속도와 기능 | + | **Nova Micro** | 높음 | 0.30s | $0.04 | 단순·빠른 작업 처리 | + + 이 모델들은 속도와 효율을 우선시하며, 일상적 운영 또는 신속한 응답이 필요한 에이전트에게 최적입니다. **팁**: 이러한 모델을 Groq와 같은 빠른 추론 제공자와 함께 사용하면 더욱 우수한 성능을 낼 수 있습니다. 특히 Llama와 같은 오픈소스 모델에 적합합니다. + + + + + **일반 팀을 위한 최고의 다목적 모델** + + | Model | Overall Score | Versatility | Cost ($/M tokens) | Best Use in CrewAI | + |:------|:--------------|:------------|:------------------|:------------------| + | **GPT-4.1** | 53 | 탁월 | $3.50 | 범용 팀 LLM | + | **Claude 3.7 Sonnet** | 48 | 매우 좋음 | $6.00 | 균형 잡힌 reasoning 및 창의력 | + | **Gemini 2.0 Flash** | 48 | 좋음 | $0.17 | 비용 효율적인 범용 용도 | + | **Llama 4 Maverick** | 51 | 좋음 | $0.37 | 오픈소스 범용 모델 | + | **Qwen3 32B** | 44 | 좋음 | $1.23 | 예산 친화적 다재다능성 | + + 이 모델들은 다양한 측면에서 우수한 성능을 제공하며, 여러 작업이 혼합된 팀에 적합합니다. + + + + +### 현재 모델을 위한 선택 프레임워크 + + + + **퍼포먼스가 우선 순위일 때**: 매니저 LLM 또는 중요한 에이전트 역할에는 **o3**, **Gemini 2.5 Pro**, **Claude 4 Sonnet**과 같은 최상위 모델을 사용하세요. 이 모델들은 복잡한 reasoning 및 coordination에 탁월하지만 비용이 더 높습니다. + + **전략**: 프리미엄 모델이 전략적 사고를 담당하고, 효율적인 모델이 일상적 operation을 처리하는 멀티 모델 접근법을 구현하세요. + + + + + **예산이 주요 제약일 때**: **DeepSeek R1**, **Llama 4 Scout**, **Gemini 2.0 Flash**와 같은 모델에 집중하세요. 이 모델들은 훨씬 낮은 비용으로 강력한 퍼포먼스를 제공합니다. + + **전략**: 대부분의 에이전트에는 비용 효율이 높은 모델을 사용하고, 가장 중요한 decision-making 역할에만 프리미엄 모델을 남겨두세요. + + + + + **특정 도메인 전문성이 필요할 때**: 주된 사용 사례에 최적화된 모델을 선택하세요. 코딩에는 **Claude 4** 시리즈, 리서치에는 **Gemini 2.5 Pro**, function calling에는 **Llama 405B**를 사용하세요. + + **전략**: crew의 주요 기능에 따라 모델을 선택해, 핵심 역량이 모델의 강점과 일치하도록 하세요. + + + + + **데이터 민감한 operation의 경우**: 로컬에서 배포 가능하면서 경쟁력 있는 퍼포먼스를 유지하는 오픈 소스 모델인 **Llama 4** 시리즈, **DeepSeek V3**, **Qwen3** 등을 고려하세요. + + **전략**: 사설 인프라에 오픈 소스 모델을 배포하여, 데이터 제어를 위해 필요한 퍼포먼스 손실을 감수하세요. + + + + +### 모델 선택을 위한 주요 고려사항 + +- **성능 동향**: 현재 시장에서는 reasoning에 초점을 맞춘 모델(o3, Gemini 2.5 Pro)과 균형 잡힌 모델(Claude 4, GPT-4.1) 간의 치열한 경쟁이 있습니다. DeepSeek R1과 같은 특화 모델은 우수한 비용-성능 비율을 제공합니다. + +- **속도와 지능 간의 트레이드오프**: Llama 4 Scout와 같은 모델은 합리적인 지능을 유지하면서도 빠른 속도(2,600 tokens/s)를 우선시하며, o3와 같은 모델은 속도와 가격을 희생해 reasoning 능력을 극대화합니다. + +- **오픈 소스의 실효성**: 오픈 소스와 독점 모델 간의 격차가 계속 좁혀지고 있으며, Llama 4 Maverick 및 DeepSeek V3와 같은 모델이 매력적인 가격대에서 경쟁력 있는 성능을 제공합니다. 특히 빠른 추론을 제공하는 업체들은 오픈 소스 모델과 함께 탁월한 속도-비용 비율을 제공하는 경우가 많아 독점 모델보다 우위에 서기도 합니다. + + + **테스트는 필수입니다**: 리더보드 순위는 일반적인 가이드라인을 제공하지만, + 귀하의 특정 사용 사례, 프롬프트 스타일, 평가 기준에 따라 결과가 달라질 수 + 있습니다. 최종 결정을 내리기 전에 반드시 실제 작업과 데이터로 후보 모델을 + 테스트해 보세요. + + +### 실질적인 구현 전략 + + + + 여러 차원에서 우수한 성능을 제공하며 실제 환경에서 광범위하게 검증된 **GPT-4.1**, **Claude 3.7 Sonnet**, **Gemini 2.0 Flash**와 같은 잘 알려진 모델부터 시작하십시오. + + + + crew에 코드 작성, reasoning, 속도 등 특정 요구가 있는지 확인하고, 이러한 + 요구에 부합하는 **Claude 4 Sonnet**(개발용) 또는 **o3**(복잡한 분석용)과 같은 + 특화 모델을 고려하십시오. 속도가 중요한 애플리케이션의 경우, 모델 선택과 + 더불어 **Groq**와 같은 빠른 추론 제공자를 고려할 수 있습니다. + + + + 각 에이전트의 역할에 따라 다양한 모델을 사용하세요. 관리자와 복잡한 작업에는 + 고성능 모델을, 일상적 운영에는 효율적인 모델을 적용합니다. + + + + 사용 사례와 관련된 성능 지표를 추적하고, 새로운 모델이 출시되거나 가격이 변동될 때 모델 선택을 조정할 준비를 하십시오. + + diff --git a/docs/v1.15.13/ko/learn/multimodal-agents.mdx b/docs/v1.15.13/ko/learn/multimodal-agents.mdx new file mode 100644 index 0000000000..5f4c36b8ca --- /dev/null +++ b/docs/v1.15.13/ko/learn/multimodal-agents.mdx @@ -0,0 +1,141 @@ +--- +title: 멀티모달 에이전트 사용하기 +description: CrewAI 프레임워크 내에서 이미지 및 기타 비텍스트 콘텐츠를 처리하기 위해 에이전트에서 멀티모달 기능을 활성화하고 사용하는 방법을 알아보세요. +icon: video +mode: "wide" +--- + +## 멀티모달 에이전트 사용하기 + +CrewAI는 텍스트뿐만 아니라 이미지와 같은 비텍스트 콘텐츠도 처리할 수 있는 멀티모달 에이전트를 지원합니다. 이 가이드에서는 에이전트에서 멀티모달 기능을 활성화하고 사용하는 방법을 안내합니다. + +### 멀티모달 기능 활성화 + +멀티모달 에이전트를 생성하려면, 에이전트를 초기화할 때 `multimodal` 파라미터를 `True`로 설정하면 됩니다: + +```python +from crewai import Agent + +agent = Agent( + role="Image Analyst", + goal="Analyze and extract insights from images", + backstory="An expert in visual content interpretation with years of experience in image analysis", + multimodal=True # This enables multimodal capabilities +) +``` + +`multimodal=True`로 설정하면, 에이전트는 자동으로 비텍스트 콘텐츠를 처리하는 데 필요한 도구들(예: `AddImageTool`)과 함께 구성됩니다. + +### 이미지 작업하기 + +멀티모달 에이전트는 이미지를 처리할 수 있는 `AddImageTool`이 사전 구성되어 포함되어 있습니다. 이 도구를 수동으로 추가할 필요가 없으며, 멀티모달 기능을 활성화하면 자동으로 포함됩니다. + +아래는 멀티모달 에이전트를 사용하여 이미지를 분석하는 방법을 보여주는 전체 예제입니다: + +```python +from crewai import Agent, Task, Crew + +# Create a multimodal agent +image_analyst = Agent( + role="Product Analyst", + goal="Analyze product images and provide detailed descriptions", + backstory="Expert in visual product analysis with deep knowledge of design and features", + multimodal=True +) + +# Create a task for image analysis +task = Task( + description="Analyze the product image at https://example.com/product.jpg and provide a detailed description", + expected_output="A detailed description of the product image", + agent=image_analyst +) + +# Create and run the crew +crew = Crew( + agents=[image_analyst], + tasks=[task] +) + +result = crew.kickoff() +``` + +### 컨텍스트를 활용한 고급 사용법 + +멀티모달 agent를 위한 task를 생성할 때 추가적인 컨텍스트나 이미지에 대한 구체적인 질문을 제공할 수 있습니다. task 설명에는 agent가 집중해야 할 특정 측면을 포함할 수 있습니다. + +```python +from crewai import Agent, Task, Crew + +# Create a multimodal agent for detailed analysis +expert_analyst = Agent( + role="Visual Quality Inspector", + goal="Perform detailed quality analysis of product images", + backstory="Senior quality control expert with expertise in visual inspection", + multimodal=True # AddImageTool is automatically included +) + +# Create a task with specific analysis requirements +inspection_task = Task( + description=""" + Analyze the product image at https://example.com/product.jpg with focus on: + 1. Quality of materials + 2. Manufacturing defects + 3. Compliance with standards + Provide a detailed report highlighting any issues found. + """, + expected_output="A detailed report highlighting any issues found", + agent=expert_analyst +) + +# Create and run the crew +crew = Crew( + agents=[expert_analyst], + tasks=[inspection_task] +) + +result = crew.kickoff() +``` + +### 도구 세부 정보 + +멀티모달 에이전트를 사용할 때, `AddImageTool`은 다음 스키마로 자동 구성됩니다: + +```python +class AddImageToolSchema: + image_url: str # Required: The URL or path of the image to process + action: Optional[str] = None # Optional: Additional context or specific questions about the image +``` + +멀티모달 에이전트는 내장 도구를 통해 자동으로 이미지 처리를 수행하므로 다음과 같은 작업이 가능합니다: +- URL 또는 로컬 파일 경로를 통해 이미지 접근 +- 선택적 컨텍스트나 구체적인 질문을 포함하여 이미지 내용 처리 +- 시각적 정보와 작업 요구사항에 따른 분석 및 인사이트 제공 + +### 모범 사례 + +멀티모달 에이전트를 사용할 때 다음의 모범 사례를 염두에 두세요: + +1. **이미지 접근성** + - 에이전트가 접근할 수 있는 URL을 통해 이미지를 제공해야 합니다. + - 로컬 이미지는 임시로 호스팅하거나 절대 파일 경로를 사용하는 것을 고려하세요. + - 작업을 실행하기 전에 이미지 URL이 유효하고 접근 가능한지 확인하세요. + +2. **작업 설명** + - 에이전트가 이미지의 어떤 부분을 분석하기를 원하는지 구체적으로 명시하세요. + - 작업 설명에 명확한 질문이나 요구사항을 포함하세요. + - 집중된 분석이 필요한 경우 선택적인 `action` 파라미터 사용을 고려하세요. + +3. **리소스 관리** + - 이미지 처리는 텍스트 전용 작업보다 더 많은 컴퓨팅 자원을 필요로 할 수 있습니다. + - 일부 언어 모델은 이미지 데이터를 base64로 인코딩해야 할 수 있습니다. + - 성능 최적화를 위해 여러 이미지를 일괄 처리하는 방법을 고려하세요. + +4. **환경 설정** + - 이미지 처리를 위한 필수 의존성이 환경에 설치되어 있는지 확인하세요. + - 사용하는 언어 모델이 멀티모달 기능을 지원하는지 확인하세요. + - 설정을 검증하기 위해 작은 이미지를 먼저 테스트하세요. + +5. **오류 처리** + - 이미지 로딩 실패에 대한 적절한 오류 처리를 구현하세요. + - 이미지 처리 실패 시를 대비한 예비 전략을 마련하세요. + - 디버깅을 위해 이미지 처리 작업을 모니터링하고 로그를 남기세요. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/overview.mdx b/docs/v1.15.13/ko/learn/overview.mdx new file mode 100644 index 0000000000..0568222ce3 --- /dev/null +++ b/docs/v1.15.13/ko/learn/overview.mdx @@ -0,0 +1,159 @@ +--- +title: "개요" +description: "포괄적인 가이드와 튜토리얼을 통해 CrewAI 애플리케이션을 빌드하고, 맞춤화하며, 최적화하는 방법을 알아보세요." +icon: "face-smile" +mode: "wide" +--- + +## CrewAI 배우기 + +이 섹션은 CrewAI를 마스터하는 데 도움이 되는 종합적인 가이드와 튜토리얼을 제공합니다. 기본 개념부터 고급 기술까지 다루며, 이제 막 시작하는 분이든 기존 구현을 최적화하려는 분이든, 이 자료들은 강력한 AI 에이전트 워크플로우를 구축하는 모든 측면을 안내해 드립니다. + +## 시작하기 안내 + +### 핵심 개념 + + + 구조화된 워크플로우를 위해 작업을 순차적으로 실행하는 방법을 학습합니다. + + + + 매니저 에이전트가 워크플로우를 감독하며 계층적으로 작업을 실행합니다. + + + + 결과에 따라 조건부로 작업을 실행하여 동적인 워크플로우를 만듭니다. + + + + 향상된 성능과 동시성을 위해 crew를 비동기로 실행합니다. + + + +### 에이전트 개발 + + + 에이전트의 동작 방식, 역할, 역량을 커스터마이즈하는 방법을 배워보세요. + + + + 코드 작성, 실행, 디버깅을 자동으로 수행할 수 있는 에이전트를 구축하세요. + + + + 텍스트, 이미지, 기타 미디어 유형을 처리할 수 있는 에이전트를 만들어보세요. + + + + 복잡한 계층적 워크플로우를 위한 커스텀 매니저 에이전트를 구현하세요. + + + +## 고급 기능 + +### 워크플로 제어 + + + 에이전트 워크플로에 인간의 감독과 개입을 통합하세요. + + + + 작업 실행 중에 인간의 입력을 허용하여 동적인 의사결정을 지원합니다. + + + + 이전 crew 실행으로부터 작업을 다시 실행하고 재개하세요. + + + + 서로 다른 입력으로 crew를 효율적으로 여러 번 실행하세요. + + + +### 맞춤화 및 통합 + + + CrewAI와 커스텀 언어 모델 및 공급자를 통합하세요. + + + + 다양한 LLM 공급자에 대한 연결을 구성하고 관리하세요. + + + + 에이전트의 기능을 확장할 수 있는 커스텀 도구를 빌드하세요. + + + + 더 깔끔하고 유지 관리하기 쉬운 코드를 위해 Python 주석을 사용하세요. + + + +## 특수화된 애플리케이션 + +### 콘텐츠 & 미디어 + + + 에이전트와의 DALL-E 통합을 사용하여 이미지를 생성하세요. + + + + 기존 에이전트와 모델을 CrewAI 워크플로우에 통합하세요. + + + +### 도구 관리 + + + 도구를 구성하여 출력값을 작업 결과로 직접 반환하도록 합니다. + + + +## 학습 경로 추천 + +### 초보자를 위한 안내 +1. 기본 워크플로 실행을 이해하려면 **Sequential Process**로 시작하세요. +2. 효과적인 에이전트 구성을 만들기 위해 **Customizing Agents**를 학습하세요. +3. 기능 확장을 위해 **Create Custom Tools**을(를) 탐색하세요. +4. 인터랙티브 워크플로를 위해 **Human in the Loop**을(를) 시도해 보세요. + +### 중급 사용자를 위한 안내 +1. 복잡한 다중 에이전트 시스템을 위해 **계층적 프로세스** 마스터하기 +2. 동적 워크플로우를 위해 **조건부 태스크** 구현하기 +3. 성능 최적화를 위해 **비동기 시작** 사용하기 +4. 특화된 모델을 위해 **커스텀 LLM** 통합하기 + +### 고급 사용자용 +1. 복잡한 미디어 처리를 위한 **멀티모달 에이전트** 빌드 +2. 정교한 오케스트레이션을 위한 **커스텀 매니저 에이전트** 생성 +3. 하이브리드 시스템을 위한 **BYOA(Bring Your Own Agent)** 구현 +4. 견고한 오류 복구를 위한 **리플레이 태스크** 사용 + +## 모범 사례 + +### 개발 +- **간단하게 시작하세요**: 복잡성을 추가하기 전에 기본적인 순차 워크플로우부터 시작하세요 +- **점진적으로 테스트하세요**: 더 큰 시스템에 통합하기 전에 각 구성 요소를 테스트하세요 +- **애노테이션 사용**: 더 깔끔하고 유지보수가 쉬운 코드를 위해 Python 애노테이션을 활용하세요 +- **커스텀 도구**: 다양한 agent에서 공유할 수 있는 재사용 가능한 도구를 만드세요 + +### 운영 환경 +- **오류 처리**: 강력한 오류 처리 및 복구 메커니즘 구현 +- **성능**: 비동기 실행을 사용하고 더 나은 성능을 위해 LLM 호출 최적화 +- **모니터링**: 에이전트 성능 추적을 위해 가시성 도구 통합 +- **인간 감독**: 중요한 의사결정을 위한 인간 점검 지점 포함 + +### 최적화 +- **리소스 관리**: 토큰 사용량과 API 비용을 모니터링하고 최적화합니다. +- **워크플로우 설계**: 불필요한 LLM 호출을 최소화하는 워크플로우를 설계합니다. +- **도구 효율성**: 최소한의 오버헤드로 최대 가치를 제공하는 효율적인 도구를 만듭니다. +- **반복적 개선**: 피드백과 메트릭을 활용하여 에이전트 성능을 지속적으로 개선합니다. + +## 도움 받기 + +- **문서**: 각 가이드에는 자세한 예시와 설명이 포함되어 있습니다 +- **커뮤니티**: 토론과 지원을 위해 [CrewAI 포럼](https://community.crewai.com)에 참여하세요 +- **예제**: 완전한 작동 구현을 보려면 예제 섹션을 확인하세요 +- **지원**: 기술 지원이 필요하면 [support@crewai.com](mailto:support@crewai.com)으로 문의하세요 + +현재 필요에 맞는 가이드부터 시작하고, 기본 사항에 익숙해지면 점차 더 고급 주제를 탐색해보세요. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/replay-tasks-from-latest-crew-kickoff.mdx b/docs/v1.15.13/ko/learn/replay-tasks-from-latest-crew-kickoff.mdx new file mode 100644 index 0000000000..1ae9eae33d --- /dev/null +++ b/docs/v1.15.13/ko/learn/replay-tasks-from-latest-crew-kickoff.mdx @@ -0,0 +1,79 @@ +--- +title: 최신 Crew Kickoff에서 작업 다시 실행하기 +description: 최신 crew.kickoff(...)에서 작업을 다시 실행합니다. +icon: arrow-right +mode: "wide" +--- + +## 소개 + +CrewAI는 최신 crew 킥오프에서 지정된 태스크를 다시 실행할 수 있는 기능을 제공합니다. 이 기능은 킥오프를 완료한 후 특정 태스크를 다시 시도하고 싶거나 데이터를 다시 가져올 필요 없이 이미 에이전트들이 킥오프 실행에서 컨텍스트를 저장한 경우, 원하는 태스크만 다시 실행(Replay)하면 될 때 특히 유용합니다. + + + 태스크를 다시 실행하기 전에 반드시 `crew.kickoff()`을 실행해야 합니다. + 현재는 최신 킥오프만 지원되므로, `kickoff_for_each`를 사용하는 경우에도 가장 최근의 crew 실행만 다시 실행할 수 있습니다. + + +다음은 태스크에서 다시 실행하는 방법의 예시입니다: + +### CLI를 사용하여 특정 Task에서 재실행하기 + +재실행 기능을 사용하려면 다음 단계를 따르세요: + + + + + + 최신 kickoff task_id를 확인하려면 아래를 사용하세요: + + ```shell + crewai log-tasks-outputs + ``` + + 재실행할 `task_id`를 확인했다면, 아래를 사용하세요: + + ```shell + crewai replay -t + ``` + + + + + 개발 환경에 `crewai`가 정상적으로 설치 및 구성되어 있는지 확인하세요. + + +### 작업에서 프로그래밍 방식으로 리플레이하기 + +작업에서 프로그래밍 방식으로 리플레이하려면 다음 단계를 따르세요: + + + + 리플레이 프로세스를 위한 `task_id`와 입력 파라미터를 지정합니다. + + + 잠재적인 오류를 처리하기 위해 try-except 블록 내에서 리플레이 명령을 실행합니다. + + ```python Code + def replay(): + """ + Replay the crew execution from a specific task. + """ + task_id = '' + inputs = {"topic": "CrewAI Training"} # This is optional; you can pass in the inputs you want to replay; otherwise, it uses the previous kickoff's inputs. + try: + YourCrewName_Crew().crew().replay(task_id=task_id, inputs=inputs) + + except subprocess.CalledProcessError as e: + raise Exception(f"An error occurred while replaying the crew: {e}") + + except Exception as e: + raise Exception(f"An unexpected error occurred: {e}") + ``` + + + + +## 결론 + +위의 개선 사항과 세부적인 기능으로 CrewAI에서 특정 작업을 재실행하는 것이 더욱 효율적이고 견고해졌습니다. +이러한 기능을 최대한 활용하려면 명령어와 단계를 정확하게 따라주시기 바랍니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/sequential-process.mdx b/docs/v1.15.13/ko/learn/sequential-process.mdx new file mode 100644 index 0000000000..e8760c7c5f --- /dev/null +++ b/docs/v1.15.13/ko/learn/sequential-process.mdx @@ -0,0 +1,128 @@ +--- +title: 순차 프로세스 +description: CrewAI 프로젝트에서 작업 실행을 위한 순차 프로세스를 활용하는 방법에 대한 종합 가이드입니다. +icon: forward +mode: "wide" +--- + +## 소개 + +CrewAI는 순차적 및 계층적 프로세스를 모두 지원하는 구조화된 방식으로 작업을 실행할 수 있는 유연한 프레임워크를 제공합니다. +이 가이드에서는 효율적인 작업 실행과 프로젝트 완수를 보장하기 위해 이러한 프로세스를 효과적으로 구현하는 방법을 설명합니다. + +## 순차적 프로세스 개요 + +순차적 프로세스는 작업이 선형적인 진행 방식으로 하나씩 차례로 실행되도록 보장합니다. +이 접근 방식은 특정 순서로 작업이 완료되어야 하는 프로젝트에 이상적입니다. + +### 주요 기능 + +- **선형 작업 흐름**: 미리 정해진 순서대로 작업을 처리하여 체계적인 진행을 보장합니다. +- **단순성**: 명확하고 단계별 작업이 있는 프로젝트에 가장 적합합니다. +- **쉬운 모니터링**: 작업 완료 및 프로젝트 진행 상황을 쉽게 추적할 수 있습니다. + +## 순차적 프로세스 구현하기 + +순차적 프로세스를 사용하려면 crew를 구성하고 수행되어야 하는 순서대로 작업을 정의하세요. + +```python Code +from crewai import Crew, Process, Agent, Task, TaskOutput, CrewOutput + +# Define your agents +researcher = Agent( + role='Researcher', + goal='Conduct foundational research', + backstory='An experienced researcher with a passion for uncovering insights' +) +analyst = Agent( + role='Data Analyst', + goal='Analyze research findings', + backstory='A meticulous analyst with a knack for uncovering patterns' +) +writer = Agent( + role='Writer', + goal='Draft the final report', + backstory='A skilled writer with a talent for crafting compelling narratives' +) + +# Define your tasks +research_task = Task( + description='Gather relevant data...', + agent=researcher, + expected_output='Raw Data' +) +analysis_task = Task( + description='Analyze the data...', + agent=analyst, + expected_output='Data Insights' +) +writing_task = Task( + description='Compose the report...', + agent=writer, + expected_output='Final Report' +) + +# Form the crew with a sequential process +report_crew = Crew( + agents=[researcher, analyst, writer], + tasks=[research_task, analysis_task, writing_task], + process=Process.sequential +) + +# Execute the crew +result = report_crew.kickoff() + +# Accessing the type-safe output +task_output: TaskOutput = result.tasks[0].output +crew_output: CrewOutput = result.output +``` + +### 참고: + +순차적 프로세스의 각 작업에는 **반드시** 에이전트가 할당되어야 합니다. 모든 `Task`에 `agent` 파라미터가 포함되어 있는지 확인하세요. + +### 워크플로우 실행 + +1. **초기 작업**: 순차적인 프로세스에서 첫 번째 agent가 자신의 작업을 완료하고 완료 신호를 보냅니다. +2. **이후 작업들**: agent들은 프로세스 유형에 따라 작업을 수행하며, 이전 작업의 결과나 지침이 실행을 안내합니다. +3. **완료**: 최종 작업이 실행되면 프로세스가 종료되어 프로젝트가 완료됩니다. + +## 고급 기능 + +### 작업 위임 + +순차적 프로세스에서, 에이전트가 `allow_delegation`이 `True`로 설정되어 있으면 해당 에이전트는 crew 내의 다른 에이전트에게 작업을 위임할 수 있습니다. +이 기능은 crew에 여러 에이전트가 있을 때 자동으로 설정됩니다. + +### 비동기 실행 + +작업은 비동기로 실행될 수 있어, 적절할 때 병렬 처리가 가능합니다. +비동기 작업을 생성하려면 작업을 정의할 때 `async_execution=True`로 설정하세요. + +### 메모리 및 캐싱 + +CrewAI는 메모리와 캐싱 기능을 모두 지원합니다: + +- **메모리**: Crew를 생성할 때 `memory=True`로 설정하면 활성화됩니다. 이를 통해 에이전트가 작업 간 정보를 유지할 수 있습니다. +- **캐싱**: 기본적으로 캐싱이 활성화되어 있습니다. 비활성화하려면 `cache=False`로 설정하세요. + +### 콜백 + +콜백은 작업(task) 수준과 단계(step) 수준 모두에서 설정할 수 있습니다: + +- `task_callback`: 각 작업이 완료된 후 실행됩니다. +- `step_callback`: 에이전트의 각 단계 실행 후에 실행됩니다. + +### 사용량 메트릭 + +CrewAI는 모든 task와 agent 전반에 걸쳐 토큰 사용량을 추적합니다. 이 메트릭은 실행 후에 확인할 수 있습니다. + +## 순차적 프로세스를 위한 모범 사례 + +1. **순서가 중요함**: 각 작업이 이전 작업을 기반으로 쌓일 수 있도록 논리적인 순서로 작업을 배열하세요. +2. **명확한 작업 설명**: 각 작업에 대해 에이전트를 효과적으로 안내할 수 있도록 상세한 설명을 제공하세요. +3. **적절한 에이전트 선정**: 각 작업의 요구사항에 맞게 에이전트의 역량과 역할을 매칭하세요. +4. **컨텍스트 활용**: 이전 작업에서 얻은 컨텍스트를 다음 작업에 활용하세요. + +이 업데이트된 문서는 코드베이스의 최신 변경 사항을 정확하게 반영하고, 새로운 기능 및 설정을 어떻게 활용할 수 있는지 명확하게 설명합니다. +내용이 간단하고 명확하여 쉽게 이해할 수 있도록 구성되었습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/streaming-crew-execution.mdx b/docs/v1.15.13/ko/learn/streaming-crew-execution.mdx new file mode 100644 index 0000000000..db2ce1c0c0 --- /dev/null +++ b/docs/v1.15.13/ko/learn/streaming-crew-execution.mdx @@ -0,0 +1,384 @@ +--- +title: 스트리밍 Crew 실행 +description: CrewAI crew 실행에서 실시간 출력을 스트리밍하기 +icon: wave-pulse +mode: "wide" +--- + +## 소개 + +CrewAI는 crew 실행 중 실시간 출력을 스트리밍하는 기능을 제공하여, 전체 프로세스가 완료될 때까지 기다리지 않고 결과가 생성되는 대로 표시할 수 있습니다. 이 기능은 대화형 애플리케이션을 구축하거나, 사용자 피드백을 제공하거나, 장시간 실행되는 프로세스를 모니터링할 때 특히 유용합니다. + +## 스트리밍 작동 방식 + +스트리밍이 활성화되면 CrewAI는 LLM 응답과 도구 호출을 실시간으로 캡처하여, 어떤 task와 agent가 실행 중인지에 대한 컨텍스트를 포함한 구조화된 청크로 패키징합니다. 이러한 청크를 실시간으로 반복 처리하고 실행이 완료되면 최종 결과에 접근할 수 있습니다. + +## 스트리밍 활성화 + +스트리밍을 활성화하려면 crew를 생성할 때 `stream` 파라미터를 `True`로 설정하세요: + +```python Code +from crewai import Agent, Crew, Task + +# 에이전트와 태스크 생성 +researcher = Agent( + role="Research Analyst", + goal="Gather comprehensive information on topics", + backstory="You are an experienced researcher with excellent analytical skills.", +) + +task = Task( + description="Research the latest developments in AI", + expected_output="A detailed report on recent AI advancements", + agent=researcher, +) + +# 스트리밍 활성화 +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True # 스트리밍 출력 활성화 +) +``` + +## 동기 스트리밍 + +스트리밍이 활성화된 crew에서 `kickoff()`를 호출하면, 청크가 도착할 때마다 반복 처리할 수 있는 `CrewStreamingOutput` 객체가 반환됩니다: + +```python Code +# 스트리밍 실행 시작 +streaming = crew.kickoff(inputs={"topic": "artificial intelligence"}) + +# 청크가 도착할 때마다 반복 +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# 스트리밍 완료 후 최종 결과 접근 +result = streaming.result +print(f"\n\n최종 출력: {result.raw}") +``` + +### 스트림 청크 정보 + +각 청크는 실행에 대한 풍부한 컨텍스트를 제공합니다: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +for chunk in streaming: + print(f"Task: {chunk.task_name} (인덱스 {chunk.task_index})") + print(f"Agent: {chunk.agent_role}") + print(f"Content: {chunk.content}") + print(f"Type: {chunk.chunk_type}") # TEXT 또는 TOOL_CALL + if chunk.tool_call: + print(f"Tool: {chunk.tool_call.tool_name}") + print(f"Arguments: {chunk.tool_call.arguments}") +``` + +### 스트리밍 결과 접근 + +`CrewStreamingOutput` 객체는 여러 유용한 속성을 제공합니다: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +# 청크 반복 및 수집 +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# 반복 완료 후 +print(f"\n완료됨: {streaming.is_completed}") +print(f"전체 텍스트: {streaming.get_full_text()}") +print(f"전체 청크 수: {len(streaming.chunks)}") +print(f"최종 결과: {streaming.result.raw}") +``` + +## 비동기 스트리밍 + +비동기 애플리케이션의 경우, 비동기 반복과 함께 `akickoff()`(네이티브 async) 또는 `kickoff_async()`(스레드 기반)를 사용할 수 있습니다: + +### `akickoff()`를 사용한 네이티브 Async + +`akickoff()` 메서드는 전체 체인에서 진정한 네이티브 async 실행을 제공합니다: + +```python Code +import asyncio + +async def stream_crew(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + # 네이티브 async 스트리밍 시작 + streaming = await crew.akickoff(inputs={"topic": "AI"}) + + # 청크에 대한 비동기 반복 + async for chunk in streaming: + print(chunk.content, end="", flush=True) + + # 최종 결과 접근 + result = streaming.result + print(f"\n\n최종 출력: {result.raw}") + +asyncio.run(stream_crew()) +``` + +### `kickoff_async()`를 사용한 스레드 기반 Async + +더 간단한 async 통합이나 하위 호환성을 위해: + +```python Code +import asyncio + +async def stream_crew(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + # 스레드 기반 async 스트리밍 시작 + streaming = await crew.kickoff_async(inputs={"topic": "AI"}) + + # 청크에 대한 비동기 반복 + async for chunk in streaming: + print(chunk.content, end="", flush=True) + + # 최종 결과 접근 + result = streaming.result + print(f"\n\n최종 출력: {result.raw}") + +asyncio.run(stream_crew()) +``` + + +고동시성 워크로드의 경우, 태스크 실행, 메모리 작업, 지식 검색에 네이티브 async를 사용하는 `akickoff()`가 권장됩니다. 자세한 내용은 [Crew 비동기 시작](/ko/learn/kickoff-async) 가이드를 참조하세요. + + +## kickoff_for_each를 사용한 스트리밍 + +`kickoff_for_each()`로 여러 입력에 대해 crew를 실행할 때, 동기 또는 비동기 여부에 따라 스트리밍이 다르게 작동합니다: + +### 동기 kickoff_for_each + +동기 `kickoff_for_each()`를 사용하면, 각 입력에 대해 하나씩 `CrewStreamingOutput` 객체의 리스트가 반환됩니다: + +```python Code +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True +) + +inputs_list = [ + {"topic": "AI in healthcare"}, + {"topic": "AI in finance"} +] + +# 스트리밍 출력 리스트 반환 +streaming_outputs = crew.kickoff_for_each(inputs=inputs_list) + +# 각 스트리밍 출력에 대해 반복 +for i, streaming in enumerate(streaming_outputs): + print(f"\n=== 입력 {i + 1} ===") + for chunk in streaming: + print(chunk.content, end="", flush=True) + + result = streaming.result + print(f"\n\n결과 {i + 1}: {result.raw}") +``` + +### 비동기 kickoff_for_each_async + +비동기 `kickoff_for_each_async()`를 사용하면, 모든 crew의 청크가 동시에 도착하는 대로 반환하는 단일 `CrewStreamingOutput`이 반환됩니다: + +```python Code +import asyncio + +async def stream_multiple_crews(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + inputs_list = [ + {"topic": "AI in healthcare"}, + {"topic": "AI in finance"} + ] + + # 모든 crew에 대한 단일 스트리밍 출력 반환 + streaming = await crew.kickoff_for_each_async(inputs=inputs_list) + + # 모든 crew의 청크가 생성되는 대로 도착 + async for chunk in streaming: + print(f"[{chunk.task_name}] {chunk.content}", end="", flush=True) + + # 모든 결과 접근 + results = streaming.results # CrewOutput 객체 리스트 + for i, result in enumerate(results): + print(f"\n\n결과 {i + 1}: {result.raw}") + +asyncio.run(stream_multiple_crews()) +``` + +## 스트림 청크 타입 + +청크는 `chunk_type` 필드로 표시되는 다양한 타입을 가질 수 있습니다: + +### TEXT 청크 + +LLM 응답의 표준 텍스트 콘텐츠: + +```python Code +for chunk in streaming: + if chunk.chunk_type == StreamChunkType.TEXT: + print(chunk.content, end="", flush=True) +``` + +### TOOL_CALL 청크 + +수행 중인 도구 호출에 대한 정보: + +```python Code +for chunk in streaming: + if chunk.chunk_type == StreamChunkType.TOOL_CALL: + print(f"\n도구 호출: {chunk.tool_call.tool_name}") + print(f"인자: {chunk.tool_call.arguments}") +``` + +## 실용적인 예시: 스트리밍을 사용한 UI 구축 + +다음은 스트리밍을 사용한 대화형 애플리케이션을 구축하는 방법을 보여주는 완전한 예시입니다: + +```python Code +import asyncio +from crewai import Agent, Crew, Task +from crewai.types.streaming import StreamChunkType + +async def interactive_research(): + # 스트리밍이 활성화된 crew 생성 + researcher = Agent( + role="Research Analyst", + goal="Provide detailed analysis on any topic", + backstory="You are an expert researcher with broad knowledge.", + ) + + task = Task( + description="Research and analyze: {topic}", + expected_output="A comprehensive analysis with key insights", + agent=researcher, + ) + + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True, + verbose=False + ) + + # 사용자 입력 받기 + topic = input("연구할 주제를 입력하세요: ") + + print(f"\n{'='*60}") + print(f"연구 중: {topic}") + print(f"{'='*60}\n") + + # 스트리밍 실행 시작 + streaming = await crew.kickoff_async(inputs={"topic": topic}) + + current_task = "" + async for chunk in streaming: + # 태스크 전환 표시 + if chunk.task_name != current_task: + current_task = chunk.task_name + print(f"\n[{chunk.agent_role}] 작업 중: {chunk.task_name}") + print("-" * 60) + + # 텍스트 청크 표시 + if chunk.chunk_type == StreamChunkType.TEXT: + print(chunk.content, end="", flush=True) + + # 도구 호출 표시 + elif chunk.chunk_type == StreamChunkType.TOOL_CALL and chunk.tool_call: + print(f"\n🔧 도구 사용: {chunk.tool_call.tool_name}") + + # 최종 결과 표시 + result = streaming.result + print(f"\n\n{'='*60}") + print("분석 완료!") + print(f"{'='*60}") + print(f"\n토큰 사용량: {result.token_usage}") + +asyncio.run(interactive_research()) +``` + +## 사용 사례 + +스트리밍은 다음과 같은 경우에 특히 유용합니다: + +- **대화형 애플리케이션**: 에이전트가 작업하는 동안 사용자에게 실시간 피드백 제공 +- **장시간 실행 태스크**: 연구, 분석 또는 콘텐츠 생성의 진행 상황 표시 +- **디버깅 및 모니터링**: 에이전트 동작과 의사 결정을 실시간으로 관찰 +- **사용자 경험**: 점진적인 결과를 표시하여 체감 지연 시간 감소 +- **라이브 대시보드**: crew 실행 상태를 표시하는 모니터링 인터페이스 구축 + +## 취소 및 리소스 정리 + +`CrewStreamingOutput`은 소비자가 연결을 끊을 때 진행 중인 작업을 즉시 중단하는 정상적인 취소를 지원합니다. + +### 비동기 컨텍스트 매니저 + +```python Code +streaming = await crew.akickoff(inputs={"topic": "AI"}) + +async with streaming: + async for chunk in streaming: + print(chunk.content, end="", flush=True) +``` + +### 명시적 취소 + +```python Code +streaming = await crew.akickoff(inputs={"topic": "AI"}) +try: + async for chunk in streaming: + print(chunk.content, end="", flush=True) +finally: + await streaming.aclose() # 비동기 + # streaming.close() # 동기 버전 +``` + +취소 후 `streaming.is_cancelled`와 `streaming.is_completed`는 모두 `True`입니다. `aclose()`와 `close()` 모두 멱등성을 가집니다. + +## 중요 사항 + +- 스트리밍은 crew의 모든 에이전트에 대해 자동으로 LLM 스트리밍을 활성화합니다 +- `.result` 속성에 접근하기 전에 모든 청크를 반복해야 합니다 +- 스트리밍을 사용하는 `kickoff_for_each_async()`의 경우, 모든 출력을 가져오려면 `.results`(복수형)를 사용하세요 +- 스트리밍은 최소한의 오버헤드를 추가하며 실제로 체감 성능을 향상시킬 수 있습니다 +- 각 청크는 풍부한 UI를 위한 전체 컨텍스트(태스크, 에이전트, 청크 타입)를 포함합니다 + +## 오류 처리 + +스트리밍 실행 중 오류 처리: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +try: + for chunk in streaming: + print(chunk.content, end="", flush=True) + + result = streaming.result + print(f"\n성공: {result.raw}") + +except Exception as e: + print(f"\n스트리밍 중 오류 발생: {e}") + if streaming.is_completed: + print("스트리밍은 완료되었지만 오류가 발생했습니다") +``` + +스트리밍을 활용하면 CrewAI로 더 반응성이 좋고 대화형인 애플리케이션을 구축하여 사용자에게 에이전트 실행과 결과에 대한 실시간 가시성을 제공할 수 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/learn/streaming-runtime-contract.mdx b/docs/v1.15.13/ko/learn/streaming-runtime-contract.mdx new file mode 100644 index 0000000000..d216d1664c --- /dev/null +++ b/docs/v1.15.13/ko/learn/streaming-runtime-contract.mdx @@ -0,0 +1,194 @@ +--- +title: 스트리밍 런타임 계약 +description: Flow, 직접 LLM 호출, 대화 턴에서 정렬된 런타임 프레임을 스트리밍합니다. +icon: tower-broadcast +mode: "wide" +--- + +## 개요 + +CrewAI는 단순한 텍스트 청크보다 더 많은 정보가 필요한 런타임을 위해 프레임 기반 스트리밍 계약을 제공합니다. 이 계약은 Flow 생명주기 이벤트, 직접 LLM 토큰, 도구 활동, 대화 메시지, 사용자 지정 이벤트에 대해 정렬된 `StreamFrame` 객체를 방출합니다. + +UI, 서비스 브리지, 터미널 앱, 배포 런타임을 만들 때 Flow, 채팅 턴, 직접 LLM 호출이 실행되는 동안 안정적인 구조화 이벤트 스트림이 필요하다면 이 API를 사용하세요. + +## StreamFrame + +모든 프레임은 같은 envelope를 가집니다: + +```python +from crewai.types.streaming import StreamFrame + +frame.id # 고유 프레임 id +frame.seq # 사용 가능한 경우 실행 로컬 순서 +frame.type # "flow_started" 같은 원본 이벤트 타입 +frame.channel # "llm", "flow", "tools", "messages", "lifecycle", "custom" +frame.namespace # 소스/런타임 namespace +frame.timestamp # 이벤트 timestamp +frame.parent_id # 사용 가능한 경우 부모 이벤트 id +frame.previous_id # 사용 가능한 경우 이전 이벤트 id +frame.data # 이벤트 payload +frame.event # frame.data의 alias +frame.content # 토큰류 프레임의 출력 가능한 텍스트, 그 외에는 "" +``` + +`channel` 필드는 소비자에서 프레임을 라우팅하는 가장 빠른 방법입니다: + +| 채널 | 포함 내용 | +|------|-----------| +| `llm` | LLM 스트리밍 이벤트의 토큰 및 thinking 청크 | +| `flow` | Flow 생명주기, 메서드 실행, 라우팅, pause/resume 이벤트 | +| `tools` | 도구 사용 이벤트 | +| `messages` | 대화 transcript 이벤트 | +| `lifecycle` | 다른 채널에 속하지 않는 런타임 생명주기 이벤트 | +| `custom` | 내장 채널에 매핑되지 않는 이벤트 | + +`frame.type`은 원본 이벤트 타입을 보존하므로, 소비자는 채널 안에서 특정 이벤트를 처리할 수 있습니다. + +## Flow 스트리밍 + +Flow에 `stream=True`를 설정하면 `kickoff()`가 stream session을 반환합니다: + +```python +from crewai.flow import Flow, start + + +class ReportFlow(Flow): + @start() + def generate(self): + return "done" + + +flow = ReportFlow(stream=True) +stream = flow.kickoff() + +with stream: + for chunk in stream: + print(chunk.content, end="", flush=True) + if chunk.type == "tool_usage_started": + print(chunk.event["tool_name"]) + +result = stream.result +``` + +`stream.result`를 읽기 전에 stream을 소비해야 합니다. 결과를 너무 일찍 접근하면 `RuntimeError`가 발생하여, 소비자가 부분 실행을 완료된 실행으로 잘못 처리하지 않도록 합니다. + +Flow 인스턴스에 `stream=True`를 설정하지 않고 단일 호출만 스트리밍하려면 `flow.stream_events(...)`를 직접 호출할 수도 있습니다. + +## 채널별 필터링 + +`StreamSession`은 선택한 채널 안에서 전역 프레임 순서를 보존하는 채널 projection을 제공합니다: + +```python +stream = flow.stream_events() + +with stream: + for frame in stream.llm: + print(frame.content, end="", flush=True) + +result = stream.result +``` + +사용 가능한 projection은 다음과 같습니다: + +| Projection | 프레임 | +|------------|--------| +| `stream.events` | 모든 프레임 | +| `stream.llm` | LLM 프레임 | +| `stream.messages` | 대화 메시지 프레임 | +| `stream.flow` | Flow 프레임 | +| `stream.tools` | 도구 프레임 | +| `stream.interleave([...])` | 선택한 채널 집합 | + +소비자가 일부 채널만 원하지만 상대 순서도 필요하다면 `stream.interleave(["flow", "llm", "messages"])`를 사용하세요. + +## 비동기 스트리밍 + +비동기 소비자는 `astream()`을 사용하세요: + +```python +flow = ReportFlow() +stream = flow.astream() + +async with stream: + async for chunk in stream.events: + print(chunk.channel, chunk.type, chunk.content) + +result = stream.result +``` + +비동기 세션은 동기 세션과 같은 projection을 제공합니다. + +## 직접 LLM 호출 스트리밍 + +`llm.call(...)`은 계속 최종 조립 결과를 반환합니다. 구조화된 이벤트 payload를 유지하면서 청크가 도착하는 대로 반복 처리하려면 `llm.stream_events(...)`를 사용하세요: + +```python +from crewai import LLM + + +llm = LLM(model="gpt-4o-mini") +stream = llm.stream_events( + messages=[ + { + "role": "user", + "content": "Explain CrewAI streaming in two short sentences.", + } + ] +) + +with stream: + for chunk in stream: + print(chunk.content, end="", flush=True) + +result = stream.result +``` + +`llm.stream_events(...)`는 감싼 호출 동안 일시적으로 streaming을 활성화하고, 이후 LLM의 이전 `stream` 설정을 복원합니다. provider 통합은 계속 기본 LLM stream 이벤트를 방출하며, 이 helper는 모든 LLM provider에서 그 이벤트 위에 공통 iterator API를 제공합니다. + +## 대화 턴 + +대화형 Flow는 `stream_turn()`으로 사용자 턴 하나를 스트리밍할 수 있습니다: + +```python +from crewai import Flow +from crewai.experimental.conversational import ConversationConfig, ConversationState + + +@ConversationConfig(llm="gpt-4o-mini", defer_trace_finalization=True) +class ChatFlow(Flow[ConversationState]): + conversational = True + + +flow = ChatFlow() +stream = flow.stream_turn("What can you help me with?", session_id="session-1") + +with stream: + for frame in stream.events: + if frame.channel == "llm" and frame.type == "llm_stream_chunk": + print(frame.content, end="", flush=True) + +reply = stream.result +``` + +`stream_turn()` 중에는 내장 대화 응답 경로가 해당 턴에 대해 LLM 토큰 스트리밍을 활성화하고 이후 LLM의 이전 `stream` 설정을 복원합니다. 자체 agent 또는 LLM 인스턴스를 만드는 사용자 지정 route handler는 토큰 단위 출력이 필요하다면 해당 LLM을 streaming으로 구성해야 합니다. + +## 정리 + +가능하면 세션을 context manager로 사용하세요. stream이 끝나기 전에 클라이언트 연결이 끊기면 세션을 명시적으로 닫으세요: + +```python +stream = flow.stream_events() + +try: + for frame in stream.events: + print(frame.type) +finally: + if not stream.is_exhausted: + stream.close() +``` + +비동기 stream에서는 `await stream.aclose()`를 사용하세요. + +## 레거시 청크 스트리밍 + +`stream=True`를 사용하는 Crew 스트리밍은 계속 [스트리밍 Crew 실행](/ko/learn/streaming-crew-execution)에 설명된 청크 중심 `CrewStreamingOutput` API를 반환합니다. 직접 `llm.call(...)` 호출도 계속 최종 LLM 결과를 반환합니다. 프레임 계약은 Flow, 직접 LLM 호출, 대화 턴, 도구, 메시지 전반에서 안정적인 이벤트 envelope가 필요한 런타임을 위한 것입니다. diff --git a/docs/v1.15.13/ko/learn/tool-hooks.mdx b/docs/v1.15.13/ko/learn/tool-hooks.mdx new file mode 100644 index 0000000000..672070cef2 --- /dev/null +++ b/docs/v1.15.13/ko/learn/tool-hooks.mdx @@ -0,0 +1,498 @@ +--- +title: 도구 호출 훅 +description: CrewAI에서 도구 실행을 가로채고, 수정하고, 제어하는 도구 호출 훅 사용 방법 배우기 +mode: "wide" +--- + +도구 호출 훅(Tool Call Hooks)은 에이전트 작업 중 도구 실행에 대한 세밀한 제어를 제공합니다. 이러한 훅을 사용하면 도구 호출을 가로채고, 입력을 수정하고, 출력을 변환하고, 안전 검사를 구현하고, 포괄적인 로깅 또는 모니터링을 추가할 수 있습니다. + +## 개요 + +도구 훅은 두 가지 중요한 시점에 실행됩니다: +- **도구 호출 전**: 입력 수정, 매개변수 검증 또는 실행 차단 +- **도구 호출 후**: 결과 변환, 출력 정제 또는 실행 세부사항 로깅 + +## 훅 타입 + +### 도구 호출 전 훅 + +모든 도구 실행 전에 실행되며, 다음을 수행할 수 있습니다: +- 도구 입력 검사 및 수정 +- 조건에 따라 도구 실행 차단 +- 위험한 작업에 대한 승인 게이트 구현 +- 매개변수 검증 +- 도구 호출 로깅 + +**시그니처:** +```python +def before_hook(context: ToolCallHookContext) -> bool | None: + # 실행을 차단하려면 False 반환 + # 실행을 허용하려면 True 또는 None 반환 + ... +``` + +### 도구 호출 후 훅 + +모든 도구 실행 후에 실행되며, 다음을 수행할 수 있습니다: +- 도구 결과 수정 또는 정제 +- 메타데이터 또는 서식 추가 +- 실행 결과 로깅 +- 결과 검증 구현 +- 출력 형식 변환 + +**시그니처:** +```python +def after_hook(context: ToolCallHookContext) -> str | None: + # 수정된 결과 문자열 반환 + # 원본 결과를 유지하려면 None 반환 + ... +``` + +## 도구 훅 컨텍스트 + +`ToolCallHookContext` 객체는 도구 실행 상태에 대한 포괄적인 액세스를 제공합니다: + +```python +class ToolCallHookContext: + tool_name: str # 호출되는 도구의 이름 + tool_input: dict[str, Any] # 변경 가능한 도구 입력 매개변수 + tool: CrewStructuredTool # 도구 인스턴스 참조 + agent: Agent | BaseAgent | None # 도구를 실행하는 에이전트 + task: Task | None # 현재 작업 + crew: Crew | None # 크루 인스턴스 + tool_result: str | None # 도구 결과 (후 훅용) +``` + +### 도구 입력 수정 + +**중요:** 항상 도구 입력을 제자리에서 수정하세요: + +```python +# ✅ 올바름 - 제자리에서 수정 +def sanitize_input(context: ToolCallHookContext) -> None: + context.tool_input['query'] = context.tool_input['query'].lower() + +# ❌ 잘못됨 - 딕셔너리 참조를 교체 +def wrong_approach(context: ToolCallHookContext) -> None: + context.tool_input = {'query': 'new query'} +``` + +## 등록 방법 + +### 1. 데코레이터 기반 등록 (권장) + +더 깔끔한 구문을 위해 데코레이터를 사용합니다: + +```python +from crewai.hooks import before_tool_call, after_tool_call + +@before_tool_call +def block_dangerous_tools(context): + """위험한 도구를 차단합니다.""" + dangerous_tools = ['delete_database', 'drop_table', 'rm_rf'] + if context.tool_name in dangerous_tools: + print(f"⛔ 위험한 도구 차단됨: {context.tool_name}") + return False # 실행 차단 + return None + +@after_tool_call +def sanitize_results(context): + """결과를 정제합니다.""" + if context.tool_result and "password" in context.tool_result.lower(): + return context.tool_result.replace("password", "[수정됨]") + return None +``` + +### 2. 크루 범위 훅 + +특정 크루 인스턴스에 대한 훅을 등록합니다: + +```python +from crewai import CrewBase +from crewai.project import crew +from crewai.hooks import before_tool_call_crew, after_tool_call_crew + +@CrewBase +class MyProjCrew: + @before_tool_call_crew + def validate_tool_inputs(self, context): + # 이 크루에만 적용됩니다 + if context.tool_name == "web_search": + if not context.tool_input.get('query'): + print("❌ 잘못된 검색 쿼리") + return False + return None + + @after_tool_call_crew + def log_tool_results(self, context): + # 크루별 도구 로깅 + print(f"✅ {context.tool_name} 완료됨") + return None + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +## 일반적인 사용 사례 + +### 1. 안전 가드레일 + +```python +@before_tool_call +def safety_check(context: ToolCallHookContext) -> bool | None: + """해를 끼칠 수 있는 도구를 차단합니다.""" + destructive_tools = [ + 'delete_file', + 'drop_table', + 'remove_user', + 'system_shutdown' + ] + + if context.tool_name in destructive_tools: + print(f"🛑 파괴적인 도구 차단됨: {context.tool_name}") + return False + + # 민감한 작업에 대해 경고 + sensitive_tools = ['send_email', 'post_to_social_media', 'charge_payment'] + if context.tool_name in sensitive_tools: + print(f"⚠️ 민감한 도구 실행 중: {context.tool_name}") + + return None +``` + +### 2. 사람의 승인 게이트 + +```python +@before_tool_call +def require_approval_for_actions(context: ToolCallHookContext) -> bool | None: + """특정 작업에 대한 승인을 요구합니다.""" + approval_required = [ + 'send_email', + 'make_purchase', + 'delete_file', + 'post_message' + ] + + if context.tool_name in approval_required: + response = context.request_human_input( + prompt=f"{context.tool_name}을(를) 승인하시겠습니까?", + default_message=f"입력: {context.tool_input}\n승인하려면 'yes'를 입력하세요:" + ) + + if response.lower() != 'yes': + print(f"❌ 도구 실행 거부됨: {context.tool_name}") + return False + + return None +``` + +### 3. 입력 검증 및 정제 + +```python +@before_tool_call +def validate_and_sanitize_inputs(context: ToolCallHookContext) -> bool | None: + """입력을 검증하고 정제합니다.""" + # 검색 쿼리 검증 + if context.tool_name == 'web_search': + query = context.tool_input.get('query', '') + if len(query) < 3: + print("❌ 검색 쿼리가 너무 짧습니다") + return False + + # 쿼리 정제 + context.tool_input['query'] = query.strip().lower() + + # 파일 경로 검증 + if context.tool_name == 'read_file': + path = context.tool_input.get('path', '') + if '..' in path or path.startswith('/'): + print("❌ 잘못된 파일 경로") + return False + + return None +``` + +### 4. 결과 정제 + +```python +@after_tool_call +def sanitize_sensitive_data(context: ToolCallHookContext) -> str | None: + """민감한 데이터를 정제합니다.""" + if not context.tool_result: + return None + + import re + result = context.tool_result + + # API 키 제거 + result = re.sub( + r'(api[_-]?key|token)["\']?\s*[:=]\s*["\']?[\w-]+', + r'\1: [수정됨]', + result, + flags=re.IGNORECASE + ) + + # 이메일 주소 제거 + result = re.sub( + r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', + '[이메일-수정됨]', + result + ) + + # 신용카드 번호 제거 + result = re.sub( + r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', + '[카드-수정됨]', + result + ) + + return result +``` + +### 5. 도구 사용 분석 + +```python +import time +from collections import defaultdict + +tool_stats = defaultdict(lambda: {'count': 0, 'total_time': 0, 'failures': 0}) + +@before_tool_call +def start_timer(context: ToolCallHookContext) -> None: + context.tool_input['_start_time'] = time.time() + return None + +@after_tool_call +def track_tool_usage(context: ToolCallHookContext) -> None: + start_time = context.tool_input.get('_start_time', time.time()) + duration = time.time() - start_time + + tool_stats[context.tool_name]['count'] += 1 + tool_stats[context.tool_name]['total_time'] += duration + + if not context.tool_result or 'error' in context.tool_result.lower(): + tool_stats[context.tool_name]['failures'] += 1 + + print(f""" + 📊 {context.tool_name} 도구 통계: + - 실행 횟수: {tool_stats[context.tool_name]['count']} + - 평균 시간: {tool_stats[context.tool_name]['total_time'] / tool_stats[context.tool_name]['count']:.2f}초 + - 실패: {tool_stats[context.tool_name]['failures']} + """) + + return None +``` + +### 6. 속도 제한 + +```python +from collections import defaultdict +from datetime import datetime, timedelta + +tool_call_history = defaultdict(list) + +@before_tool_call +def rate_limit_tools(context: ToolCallHookContext) -> bool | None: + """도구 호출 속도를 제한합니다.""" + tool_name = context.tool_name + now = datetime.now() + + # 오래된 항목 정리 (1분 이상 된 것) + tool_call_history[tool_name] = [ + call_time for call_time in tool_call_history[tool_name] + if now - call_time < timedelta(minutes=1) + ] + + # 속도 제한 확인 (분당 최대 10회 호출) + if len(tool_call_history[tool_name]) >= 10: + print(f"🚫 {tool_name}에 대한 속도 제한 초과") + return False + + # 이 호출 기록 + tool_call_history[tool_name].append(now) + return None +``` + +### 7. 디버그 로깅 + +```python +@before_tool_call +def debug_tool_call(context: ToolCallHookContext) -> None: + """도구 호출을 디버그합니다.""" + print(f""" + 🔍 도구 호출 디버그: + - 도구: {context.tool_name} + - 에이전트: {context.agent.role if context.agent else '알 수 없음'} + - 작업: {context.task.description[:50] if context.task else '알 수 없음'}... + - 입력: {context.tool_input} + """) + return None + +@after_tool_call +def debug_tool_result(context: ToolCallHookContext) -> None: + """도구 결과를 디버그합니다.""" + if context.tool_result: + result_preview = context.tool_result[:200] + print(f"✅ 결과 미리보기: {result_preview}...") + else: + print("⚠️ 반환된 결과 없음") + return None +``` + +## 훅 관리 + +### 훅 등록 해제 + +```python +from crewai.hooks import ( + unregister_before_tool_call_hook, + unregister_after_tool_call_hook +) + +# 특정 훅 등록 해제 +def my_hook(context): + ... + +register_before_tool_call_hook(my_hook) +# 나중에... +success = unregister_before_tool_call_hook(my_hook) +print(f"등록 해제됨: {success}") +``` + +### 훅 지우기 + +```python +from crewai.hooks import ( + clear_before_tool_call_hooks, + clear_after_tool_call_hooks, + clear_all_tool_call_hooks +) + +# 특정 훅 타입 지우기 +count = clear_before_tool_call_hooks() +print(f"{count}개의 전(before) 훅이 지워졌습니다") + +# 모든 도구 훅 지우기 +before_count, after_count = clear_all_tool_call_hooks() +print(f"{before_count}개의 전(before) 훅과 {after_count}개의 후(after) 훅이 지워졌습니다") +``` + +## 고급 패턴 + +### 조건부 훅 실행 + +```python +@before_tool_call +def conditional_blocking(context: ToolCallHookContext) -> bool | None: + """특정 조건에서만 차단합니다.""" + # 특정 에이전트에 대해서만 차단 + if context.agent and context.agent.role == "junior_agent": + if context.tool_name in ['delete_file', 'send_email']: + print(f"❌ 주니어 에이전트는 {context.tool_name}을(를) 사용할 수 없습니다") + return False + + # 특정 작업 중에만 차단 + if context.task and "민감한" in context.task.description.lower(): + if context.tool_name == 'web_search': + print("❌ 민감한 작업에서는 웹 검색이 차단됩니다") + return False + + return None +``` + +### 컨텍스트 인식 입력 수정 + +```python +@before_tool_call +def enhance_tool_inputs(context: ToolCallHookContext) -> None: + """에이전트 역할에 따라 컨텍스트를 추가합니다.""" + # 에이전트 역할에 따라 컨텍스트 추가 + if context.agent and context.agent.role == "researcher": + if context.tool_name == 'web_search': + # 연구원에 대한 도메인 제한 추가 + context.tool_input['domains'] = ['edu', 'gov', 'org'] + + # 작업에 따라 컨텍스트 추가 + if context.task and "긴급" in context.task.description.lower(): + if context.tool_name == 'send_email': + context.tool_input['priority'] = 'high' + + return None +``` + +## 모범 사례 + +1. **훅을 집중적으로 유지**: 각 훅은 단일 책임을 가져야 합니다 +2. **무거운 계산 피하기**: 훅은 모든 도구 호출마다 실행됩니다 +3. **오류를 우아하게 처리**: try-except를 사용하여 훅 실패 방지 +4. **타입 힌트 사용**: 더 나은 IDE 지원을 위해 `ToolCallHookContext` 활용 +5. **차단 조건 문서화**: 도구가 차단되는 시기/이유를 명확히 하세요 +6. **훅을 독립적으로 테스트**: 프로덕션에서 사용하기 전에 단위 테스트 +7. **테스트에서 훅 지우기**: 테스트 실행 간 `clear_all_tool_call_hooks()` 사용 +8. **제자리에서 수정**: 항상 `context.tool_input`을 제자리에서 수정하고 교체하지 마세요 +9. **중요한 결정 로깅**: 특히 도구 실행을 차단할 때 +10. **성능 고려**: 가능한 경우 비용이 많이 드는 검증을 캐시 + +## 오류 처리 + +```python +@before_tool_call +def safe_validation(context: ToolCallHookContext) -> bool | None: + try: + # 검증 로직 + if not validate_input(context.tool_input): + return False + except Exception as e: + print(f"⚠️ 훅 오류: {e}") + # 결정: 오류 발생 시 허용 또는 차단 + return None # 오류에도 불구하고 실행 허용 +``` + +## 타입 안전성 + +```python +from crewai.hooks import ToolCallHookContext, BeforeToolCallHookType, AfterToolCallHookType + +# 명시적 타입 주석 +def my_before_hook(context: ToolCallHookContext) -> bool | None: + return None + +def my_after_hook(context: ToolCallHookContext) -> str | None: + return None + +# 타입 안전 등록 +register_before_tool_call_hook(my_before_hook) +register_after_tool_call_hook(my_after_hook) +``` + +## 문제 해결 + +### 훅이 실행되지 않음 +- 크루 실행 전에 훅이 등록되었는지 확인 +- 이전 훅이 `False`를 반환했는지 확인 (실행 및 후속 훅 차단) +- 훅 시그니처가 예상 타입과 일치하는지 확인 + +### 입력 수정이 작동하지 않음 +- 제자리 수정 사용: `context.tool_input['key'] = value` +- 딕셔너리를 교체하지 마세요: `context.tool_input = {}` + +### 결과 수정이 작동하지 않음 +- 후 훅에서 수정된 문자열을 반환 +- `None`을 반환하면 원본 결과가 유지됩니다 +- 도구가 실제로 결과를 반환했는지 확인 + +### 도구가 예기치 않게 차단됨 +- 차단 조건에 대한 모든 전(before) 훅 확인 +- 훅 실행 순서 확인 +- 어떤 훅이 차단하는지 식별하기 위해 디버그 로깅 추가 + +## 결론 + +도구 호출 훅은 CrewAI에서 도구 실행을 제어하고 모니터링하는 강력한 기능을 제공합니다. 이를 사용하여 안전 가드레일, 승인 게이트, 입력 검증, 결과 정제, 로깅 및 분석을 구현하세요. 적절한 오류 처리 및 타입 안전성과 결합하면, 훅을 통해 포괄적인 관찰성을 갖춘 안전하고 프로덕션 준비가 된 에이전트 시스템을 구축할 수 있습니다. + diff --git a/docs/v1.15.13/ko/learn/using-annotations.mdx b/docs/v1.15.13/ko/learn/using-annotations.mdx new file mode 100644 index 0000000000..e397a5b9b2 --- /dev/null +++ b/docs/v1.15.13/ko/learn/using-annotations.mdx @@ -0,0 +1,155 @@ +--- +title: "crew.py에서 어노테이션 사용하기" +description: "CrewAI에서 에이전트, 태스크, 컴포넌트를 올바르게 구조화하기 위해 어노테이션을 사용하는 방법을 알아보세요." +icon: "at" +mode: "wide" +--- + +이 가이드는 클래식 `crew.py` 파일에서 **agent**, **task**, 및 기타 구성 요소를 올바르게 참조하기 위해 어노테이션을 사용하는 방법을 설명합니다. + + +`crewai create crew `으로 만든 새 프로젝트는 JSON-first이며 `crew.jsonc`와 `agents/*.jsonc`를 사용합니다. 이 가이드는 `crewai create crew --classic`으로 만든 클래식 프로젝트, 기존 Python/YAML 프로젝트 마이그레이션, 또는 Python 데코레이터 제어가 필요한 경우에 사용하세요. + + +## 소개 + +CrewAI 프레임워크에서 어노테이션은 클래스와 메소드를 데코레이트하는 데 사용되며, crew의 다양한 컴포넌트에 메타데이터와 기능을 제공합니다. 클래식 Python/YAML 프로젝트에서는 `config/agents.yaml`, `config/tasks.yaml`을 로드하고 `Crew` 객체를 반환하는 코드를 구조화합니다. + +## 사용 가능한 어노테이션 + +CrewAI 프레임워크는 다음과 같은 어노테이션을 제공합니다: + +- `@CrewBase`: 메인 crew 클래스를 데코레이트할 때 사용합니다. +- `@agent`: Agent 객체를 정의하고 반환하는 메서드를 데코레이트합니다. +- `@task`: Task 객체를 정의하고 반환하는 메서드를 데코레이트합니다. +- `@crew`: Crew 객체를 생성하고 반환하는 메서드를 데코레이트합니다. +- `@llm`: Language Model 객체를 초기화하고 반환하는 메서드를 데코레이트합니다. +- `@tool`: Tool 객체를 초기화하고 반환하는 메서드를 데코레이트합니다. +- `@callback`: 콜백 메서드를 정의할 때 사용합니다. +- `@output_json`: JSON 데이터를 출력하는 메서드에 사용합니다. +- `@output_pydantic`: Pydantic 모델을 출력하는 메서드에 사용합니다. +- `@cache_handler`: 캐시 처리 메서드를 정의할 때 사용합니다. + +## 사용 예시 + +이러한 주석을 어떻게 사용하는지 예제를 통해 살펴보겠습니다: + +### 1. Crew Base 클래스 + +```python +@CrewBase +class LinkedinProfileCrew(): + """LinkedinProfile crew""" + agents_config = 'config/agents.yaml' + tasks_config = 'config/tasks.yaml' +``` + +`@CrewBase` 어노테이션은 메인 crew 클래스를 데코레이트하는 데 사용됩니다. 이 클래스는 일반적으로 agent, task, 그리고 crew 자체를 생성하기 위한 구성과 메서드를 포함합니다. + + +`@CrewBase`는 단순히 클래스를 등록하는 것 이상을 처리합니다. + +- **구성 부트스트래핑:** 클래스 파일과 동일한 경로에서 `agents_config`와 `tasks_config`(기본값은 각각 `config/agents.yaml`, `config/tasks.yaml`)을 찾아 인스턴스화 시점에 불러오며, 파일이 없으면 빈 딕셔너리로 안전하게 대체합니다. +- **데코레이터 오케스트레이션:** `@agent`, `@task`, `@before_kickoff`, `@after_kickoff`로 표시된 메서드를 메모이즈하여 crew마다 한 번만 인스턴스화하고 선언 순서를 보장합니다. +- **후크 연결:** 보존된 킥오프 훅을 `@crew` 메서드가 반환하는 `Crew` 객체에 자동으로 연결하여 `.kickoff()` 호출 전후에 실행되도록 합니다. +- **MCP 연동:** 클래스에 `mcp_server_params`가 정의되어 있으면 `get_mcp_tools()`가 MCP 서버 어댑터를 지연 생성해 도구를 로드하고, 내부 after-kickoff 훅이 킥오프 종료 후 어댑터를 정리합니다. 어댑터 구성 방법은 [MCP 개요](/ko/mcp/overview)를 참고하세요. + + +### 2. 도구 정의 + +```python +@tool +def myLinkedInProfileTool(self): + return LinkedInProfileTool() +``` + +`@tool` 애너테이션은 도구 객체를 반환하는 메서드를 데코레이터할 때 사용됩니다. 이러한 도구들은 에이전트가 특정 작업을 수행할 때 사용할 수 있습니다. + +### 3. LLM 정의 + +```python +@llm +def groq_llm(self): + api_key = os.getenv('api_key') + return ChatGroq(api_key=api_key, temperature=0, model_name="mixtral-8x7b-32768") +``` + +`@llm` 애노테이션은 Language Model 객체를 초기화하고 반환하는 메서드를 데코레이팅하는 데 사용됩니다. 이러한 LLM은 에이전트가 자연어 처리 작업을 수행할 때 사용됩니다. + +### 4. 에이전트 정의 + +```python +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'] + ) +``` + +`@agent` 어노테이션은 에이전트 객체를 정의하고 반환하는 메서드를 데코레이트할 때 사용됩니다. + +### 5. Task 정의 + +```python +@task +def research_task(self) -> Task: + return Task( + config=self.tasks_config['research_linkedin_task'], + agent=self.researcher() + ) +``` + +`@task` 어노테이션은 Task 객체를 정의하고 반환하는 메서드를 데코레이트하는 데 사용됩니다. 이러한 메서드는 task 구성과 해당 task를 담당하는 agent를 지정합니다. + +### 6. Crew 생성 + +```python +@crew +def crew(self) -> Crew: + """Creates the LinkedinProfile crew""" + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +`@crew` 어노테이션은 `Crew` 객체를 생성하고 반환하는 메서드를 데코레이션하는 데 사용됩니다. 이 메서드는 모든 구성 요소(agents와 tasks)를 기능적인 crew로 조합합니다. + +## 클래식 YAML 구성 + +클래식 프로젝트에서 에이전트 구성은 일반적으로 YAML 파일에 저장됩니다. 아래는 연구원 에이전트에 대한 `agents.yaml` 파일 예시입니다. + +```yaml +researcher: + role: > + LinkedIn Profile Senior Data Researcher + goal: > + Uncover detailed LinkedIn profiles based on provided name {name} and domain {domain} + Generate a Dall-E image based on domain {domain} + backstory: > + You're a seasoned researcher with a knack for uncovering the most relevant LinkedIn profiles. + Known for your ability to navigate LinkedIn efficiently, you excel at gathering and presenting + professional information clearly and concisely. + allow_delegation: False + verbose: True + llm: groq_llm + tools: + - myLinkedInProfileTool + - mySerperDevTool + - myDallETool +``` + +이 YAML 구성은 `LinkedinProfileCrew` 클래스에 정의된 연구원 에이전트에 해당합니다. 구성에는 에이전트의 역할, 목표, 배경 이야기와 사용하는 LLM 및 도구와 같은 기타 속성이 명시되어 있습니다. + +YAML 파일의 `llm`과 `tools`가 Python 클래스에서 `@llm` 및 `@tool`로 데코레이션된 메서드와 어떻게 대응되는지 주목하세요. + +## 모범 사례 + +- **일관성 있는 명명**: 메서드에 대해 명확하고 일관성 있는 명명 규칙을 사용하세요. 예를 들어, agent 메서드는 역할에 따라 이름을 지정할 수 있습니다(예: researcher, reporting_analyst). +- **환경 변수**: API 키와 같은 민감한 정보를 위해 환경 변수를 사용하세요. +- **유연성**: agent와 task를 쉽게 추가 및 제거할 수 있도록 crew를 유연하게 설계하세요. +- **YAML-코드 일치**: 클래식 프로젝트에서는 YAML 파일의 이름과 구조가 Python 코드의 데코레이터가 적용된 메서드와 정확히 일치하는지 확인하세요. + +이 지침을 따르고 어노테이션을 올바르게 사용하면 클래식 crew를 구조적이고 유지보수하기 쉽게 유지할 수 있습니다. 새 crew에는 [Crews](/ko/concepts/crews)의 JSON-first 구조를 권장합니다. diff --git a/docs/v1.15.13/ko/mcp/dsl-integration.mdx b/docs/v1.15.13/ko/mcp/dsl-integration.mdx new file mode 100644 index 0000000000..33eb6f81ea --- /dev/null +++ b/docs/v1.15.13/ko/mcp/dsl-integration.mdx @@ -0,0 +1,234 @@ +--- +title: MCP DSL 통합 +description: CrewAI의 간단한 DSL 구문을 사용하여 mcps 필드로 MCP 서버를 에이전트와 직접 통합하는 방법을 알아보세요. +icon: code +mode: "wide" +--- + +## 개요 + +CrewAI의 MCP DSL(Domain Specific Language) 통합은 에이전트를 MCP(Model Context Protocol) 서버에 연결하는 **가장 간단한 방법**을 제공합니다. 에이전트에 `mcps` 필드만 추가하면 CrewAI가 모든 복잡성을 자동으로 처리합니다. + + + 이는 대부분의 MCP 사용 사례에 **권장되는 접근 방식**입니다. 수동 연결 관리가 + 필요한 고급 시나리오의 경우 + [MCPServerAdapter](/ko/mcp/overview#advanced-mcpserveradapter)를 참조하세요. + + +## 기본 사용법 + +`mcps` 필드를 사용하여 에이전트에 MCP 서버를 추가하세요: + +```python +from crewai import Agent + +agent = Agent( + role="연구 보조원", + goal="연구 및 분석 업무 지원", + backstory="고급 연구 도구에 접근할 수 있는 전문가 보조원", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=your_key&profile=research" + ] +) + +# MCP 도구들이 이제 자동으로 사용 가능합니다! +# 수동 연결 관리나 도구 구성이 필요 없습니다 +``` + +## 지원되는 참조 형식 + +### 외부 MCP 원격 서버 + +```python +# 기본 HTTPS 서버 +"https://api.example.com/mcp" + +# 인증이 포함된 서버 +"https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile" + +# 사용자 정의 경로가 있는 서버 +"https://services.company.com/api/v1/mcp" +``` + +### 특정 도구 선택 + +`#` 구문을 사용하여 서버에서 특정 도구를 선택하세요: + +```python +# 날씨 서버에서 예보 도구만 가져오기 +"https://weather.api.com/mcp#get_forecast" + +# Exa에서 검색 도구만 가져오기 +"https://mcp.exa.ai/mcp?api_key=your_key#web_search_exa" +``` + +### 연결된 MCP 통합 + +CrewAI 카탈로그에서 MCP 서버를 연결하거나 직접 가져올 수 있습니다. 계정에 연결한 후 슬러그로 참조하세요: + +```python +# 모든 도구가 포함된 연결된 MCP +"snowflake" + +# 연결된 MCP의 특정 도구 +"stripe#list_invoices" + +# 여러 연결된 MCP +mcps=[ + "snowflake", + "stripe", + "github" +] +``` + +## 완전한 예제 + +다음은 여러 MCP 서버를 사용하는 완전한 예제입니다: + +```python +from crewai import Agent, Task, Crew, Process + +# 다중 MCP 소스를 가진 에이전트 생성 +multi_source_agent = Agent( + role="다중 소스 연구 분석가", + goal="다중 데이터 소스를 사용한 종합적인 연구 수행", + backstory="""웹 검색, 날씨 데이터, 금융 정보, + 학술 연구 도구에 접근할 수 있는 전문가 연구원""", + mcps=[ + # 외부 MCP 서버 + "https://mcp.exa.ai/mcp?api_key=your_exa_key&profile=research", + "https://weather.api.com/mcp#get_current_conditions", + + # 카탈로그에서 연결된 MCP + "snowflake", + "stripe#list_invoices", + "github#search_repositories" + ] +) + +# 종합적인 연구 작업 생성 +research_task = Task( + description="""AI 에이전트가 비즈니스 생산성에 미치는 영향을 연구하세요. + 원격 근무에 대한 현재 날씨 영향, 금융 시장 트렌드, + AI 에이전트 프레임워크에 대한 최근 학술 발표를 포함하세요.""", + expected_output="""다음을 다루는 종합 보고서: + 1. AI 에이전트 비즈니스 영향 분석 + 2. 원격 근무를 위한 날씨 고려사항 + 3. AI 관련 금융 시장 트렌드 + 4. 학술 연구 인용 및 통찰 + 5. 경쟁 환경 분석""", + agent=multi_source_agent +) + +# crew 생성 및 실행 +research_crew = Crew( + agents=[multi_source_agent], + tasks=[research_task], + process=Process.sequential, + verbose=True +) + +result = research_crew.kickoff() +print(f"{len(multi_source_agent.mcps)}개의 MCP 데이터 소스로 연구 완료") +``` + +## 주요 기능 + +- 🔄 **자동 도구 발견**: 도구들이 자동으로 발견되고 통합됩니다 +- 🏷️ **이름 충돌 방지**: 서버 이름이 도구 이름에 접두사로 붙습니다 +- ⚡ **성능 최적화**: 스키마 캐싱과 온디맨드 연결 +- 🛡️ **오류 복원력**: 사용할 수 없는 서버의 우아한 처리 +- ⏱️ **타임아웃 보호**: 내장 타임아웃으로 연결 중단 방지 +- 📊 **투명한 통합**: 기존 CrewAI 기능과 완벽한 연동 + +## 오류 처리 + +MCP DSL 통합은 복원력 있게 설계되었습니다: + +```python +agent = Agent( + role="복원력 있는 에이전트", + goal="서버 문제에도 불구하고 작업 계속", + backstory="장애를 우아하게 처리하는 에이전트", + mcps=[ + "https://reliable-server.com/mcp", # 작동할 것 + "https://unreachable-server.com/mcp", # 우아하게 건너뛸 것 + "https://slow-server.com/mcp", # 우아하게 타임아웃될 것 + "snowflake" # 카탈로그에서 연결된 MCP + ] +) +# 에이전트는 작동하는 서버의 도구를 사용하고 실패한 서버에 대한 경고를 로그에 남깁니다 +``` + +## 성능 기능 + +### 자동 캐싱 + +도구 스키마는 성능 향상을 위해 5분간 캐시됩니다: + +```python +# 첫 번째 에이전트 생성 - 서버에서 도구 발견 +agent1 = Agent(role="첫 번째", goal="테스트", backstory="테스트", + mcps=["https://api.example.com/mcp"]) + +# 두 번째 에이전트 생성 (5분 이내) - 캐시된 도구 스키마 사용 +agent2 = Agent(role="두 번째", goal="테스트", backstory="테스트", + mcps=["https://api.example.com/mcp"]) # 훨씬 빠릅니다! +``` + +### 온디맨드 연결 + +도구 연결은 실제로 사용될 때만 설정됩니다: + +```python +# 에이전트 생성은 빠름 - 아직 MCP 연결을 만들지 않음 +agent = Agent( + role="온디맨드 에이전트", + goal="도구를 효율적으로 사용", + backstory="필요할 때만 연결하는 효율적인 에이전트", + mcps=["https://api.example.com/mcp"] +) + +# MCP 연결은 도구가 실제로 실행될 때만 만들어집니다 +# 이는 연결 오버헤드를 최소화하고 시작 성능을 개선합니다 +``` + +## 모범 사례 + +### 1. 가능하면 특정 도구 사용 + +```python +# 좋음 - 필요한 도구만 가져오기 +mcps=["https://weather.api.com/mcp#get_forecast"] + +# 덜 효율적 - 서버의 모든 도구 가져오기 +mcps=["https://weather.api.com/mcp"] +``` + +### 2. 인증을 안전하게 처리 + +```python +import os + +# 환경 변수에 API 키 저장 +exa_key = os.getenv("EXA_API_KEY") +exa_profile = os.getenv("EXA_PROFILE") + +agent = Agent( + role="안전한 에이전트", + goal="MCP 도구를 안전하게 사용", + backstory="보안을 고려하는 에이전트", + mcps=[f"https://mcp.exa.ai/mcp?api_key={exa_key}&profile={exa_profile}"] +) +``` + +### 3. 서버 장애 계획 + +```python +# 항상 백업 옵션 포함 +mcps=[ + "https://primary-api.com/mcp", # 주요 선택 + "https://backup-api.com/mcp", # 백업 옵션 + "snowflake" # 연결된 MCP 폴백 +] +``` diff --git a/docs/v1.15.13/ko/mcp/multiple-servers.mdx b/docs/v1.15.13/ko/mcp/multiple-servers.mdx new file mode 100644 index 0000000000..dfd85a7f70 --- /dev/null +++ b/docs/v1.15.13/ko/mcp/multiple-servers.mdx @@ -0,0 +1,65 @@ +--- +title: 여러 MCP 서버에 연결하기 +description: CrewAI에서 MCPServerAdapter를 사용하여 여러 MCP 서버에 동시에 연결하고 해당 도구를 집계하는 방법을 알아봅니다. +icon: layer-group +mode: "wide" +--- + +## 개요 + +`crewai-tools`의 `MCPServerAdapter`는 여러 MCP 서버에 동시에 연결할 수 있게 해줍니다. 이는 에이전트가 서로 다른 서비스나 환경에 분산된 도구에 접근해야 할 때 유용합니다. 어댑터는 지정된 모든 서버에서 도구를 집계하여 CrewAI 에이전트가 사용할 수 있게 합니다. + +## 구성 + +여러 서버에 연결하려면 서버 파라미터 딕셔너리의 리스트를 `MCPServerAdapter`에 제공합니다. 리스트에 있는 각 딕셔너리는 하나의 MCP 서버에 대한 파라미터를 정의해야 합니다. + +각 서버에 대해 지원되는 transport 타입은 `stdio`, `sse`, 그리고 `streamable-http`입니다. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters # Needed for Stdio example + +# 여러 MCP 서버의 파라미터 정의 +server_params_list = [ + # Streamable HTTP 서버 + { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" + }, + # SSE 서버 + { + "url": "http://localhost:8000/sse", + "transport": "sse" + }, + # StdIO 서버 + StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, + ) +] + +try: + with MCPServerAdapter(server_params_list) as aggregated_tools: + print(f"Available aggregated tools: {[tool.name for tool in aggregated_tools]}") + + multi_server_agent = Agent( + role="Versatile Assistant", + goal="Utilize tools from local Stdio, remote SSE, and remote HTTP MCP servers.", + backstory="An AI agent capable of leveraging a diverse set of tools from multiple sources.", + tools=aggregated_tools, # All tools are available here + verbose=True, + ) + + ... # Your other agent, tasks, and crew code here + +except Exception as e: + print(f"Error connecting to or using multiple MCP servers (Managed): {e}") + print("Ensure all MCP servers are running and accessible with correct configurations.") + +``` + +## 연결 관리 + +컨텍스트 매니저(`with` 문)를 사용할 때, `MCPServerAdapter`는 구성된 MCP 서버와의 모든 연결의 라이프사이클(시작 및 종료)을 관리합니다. 이를 통해 리소스 관리를 단순화하고, 컨텍스트를 종료할 때 모든 연결이 적절하게 닫히도록 보장할 수 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/mcp/overview.mdx b/docs/v1.15.13/ko/mcp/overview.mdx new file mode 100644 index 0000000000..22687080b4 --- /dev/null +++ b/docs/v1.15.13/ko/mcp/overview.mdx @@ -0,0 +1,341 @@ +--- +title: "CrewAI에서 MCP 서버를 도구로 활용하기" +description: "`crewai-tools` 라이브러리를 사용하여 MCP 서버를 CrewAI agent에 도구로 통합하는 방법을 알아봅니다." +icon: plug +mode: "wide" +--- + +## 개요 + +[Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP)는 AI 에이전트가 MCP 서버로 알려진 외부 서비스와 통신함으로써 LLM에 컨텍스트를 제공할 수 있도록 표준화된 방식을 제공합니다. + +CrewAI는 MCP 통합을 위한 **두 가지 접근 방식**을 제공합니다: + +### 🚀 **새로운 기능: 간단한 DSL 통합** (권장) + +에이전트에 `mcps` 필드를 직접 사용하여 완벽한 MCP 도구 통합을 구현하세요: + +```python +from crewai import Agent + +agent = Agent( + role="연구 분석가", + goal="정보를 연구하고 분석", + backstory="외부 도구에 접근할 수 있는 전문가 연구원", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=your_key", # 외부 MCP 서버 + "https://api.weather.com/mcp#get_forecast", # 서버의 특정 도구 + "snowflake", # 카탈로그에서 연결된 MCP + "stripe#list_invoices" # 연결된 MCP의 특정 도구 + ] +) +# MCP 도구들이 이제 자동으로 에이전트에서 사용 가능합니다! +``` + +### 🔧 **고급: MCPServerAdapter** (복잡한 시나리오용) + +수동 연결 관리가 필요한 고급 사용 사례의 경우 `crewai-tools` 라이브러리는 `MCPServerAdapter` 클래스를 제공합니다. + +현재 다음과 같은 전송 메커니즘을 지원합니다: + +- **HTTPS**: 원격 서버용 (HTTPS를 통한 보안 통신) +- **Server-Sent Events (SSE)**: 원격 서버용 (서버에서 클라이언트로의 일방향, 실시간 데이터 스트리밍, HTTP 기반) +- **Streamable HTTP**: 원격 서버용 (유연하며 잠재적으로 양방향 통신이 가능, 주로 SSE를 활용한 서버-클라이언트 스트림 제공, HTTP 기반) + +## 비디오 튜토리얼 + +CrewAI와 MCP 통합에 대한 종합적인 안내를 위해 이 비디오 튜토리얼을 시청하세요: + + + +## 설치 + +`crewai-tools`와 함께 MCP를 사용하기 전에, 아래 명령어를 통해 `mcp` 추가 `crewai-tools` 종속성을 설치해야 합니다: + +```shell +uv pip install 'crewai-tools[mcp]' +``` + +## 주요 개념 및 시작하기 + +`crewai-tools`의 `MCPServerAdapter` 클래스는 MCP 서버에 연결하고 해당 도구들을 CrewAI 에이전트에서 사용할 수 있도록 하는 기본 방법입니다. 다양한 전송 메커니즘을 지원하며 연결 관리를 간소화합니다. + +파이썬 컨텍스트 매니저(`with` 문)를 사용하는 것이 `MCPServerAdapter`를 위한 **권장 방법**입니다. 이를 통해 MCP 서버와의 연결 시작 및 종료가 자동으로 처리됩니다. + +## 연결 구성 + +`MCPServerAdapter`는 연결 동작을 맞춤화할 수 있는 여러 구성 옵션을 지원합니다: + +- **`connect_timeout`** (선택 사항): MCP 서버에 연결을 설정하기 위해 대기할 최대 시간(초 단위)입니다. 명시하지 않으면 기본값은 30초입니다. 응답 시간이 가변적인 원격 서버에 특히 유용합니다. + +```python +# 사용자 지정 연결 타임아웃 예시 +with MCPServerAdapter(server_params, connect_timeout=60) as tools: + # 60초 이내에 연결이 설정되지 않으면 타임아웃 발생 + pass +``` + +```python +from crewai import Agent +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters # Stdio 서버용 + +# 예시 server_params (서버 유형에 따라 하나 선택): +# 1. Stdio 서버: +server_params=StdioServerParameters( + command="python3", + args=["servers/your_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +# 2. SSE 서버: +server_params = { + "url": "http://localhost:8000/sse", + "transport": "sse" +} + +# 3. 스트림 가능 HTTP 서버: +server_params = { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" +} + +# 예시 사용법 (server_params 설정 후 주석 해제 및 적용): +with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="MCP 서버의 도구를 활용합니다.", + backstory="나는 MCP 서버에 연결하여 해당 도구를 사용할 수 있습니다.", + tools=mcp_tools, # 불러온 도구를 Agent에 전달 + reasoning=True, + verbose=True + ) + # ... 나머지 crew 설정 ... +``` + +이 일반적인 패턴은 도구를 통합하는 방법을 보여줍니다. 각 transport에 맞춘 구체적인 예시는 아래의 상세 가이드를 참고하세요. + +## 필터링 도구 + +도구를 필터링하는 방법에는 두 가지가 있습니다: + +1. 딕셔너리 스타일의 인덱싱을 사용하여 특정 도구에 접근하기. +2. 도구 이름 목록을 `MCPServerAdapter` 생성자에 전달하기. + +### 딕셔너리 스타일 인덱싱을 사용하여 특정 도구에 접근하기 + +```python +with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="Utilize tools from an MCP server.", + backstory="I can connect to MCP servers and use their tools.", + tools=[mcp_tools["tool_name"]], # Pass the loaded tools to your agent + reasoning=True, + verbose=True + ) + # ... rest of your crew setup ... +``` + +### `MCPServerAdapter` 생성자에 도구 이름의 리스트를 전달하세요. + +```python +with MCPServerAdapter(server_params, "tool_name", connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + my_agent = Agent( + role="MCP Tool User", + goal="Utilize tools from an MCP server.", + backstory="I can connect to MCP servers and use their tools.", + tools=mcp_tools, # Pass the loaded tools to your agent + reasoning=True, + verbose=True + ) + # ... rest of your crew setup ... +``` + +## CrewBase와 함께 사용하기 + +CrewBase 클래스 내에서 MCPServer 도구를 사용하려면 `get_mcp_tools` 메서드를 사용하세요. 서버 구성은 `mcp_server_params` 속성을 통해 제공되어야 합니다. 단일 구성 또는 여러 서버 구성을 리스트 형태로 전달할 수 있습니다. + +```python +@CrewBase +class CrewWithMCP: + # ... 에이전트 및 작업 구성 파일 정의 ... + + mcp_server_params = [ + # 스트리머블 HTTP 서버 + { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" + }, + # SSE 서버 + { + "url": "http://localhost:8000/sse", + "transport": "sse" + }, + # StdIO 서버 + StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, + ) + ] + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) # 모든 사용 가능한 도구 가져오기 + + # ... 나머지 crew 설정 ... +``` + + +`@CrewBase`로 데코레이션된 클래스에서는 어댑터 수명 주기가 자동으로 관리됩니다. + +- `get_mcp_tools()`가 처음 호출될 때 공유 `MCPServerAdapter`가 지연 생성되며 crew 내 모든 에이전트가 이를 재사용합니다. +- `.kickoff()`가 끝나면 `@CrewBase`가 주입한 after-kickoff 훅이 어댑터를 종료하므로 별도의 정리 코드가 필요 없습니다. +- `mcp_server_params`를 지정하지 않으면 `get_mcp_tools()`는 빈 리스트를 반환하여 MCP 설정 여부와 상관없이 동일한 코드 경로를 사용할 수 있습니다. + +따라서 여러 에이전트에서 `get_mcp_tools()`를 호출하거나 환경에 따라 MCP 사용을 토글하더라도 안전하게 동작합니다. + + + +### 연결 타임아웃 구성 + +`mcp_connect_timeout` 클래스 속성을 설정하여 MCP 서버의 연결 타임아웃을 구성할 수 있습니다. 타임아웃을 지정하지 않으면 기본값으로 30초가 사용됩니다. + +```python +@CrewBase +class CrewWithMCP: + mcp_server_params = [...] + mcp_connect_timeout = 60 # 모든 MCP 연결에 60초 타임아웃 + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) +``` + +```python +@CrewBase +class CrewWithDefaultTimeout: + mcp_server_params = [...] + # mcp_connect_timeout 지정하지 않음 - 기본 30초 사용 + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) +``` + +### 도구 필터링 + +`get_mcp_tools` 메서드에 도구 이름의 리스트를 전달하여, 에이전트에 제공되는 도구를 필터링할 수 있습니다. + +```python +@agent +def another_agent(self): + return Agent( + config=self.agents_config["your_agent"], + tools=self.get_mcp_tools("tool_1", "tool_2") # 특정 도구만 가져오기 + ) +``` + +타임아웃 구성은 crew 내의 모든 MCP 도구 호출에 적용됩니다: + +```python +@CrewBase +class CrewWithCustomTimeout: + mcp_server_params = [...] + mcp_connect_timeout = 90 # 모든 MCP 연결에 90초 타임아웃 + + @agent + def filtered_agent(self): + return Agent( + config=self.agents_config["your_agent"], + tools=self.get_mcp_tools("tool_1", "tool_2") # 사용자 지정 타임아웃으로 특정 도구 + ) +``` + +## MCP 통합 탐색 + + + + 표준 입력/출력을 통해 로컬 MCP 서버에 연결합니다. 스크립트와 로컬 실행 + 파일에 이상적입니다. + + + 실시간 데이터 스트리밍을 위해 Server-Sent Events를 사용하여 원격 MCP 서버와 + 통합합니다. + + + 유연한 스트림 가능한 HTTP를 활용하여 원격 MCP 서버와 안정적으로 통신할 수 + 있습니다. + + + 하나의 어댑터를 사용하여 여러 MCP 서버의 도구를 동시에 통합할 수 있습니다. + + + 에이전트를 안전하게 보호하기 위한 MCP 통합의 중요한 보안 모범 사례를 + 검토하세요. + + + +CrewAI와의 MCP 통합에 대한 전체 데모와 예제를 보려면 이 저장소를 확인하세요! 👇 + + + CrewAI MCP 데모 + + +## MCP와 함께 안전하게 사용하기 + + + 항상 MCP 서버를 사용하기 전에 해당 서버를 신뢰할 수 있는지 확인하세요. + + +#### 보안 경고: DNS 리바인딩 공격 + +SSE 전송은 적절하게 보안되지 않은 경우 DNS 리바인딩 공격에 취약할 수 있습니다. +이를 방지하려면 다음을 수행하세요: + +1. **항상 Origin 헤더를 검증**하여 들어오는 SSE 연결이 예상한 소스에서 오는지 확인합니다. +2. **서버를 모든 네트워크 인터페이스**(0.0.0.0)에 바인딩하는 것을 피하고, 로컬에서 실행할 때는 localhost(127.0.0.1)에만 바인딩합니다. +3. **모든 SSE 연결에 대해 적절한 인증을 구현**합니다. + +이러한 보호 조치가 없으면 공격자가 원격 웹사이트에서 로컬 MCP 서버와 상호작용하기 위해 DNS 리바인딩을 사용할 수 있습니다. + +자세한 내용은 [Anthropic의 MCP 전송 보안 문서](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations)를 참고하세요. + +### 제한 사항 + +- **지원되는 프리미티브**: 현재 `MCPServerAdapter`는 주로 MCP `tools`를 어댑팅하는 기능을 지원합니다. 다른 MCP 프리미티브(예: `prompts` 또는 `resources`)는 현재 이 어댑터를 통해 CrewAI 컴포넌트로 직접 통합되어 있지 않습니다. +- **출력 처리**: 어댑터는 일반적으로 MCP tool의 주요 텍스트 출력(예: `.content[0].text`)을 처리합니다. 복잡하거나 멀티모달 출력의 경우 이 패턴에 맞지 않으면 별도의 커스텀 처리가 필요할 수 있습니다. diff --git a/docs/v1.15.13/ko/mcp/security.mdx b/docs/v1.15.13/ko/mcp/security.mdx new file mode 100644 index 0000000000..dd32747f50 --- /dev/null +++ b/docs/v1.15.13/ko/mcp/security.mdx @@ -0,0 +1,166 @@ +--- +title: MCP 보안 고려사항 +description: MCP 서버를 CrewAI agent와 통합할 때 중요한 보안 모범 사례에 대해 알아보세요. +icon: lock +mode: "wide" +--- + +## 개요 + + +MCP 보안에서 가장 중요한 측면은 **신뢰**입니다. 신뢰할 수 있다고 확신하는 MCP 서버에만 CrewAI 에이전트를 **연결해야 합니다**. + + +CrewAI 에이전트에 MCP(Model Context Protocol) 서버와 같은 외부 서비스를 통합할 때 보안이 가장 중요합니다. +MCP 서버는 노출한 도구를 기반으로 코드를 실행하거나 데이터에 접근하거나 다른 시스템과 상호작용할 수 있습니다. +응용 프로그램과 데이터를 보호하기 위해 그 영향력을 이해하고 모범 사례를 따르는 것이 매우 중요합니다. + +### 위험 + +- 에이전트가 실행 중인 머신에서 임의의 코드를 실행할 수 있습니다(특히 서버가 실행되는 명령어를 제어할 수 있는 `Stdio` 전송 방식을 사용할 경우). +- 에이전트나 그 환경에서 민감한 데이터가 노출될 수 있습니다. +- 예기치 않은 방식으로 에이전트의 동작이 조작되어, 본인 동의 없이 API 호출이 이루어질 수 있습니다. +- 정교한 프롬프트 인젝션 기법(아래 참조)을 통해 에이전트의 reasoning 프로세스가 탈취될 수 있습니다. + +### 1. MCP 서버 신뢰하기 + + +**신뢰할 수 있는 MCP 서버에만 연결하십시오.** + + +`MCPServerAdapter`를 MCP 서버에 연결하도록 구성하기 전에 다음을 반드시 확인하십시오: +- **서버 운영자는 누구입니까?** 신뢰할 수 있는 잘 알려진 서비스이거나 여러분이 직접 제어하는 내부 서버입니까? +- **어떤 도구를 노출합니까?** 도구의 기능을 이해해야 합니다. 공격자가 제어권을 얻거나 서버 자체가 악의적이라면 이 도구들이 오용될 수 있습니까? +- **어떤 데이터를 접근하거나 처리합니까?** MCP 서버에 전송되거나 처리될 수 있는 민감한 정보가 있는지 반드시 파악하십시오. + +특히 에이전트가 민감한 작업이나 데이터를 처리하는 경우, 알 수 없거나 검증되지 않은 MCP 서버에는 연결하지 마십시오. + +### 2. Tool Metadata를 통한 보안 프롬프트 인젝션: "Model Control Protocol"의 위험성 + +중요하면서도 미묘한 위험 중 하나는 툴 메타데이터를 통한 프롬프트 인젝션 가능성입니다. 그 과정은 다음과 같습니다: + +1. CrewAI 에이전트가 MCP 서버에 연결하면, 일반적으로 사용 가능한 툴 목록을 요청합니다. +2. MCP 서버는 각 툴에 대한 메타데이터를 이름, 설명, 파라미터 설명과 함께 응답합니다. +3. 에이전트의 언더라이잉 Language Model(LLM)은 해당 메타데이터를 활용해 언제, 어떻게 툴을 사용할지 이해합니다. 이 메타데이터는 LLM의 시스템 프롬프트나 컨텍스트에 포함되는 경우가 많습니다. +4. 악의적인 MCP 서버는 툴의 메타데이터(이름, 설명 등)에 숨겨진 또는 노골적인 명령어를 삽입할 수 있습니다. 이러한 명령은 프롬프트 인젝션으로 동작하여, LLM에게 특정 방식으로 동작하라고 지시하거나, 민감한 정보를 공개하게 하거나, 악의적인 행동을 수행하게 만들 수 있습니다. + +**중요하게도, 이 공격은 에이전트가 해당 툴을 실제로 *사용*하지 않더라도 단순히 악성 서버에 연결해 툴 목록을 조회하는 것만으로도 발생할 수 있습니다.** 악의적인 메타데이터에 노출되는 것만으로도 에이전트의 행동이 손상될 수 있습니다. + +**완화 방안:** + +* **신뢰되지 않은 서버에 대한 극도의 주의:** 반복합니다. *완전히 신뢰하지 않는 MCP 서버에는 절대 연결하지 마십시오.* 메타데이터 인젝션의 위험성 때문에 이 점이 매우 중요합니다. + +### Stdio 전송 보안 + +Stdio(표준 입력/출력) 전송은 일반적으로 CrewAI 애플리케이션과 동일한 머신에서 실행되는 로컬 MCP 서버에 사용됩니다. + +- **프로세스 격리**: 기본적으로 네트워크에 노출되지 않아 일반적으로 더 안전하지만, `StdioServerParameters`로 실행되는 스크립트나 명령어가 신뢰할 수 있는 소스에서 왔으며 적절한 파일 시스템 권한을 가지고 있는지 확인해야 합니다. 악의적인 Stdio 서버 스크립트는 여전히 로컬 시스템에 피해를 줄 수 있습니다. +- **입력값 정제**: Stdio 서버 스크립트가 에이전트 상호작용에서 파생된 복잡한 입력을 받는 경우, 스크립트 자체에서 이러한 입력값을 정제하여 명령어 삽입이나 스크립트 논리 내 다른 취약점이 발생하지 않도록 해야 합니다. +- **리소스 제한**: 로컬 Stdio 서버 프로세스는 로컬 자원(CPU, 메모리)을 소모하므로, 반드시 정상적으로 동작하는지, 시스템 자원을 소모하지 않는지 주의 깊게 관리해야 합니다. + +### 혼동된 대리인(Confused Deputy) 공격 + +[혼동된 대리인 문제(Confused Deputy Problem)](https://en.wikipedia.org/wiki/Confused_deputy_problem)는 고전적인 보안 취약점으로, MCP 통합에서 특히 MCP 서버가 다른 서드파티 서비스(예: Google Calendar, GitHub)와 OAuth 2.0을 통한 인증을 할 때 프록시 역할을 할 경우 나타날 수 있습니다. + +**시나리오:** + +1. MCP 서버(여기서는 `MCP-Proxy`라고 부르겠습니다)가 에이전트가 `ThirdPartyAPI`와 상호작용할 수 있도록 허용합니다. +2. `MCP-Proxy`는 `ThirdPartyAPI`의 인증 서버와 통신할 때 자체의 단일 고정 `client_id`를 사용합니다. +3. 사용자(즉, 여러분)는 정당하게 `MCP-Proxy`가 여러분을 대신해 `ThirdPartyAPI`에 접근할 수 있도록 승인합니다. 이 과정에서 `ThirdPartyAPI`의 인증 서버는 여러분의 브라우저에 `MCP-Proxy`의 `client_id`에 대한 동의 쿠키를 설정할 수 있습니다. +4. 공격자는 악의적인 링크를 만듭니다. 이 링크는 `MCP-Proxy`와의 OAuth 플로우를 시작하지만, `ThirdPartyAPI`의 인증 서버를 속이도록 설계되어 있습니다. +5. 여러분이 이 링크를 클릭하고, `ThirdPartyAPI`의 인증 서버가 이미 존재하는 `MCP-Proxy`의 `client_id`에 대한 동의 쿠키를 확인하면, 다시 동의를 묻지 않고 *건너뛰기* 할 수 있습니다. +6. 그러면 `MCP-Proxy`가 (공격자에게) 인증 코드를 전달하도록 속거나, 공격자가 여러분을 가장해 `MCP-Proxy`에 사용할 수 있는 MCP 인증 코드를 받게 될 수 있습니다. + +**대응 방안(주로 MCP 서버 개발자용):** + +* 다운스트림 서비스를 위해 정적 client ID를 사용하는 MCP 프록시 서버는 **각 클라이언트 애플리케이션 또는 에이전트별**로 명시적인 사용자 동의를 반드시 받아야 합니다. 이 동의는 서드파티 서비스와의 OAuth 플로우 시작 *이전*에 이루어져야 하며, `MCP-Proxy` 자체가 동의 화면을 표시하도록 해야 합니다. + +**CrewAI 사용자 주의사항:** + +* MCP 서버가 여러 번 OAuth 인증을 위해 리디렉션하는 경우, 특히 예상치 않거나 요청된 권한이 과도하게 넓다면 주의해야 합니다. +* 자신과 프록시할 수 있는 서드파티 서비스의 구분을 명확하게 하는 MCP 서버를 선호하는 것이 좋습니다. + +### 원격 전송 보안 (SSE & Streamable HTTP) + +Server-Sent Events(SSE) 또는 Streamable HTTP를 통해 원격 MCP 서버에 연결할 때, 표준 웹 보안 관행이 필수적입니다. + +### SSE 보안 고려사항 + +### a. DNS 리바인딩 공격 (특히 SSE의 경우) + + +**DNS 리바인딩 공격으로부터 보호하세요.** + + +DNS 리바인딩은 공격자가 제어하는 웹사이트가 동일 출처 정책(same-origin policy)을 우회하여 사용자의 로컬 네트워크(예: `localhost`) 또는 인트라넷에 있는 서버에 요청을 보낼 수 있도록 합니다. 이는 MCP 서버를 로컬(예: 개발용)로 실행하고 브라우저와 유사한 환경에서 agent를 사용하는 경우(일반적인 CrewAI 백엔드 구성에서는 드물지만) 또는 MCP 서버가 내부 네트워크상에 있을 경우 특히 위험할 수 있습니다. + +**MCP 서버 구현자를 위한 대응 전략:** +- **`Origin` 및 `Host` 헤더 검증**: MCP 서버(특히 SSE 서버)는 `Origin` 및/또는 `Host` HTTP 헤더를 검증하여 요청이 예상되는 도메인/클라이언트로부터 오는지 확인해야 합니다. +- **`localhost`(127.0.0.1)로 바인딩**: 개발을 위해 MCP 서버를 로컬에서 실행할 때는 `0.0.0.0` 대신 `127.0.0.1`로 바인딩하세요. 이를 통해 네트워크의 다른 기기에서 접근하지 못하도록 막을 수 있습니다. +- **인증(Authentication)**: MCP 서버가 공개된 익명 접근을 목적으로 하지 않는 한 모든 연결에 대해 인증을 요구하세요. + +### b. HTTPS 사용 + +- **전송 중 데이터 암호화**: 원격 MCP 서버의 URL에는 항상 HTTPS(HTTP Secure)를 사용하세요. 이는 CrewAI 애플리케이션과 MCP 서버 간의 통신을 암호화하여 도청 및 중간자 공격으로부터 보호합니다. `MCPServerAdapter`는 URL에 제공된 스킴(`http` 또는 `https`)을 그대로 따릅니다. + +### c. 토큰 패스스루(Token Passthrough) (안티 패턴) + +이 문제는 주로 MCP 서버 개발자들에게 해당되지만, 이를 이해하는 것은 안전한 서버를 선택하는 데 도움이 됩니다. + +"토큰 패스스루"란, MCP 서버가 CrewAI agent로부터 받은 액세스 토큰(예를 들어 `ServiceA`를 위한 토큰일 수도 있음)을 별도의 적절한 검증 없이 다른 하위 API(`ServiceB`)로 그대로 전달하는 것을 의미합니다. 특히, `ServiceB`(또는 MCP 서버 자체)는 명시적으로 *자신들을 위해* 발급된 토큰만 받아야 합니다(즉, 토큰 내의 'audience' 클레임이 해당 서버/서비스와 일치해야 함). + +**위험성:** + +* MCP 서버나 하위 API의 보안 제어(예 : 속도 제한, 세밀한 권한 부여 등)를 우회할 수 있습니다. +* 감사 추적 및 책임성을 저해할 수 있습니다. +* 탈취된 토큰의 악용을 허용할 수 있습니다. + +**대응 방안 (MCP 서버 개발자용):** + +* MCP 서버는 **명시적으로 자신을 위해 발급된 토큰만** 받아야 합니다. 토큰의 audience 클레임을 반드시 검증해야 합니다. + +**CrewAI 사용자에게 미치는 영향:** + +* 사용자가 직접적으로 제어할 수는 없지만, 보안 모범 사례를 준수하는 잘 설계된 MCP 서버에 연결하는 것이 중요함을 강조합니다. + +#### 인증 및 인가 + +- **신원 확인**: MCP 서버가 민감한 도구 또는 비공개 데이터에 대한 액세스를 제공하는 경우, 클라이언트(귀하의 CrewAI 애플리케이션)의 신원을 확인하기 위해 강력한 인증 메커니즘을 반드시 구현해야 합니다. 이는 API 키, OAuth 토큰 또는 기타 표준 방법을 포함할 수 있습니다. +- **최소 권한 원칙**: `MCPServerAdapter`에서 사용하는 자격 증명(있는 경우)은 필요한 도구에 접근하는 데 꼭 필요한 권한만 가지고 있도록 해야 합니다. + +### d. 입력 검증 및 정제 + +- **입력 검증은 매우 중요합니다**: MCP 서버는 에이전트로부터 받은 모든 입력을 처리하거나 도구에 전달하기 *전에* 철저하게 검증해야 합니다. 이는 많은 일반적인 취약점에 대한 1차 방어선입니다: + - **명령어 삽입:** 도구가 입력을 기반으로 셸 명령, SQL 쿼리 또는 기타 해석형 언어 문장을 구성하는 경우, 서버는 악의적 명령어 주입 및 실행을 방지하기 위해 이 입력을 꼼꼼하게 정제해야 합니다. + - **경로 탐색:** 도구가 입력 매개변수에 따라 파일에 접근하는 경우, 서버는 미허가 파일 또는 디렉터리에 접근하지 못하도록 이 경로를 검증 및 정제해야 합니다(예: `../` 시퀀스 차단). + - **데이터 타입 및 범위 검사:** 서버는 입력 데이터가 기대하는 데이터 타입(예: 문자열, 숫자, 불리언)에 부합하는지, 허용 범위 내에 있거나 정의된 형식(예: URL에 대한 정규식)에 맞는지 확인해야 합니다. + - **JSON 스키마 검증:** 모든 도구 매개변수는 정의된 JSON 스키마에 엄격하게 맞춰 검증되어야 합니다. 이를 통해 잘못된 요청을 조기에 차단할 수 있습니다. +- **클라이언트 측 인지**: 서버 측 검증이 가장 중요하지만, CrewAI 사용자는 특히 신뢰도가 낮은 또는 새로운 MCP 서버와 상호작용할 때 자신의 에이전트가 MCP 도구에 전달하도록 설계된 데이터에 각별히 유의해야 합니다. + +### e. 속도 제한 및 리소스 관리 + +- **오용 방지**: MCP 서버는 악의적(서비스 거부 공격 등)이든 비의도적(예: 잘못 구성된 agent가 과도한 요청을 보내는 경우)이든 오용을 방지하기 위해 속도 제한을 구현해야 합니다. +- **클라이언트 측 재시도**: 일시적인 네트워크 문제나 서버의 속도 제한이 예상될 경우, CrewAI 작업에서 합리적인 재시도 로직을 구현하되, 서버 부하를 가중시킬 수 있는 과도한 재시도는 피해야 합니다. + +## 4. 보안 MCP 서버 구현 권장 사항 (개발자용) + +CrewAI 에이전트가 연결할 수 있는 MCP 서버를 개발하고 있다면, 위의 내용에 추가하여 다음과 같은 모범 사례를 고려하세요: + +- **안전한 코딩 관행 준수**: 선택한 언어 및 프레임워크에 대한 표준 안전 코딩 원칙(예: OWASP Top 10)을 준수하세요. +- **최소 권한 원칙**: MCP 서버를 실행하는 프로세스(특히 `Stdio`의 경우)는 작업에 필요한 최소 권한만 보유하도록 하세요. 툴 자체도 자신의 기능 수행에 필요한 최소한의 권한만으로 동작해야 합니다. +- **종속성 관리**: 운영 체제 패키지, 언어 런타임, 써드파티 라이브러리 등 모든 서버 측 종속성을 최신 상태로 유지하여 알려진 취약점을 패치하세요. 취약한 종속성을 스캔하는 도구를 사용하세요. +- **안전한 기본값**: 서버와 그 도구를 기본적으로 안전하게 설계하세요. 예를 들어, 위험할 수 있는 기능은 기본적으로 꺼져 있거나 명확한 경고와 함께 명시적으로 opt-in 하도록 해야 합니다. +- **툴에 대한 접근 제어**: 인증 및 권한이 부여된 에이전트 또는 사용자만 특정 툴(특히 강력하거나 민감하거나 비용이 발생하는 툴)에 접근할 수 있도록 강력한 메커니즘을 구현하세요. +- **안전한 오류 처리**: 서버는 클라이언트에게 상세한 내부 오류 메시지, 스택 트레이스 또는 디버깅 정보를 노출해서는 안 됩니다. 이러한 정보는 내부 동작이나 잠재적 취약점을 드러낼 수 있습니다. 오류는 서버 측에서 진단을 목적으로 포괄적으로 기록하세요. +- **포괄적인 로깅 및 모니터링**: 보안 관련 이벤트(예: 인증 시도, 툴 호출, 오류, 권한 변경)에 대해 상세하게 로깅하세요. 이런 로그를 모니터링하여 의심스러운 활동이나 악용 패턴을 파악하세요. +- **MCP 인증 사양 준수**: 인증 및 권한 부여를 구현할 경우, [MCP Authorization specification](https://modelcontextprotocol.io/specification/draft/basic/authorization) 및 관련 [OAuth 2.0 security best practices](https://datatracker.ietf.org/doc/html/rfc9700)를 엄격히 준수하세요. +- **정기적인 보안 감사**: MCP 서버가 민감한 데이터를 처리하거나, 중요한 작업을 수행하거나, 대외적으로 노출된 경우 자격을 갖춘 전문가의 정기적인 보안 감사를 고려하세요. + +## 5. 추가 참고 자료 + +MCP 보안에 대한 자세한 내용은 공식 문서를 참고하세요: +- **[MCP 전송 보안](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations)** + +이러한 보안 고려사항을 이해하고 모범 사례를 구현하면 CrewAI 프로젝트에서 MCP 서버의 강력한 기능을 안전하게 활용할 수 있습니다. +여기서 다루는 내용이 모든 것을 포괄하는 것은 아니지만, 가장 일반적이고 중요한 보안 문제들을 포함하고 있습니다. +위협은 계속 진화하기 때문에 지속적으로 정보를 확인하고 그에 맞춰 보안 조치를 조정하는 것이 중요합니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/mcp/sse.mdx b/docs/v1.15.13/ko/mcp/sse.mdx new file mode 100644 index 0000000000..12b1536125 --- /dev/null +++ b/docs/v1.15.13/ko/mcp/sse.mdx @@ -0,0 +1,151 @@ +--- +title: SSE 트랜스포트 +description: 서버 전송 이벤트(SSE)를 사용하여 CrewAI를 원격 MCP 서버에 연결하여 실시간 통신을 구현하는 방법을 알아보세요. +icon: wifi +mode: "wide" +--- + +## 개요 + +Server-Sent Events(SSE)는 웹 서버가 하나의 장기 실행 HTTP 연결을 통해 클라이언트에 업데이트를 전송할 수 있는 표준 방식을 제공합니다. MCP의 맥락에서 SSE는 원격 서버가 데이터(예: tool 응답)를 실시간으로 CrewAI 애플리케이션에 스트리밍하는 데 사용됩니다. + +## 주요 개념 + +- **원격 서버**: SSE는 원격에 호스팅된 MCP 서버에 적합합니다. +- **단방향 스트림**: 일반적으로 SSE는 서버에서 클라이언트로의 단방향 통신 채널입니다. +- **`MCPServerAdapter` 구성**: SSE의 경우, 서버의 URL을 제공하고 전송 유형을 지정해야 합니다. + +## SSE를 통한 연결 + +SSE 기반 MCP 서버에 연결하려면 연결 수명 주기를 관리하는 두 가지 주요 접근 방식을 사용할 수 있습니다. + +### 1. 완전 관리형 연결(권장) + +Python 컨텍스트 매니저(`with` 문)를 사용하는 것이 권장되는 접근 방식입니다. 이 방법은 SSE MCP 서버에 대한 연결의 생성과 종료를 자동으로 처리합니다. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL + "transport": "sse" +} + +# Using MCPServerAdapter with a context manager +try: + with MCPServerAdapter(server_params) as tools: + print(f"Available tools from SSE MCP server: {[tool.name for tool in tools]}") + + # Example: Using a tool from the SSE MCP server + sse_agent = Agent( + role="Remote Service User", + goal="Utilize a tool provided by a remote SSE MCP server.", + backstory="An AI agent that connects to external services via SSE.", + tools=tools, + reasoning=True, + verbose=True, + ) + + sse_task = Task( + description="Fetch real-time stock updates for 'AAPL' using an SSE tool.", + expected_output="The latest stock price for AAPL.", + agent=sse_agent, + markdown=True + ) + + sse_crew = Crew( + agents=[sse_agent], + tasks=[sse_task], + verbose=True, + process=Process.sequential + ) + + if tools: # Only kickoff if tools were loaded + result = sse_crew.kickoff() # Add inputs={'stock_symbol': 'AAPL'} if tool requires it + print("\nCrew Task Result (SSE - Managed):\n", result) + else: + print("Skipping crew kickoff as tools were not loaded (check server connection).") + +except Exception as e: + print(f"Error connecting to or using SSE MCP server (Managed): {e}") + print("Ensure the SSE MCP server is running and accessible at the specified URL.") + +``` + + +`"http://localhost:8000/sse"`를 실제 SSE MCP 서버의 URL로 교체하십시오. + + +### 2. 수동 연결 라이프사이클 + +더 세밀한 제어가 필요한 경우, `MCPServerAdapter`의 연결 라이프사이클을 수동으로 관리할 수 있습니다. + + +연결이 종료되고 리소스가 해제되도록 반드시 `mcp_server_adapter.stop()`을 호출해야 합니다. `try...finally` 블록을 사용하는 것을 강력히 권장합니다. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL + "transport": "sse" +} + +mcp_server_adapter = None +try: + mcp_server_adapter = MCPServerAdapter(server_params) + mcp_server_adapter.start() + tools = mcp_server_adapter.tools + print(f"Available tools (manual SSE): {[tool.name for tool in tools]}") + + manual_sse_agent = Agent( + role="Remote Data Analyst", + goal="Analyze data fetched from a remote SSE MCP server using manual connection management.", + backstory="An AI skilled in handling SSE connections explicitly.", + tools=tools, + verbose=True + ) + + analysis_task = Task( + description="Fetch and analyze the latest user activity trends from the SSE server.", + expected_output="A summary report of user activity trends.", + agent=manual_sse_agent + ) + + analysis_crew = Crew( + agents=[manual_sse_agent], + tasks=[analysis_task], + verbose=True, + process=Process.sequential + ) + + result = analysis_crew.kickoff() + print("\nCrew Task Result (SSE - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual SSE MCP integration: {e}") + print("Ensure the SSE MCP server is running and accessible.") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: + print("Stopping SSE MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: + print("SSE MCP server adapter was not connected. No stop needed or start failed.") + +``` + +## SSE를 위한 보안 고려사항 + + +**DNS 리바인딩 공격**: SSE 전송 방식은 MCP 서버가 적절하게 보안 조치되지 않은 경우 DNS 리바인딩 공격에 취약할 수 있습니다. 이로 인해 악의적인 웹사이트가 로컬 또는 인트라넷 기반 MCP 서버와 상호 작용할 수 있습니다. + + +이 위험을 완화하려면: +- MCP 서버 구현에서는 들어오는 SSE 연결의 **`Origin` 헤더를 검증**해야 합니다. +- 개발 환경에서 로컬 SSE MCP 서버를 실행할 때에는 모든 네트워크 인터페이스(`0.0.0.0`)가 아닌, **`localhost`(`127.0.0.1`)에만 바인딩**해야 합니다. +- 민감한 도구나 데이터를 노출하는 SSE 연결에는 **적절한 인증**을 구현해야 합니다. + +보안 모범 사례에 대한 포괄적인 개요는 [보안 고려사항](./security.mdx) 페이지와 공식 [MCP 전송 보안 문서](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations)를 참고하시기 바랍니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/mcp/stdio.mdx b/docs/v1.15.13/ko/mcp/stdio.mdx new file mode 100644 index 0000000000..b15e731b05 --- /dev/null +++ b/docs/v1.15.13/ko/mcp/stdio.mdx @@ -0,0 +1,135 @@ +--- +title: Stdio 전송 +description: Stdio(표준 입력/출력) 전송 메커니즘을 사용하여 CrewAI를 로컬 MCP 서버에 연결하는 방법을 알아보세요. +icon: server +mode: "wide" +--- + +## 개요 + +Stdio(표준 입력/출력) 트랜스포트는 `MCPServerAdapter`를 로컬 MCP 서버에 연결하기 위해 설계되었습니다. 이 MCP 서버는 표준 입력 및 출력 스트림을 통해 통신합니다. 이는 일반적으로 MCP 서버가 CrewAI 애플리케이션과 동일한 머신에서 실행되는 스크립트나 실행 파일일 때 사용됩니다. + +## 주요 개념 + +- **로컬 실행**: Stdio 전송은 MCP 서버를 위한 로컬에서 실행 중인 프로세스를 관리합니다. +- **`StdioServerParameters`**: `mcp` 라이브러리의 이 클래스는 Stdio 서버를 실행하기 위한 명령어, 인수, 환경 변수를 구성하는 데 사용됩니다. + +## Stdio를 통한 연결 + +연결 수명 주기를 관리하기 위한 두 가지 주요 접근 방식으로 Stdio 기반 MCP 서버에 연결할 수 있습니다. + +### 1. 완전 관리형 연결(권장) + +Python 컨텍스트 관리자(`with` 문)를 사용하는 것이 권장되는 방법입니다. 이 방식은 MCP 서버 프로세스의 시작과 컨텍스트 종료 시 자동 종료를 처리합니다. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters +import os + +# Create a StdioServerParameters object +server_params=StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +with MCPServerAdapter(server_params) as tools: + print(f"Available tools from Stdio MCP server: {[tool.name for tool in tools]}") + + # Example: Using the tools from the Stdio MCP server in a CrewAI Agent + research_agent = Agent( + role="Local Data Processor", + goal="Process data using a local Stdio-based tool.", + backstory="An AI that leverages local scripts via MCP for specialized tasks.", + tools=tools, + reasoning=True, + verbose=True, + ) + + processing_task = Task( + description="Process the input data file 'data.txt' and summarize its contents.", + expected_output="A summary of the processed data.", + agent=research_agent, + markdown=True + ) + + data_crew = Crew( + agents=[research_agent], + tasks=[processing_task], + verbose=True, + process=Process.sequential + ) + + result = data_crew.kickoff() + print("\nCrew Task Result (Stdio - Managed):\n", result) + +``` + +### 2. 수동 연결 라이프사이클 + +Stdio MCP 서버 프로세스가 시작되고 중지되는 시점을 더 세밀하게 제어해야 하는 경우, `MCPServerAdapter`의 라이프사이클을 수동으로 관리할 수 있습니다. + + +서버 프로세스가 종료되고 자원이 해제되도록 **반드시** `mcp_server_adapter.stop()`을 호출해야 합니다. `try...finally` 블록을 사용하는 것을 강력히 추천합니다. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters +import os + +# Create a StdioServerParameters object +stdio_params=StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +mcp_server_adapter = MCPServerAdapter(server_params=stdio_params) +try: + mcp_server_adapter.start() # Manually start the connection and server process + tools = mcp_server_adapter.tools + print(f"Available tools (manual Stdio): {[tool.name for tool in tools]}") + + # Example: Using the tools with your Agent, Task, Crew setup + manual_agent = Agent( + role="Local Task Executor", + goal="Execute a specific local task using a manually managed Stdio tool.", + backstory="An AI proficient in controlling local processes via MCP.", + tools=tools, + verbose=True + ) + + manual_task = Task( + description="Execute the 'perform_analysis' command via the Stdio tool.", + expected_output="Results of the analysis.", + agent=manual_agent + ) + + manual_crew = Crew( + agents=[manual_agent], + tasks=[manual_task], + verbose=True, + process=Process.sequential + ) + + + result = manual_crew.kickoff() # Actual inputs depend on your tool + print("\nCrew Task Result (Stdio - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual Stdio MCP integration: {e}") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: # Check if connected before stopping + print("Stopping Stdio MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: # If adapter exists but not connected (e.g. start failed) + print("Stdio MCP server adapter was not connected. No stop needed or start failed.") + +``` + +플레이스홀더 경로 및 명령어를 실제 Stdio 서버 정보로 교체해야 합니다. `StdioServerParameters`의 `env` 파라미터는 +서버 프로세스용 환경 변수를 설정할 때 사용할 수 있습니다. 이는 서버의 동작을 구성하거나 필요한 경로(예: `PYTHONPATH`)를 제공하는 데 유용할 수 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/mcp/streamable-http.mdx b/docs/v1.15.13/ko/mcp/streamable-http.mdx new file mode 100644 index 0000000000..b6293ef823 --- /dev/null +++ b/docs/v1.15.13/ko/mcp/streamable-http.mdx @@ -0,0 +1,136 @@ +--- +title: 스트리머블 HTTP 전송 +description: 유연한 스트리머블 HTTP 전송을 사용하여 CrewAI를 원격 MCP 서버에 연결하는 방법을 알아보세요. +icon: globe +mode: "wide" +--- + +## 개요 + +Streamable HTTP 전송은 원격 MCP 서버에 연결할 수 있는 유연한 방법을 제공합니다. 이는 종종 HTTP를 기반으로 구축되며, 요청-응답 및 스트리밍을 포함한 다양한 통신 패턴을 지원할 수 있습니다. 때때로 더 넓은 HTTP 상호작용 내에서 서버-클라이언트 스트림을 위해 Server-Sent Events(SSE)를 활용하기도 합니다. + +## 주요 개념 + +- **원격 서버**: 원격에 호스팅된 MCP 서버용으로 설계되었습니다. +- **유연성**: 단순 SSE보다 더 복잡한 상호작용 패턴을 지원할 수 있으며, 서버가 구현한 경우 양방향 통신도 가능할 수 있습니다. +- **`MCPServerAdapter` 구성**: MCP 통신을 위한 서버의 기본 URL을 제공하고, 전송 유형으로 `"streamable-http"`를 지정해야 합니다. + +## 스트리머블 HTTP를 통한 연결 + +Streamable HTTP MCP 서버와의 연결 라이프사이클을 관리하는 주요 방법에는 두 가지가 있습니다: + +### 1. 완전히 관리되는 연결(추천) + +추천되는 방법은 Python 컨텍스트 매니저(`with` 문)을 사용하는 것으로, 연결의 설정과 해제를 자동으로 처리합니다. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8001/mcp", # 실제 Streamable HTTP 서버 URL로 교체하세요 + "transport": "streamable-http" +} + +try: + with MCPServerAdapter(server_params) as tools: + print(f"Available tools from Streamable HTTP MCP server: {[tool.name for tool in tools]}") + + http_agent = Agent( + role="HTTP Service Integrator", + goal="Utilize tools from a remote MCP server via Streamable HTTP.", + backstory="An AI agent adept at interacting with complex web services.", + tools=tools, + verbose=True, + ) + + http_task = Task( + description="Perform a complex data query using a tool from the Streamable HTTP server.", + expected_output="The result of the complex data query.", + agent=http_agent, + ) + + http_crew = Crew( + agents=[http_agent], + tasks=[http_task], + verbose=True, + process=Process.sequential + ) + + result = http_crew.kickoff() + print("\nCrew Task Result (Streamable HTTP - Managed):\n", result) + +except Exception as e: + print(f"Error connecting to or using Streamable HTTP MCP server (Managed): {e}") + print("Ensure the Streamable HTTP MCP server is running and accessible at the specified URL.") + +``` +**참고:** `"http://localhost:8001/mcp"`은 실제 사용 중인 Streamable HTTP MCP 서버의 URL로 교체해야 합니다. + +### 2. 수동 연결 라이프사이클 + +보다 명시적인 제어가 필요한 시나리오에서는 `MCPServerAdapter` 연결을 직접 관리할 수 있습니다. + + +연결을 종료하고 리소스를 해제하려면 작업이 끝난 후 반드시 `mcp_server_adapter.stop()`을 호출하는 것이 **매우 중요**합니다. 이를 보장하는 가장 안전한 방법은 `try...finally` 블록을 사용하는 것입니다. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8001/mcp", # Replace with your actual Streamable HTTP server URL + "transport": "streamable-http" +} + +mcp_server_adapter = None +try: + mcp_server_adapter = MCPServerAdapter(server_params) + mcp_server_adapter.start() + tools = mcp_server_adapter.tools + print(f"Available tools (manual Streamable HTTP): {[tool.name for tool in tools]}") + + manual_http_agent = Agent( + role="Advanced Web Service User", + goal="Interact with an MCP server using manually managed Streamable HTTP connections.", + backstory="An AI specialist in fine-tuning HTTP-based service integrations.", + tools=tools, + verbose=True + ) + + data_processing_task = Task( + description="Submit data for processing and retrieve results via Streamable HTTP.", + expected_output="Processed data or confirmation.", + agent=manual_http_agent + ) + + data_crew = Crew( + agents=[manual_http_agent], + tasks=[data_processing_task], + verbose=True, + process=Process.sequential + ) + + result = data_crew.kickoff() + print("\nCrew Task Result (Streamable HTTP - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual Streamable HTTP MCP integration: {e}") + print("Ensure the Streamable HTTP MCP server is running and accessible.") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: + print("Stopping Streamable HTTP MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: + print("Streamable HTTP MCP server adapter was not connected. No stop needed or start failed.") +``` + +## 보안 고려사항 + +Streamable HTTP 전송을 사용할 때는 일반적인 웹 보안 모범 사례가 매우 중요합니다: +- **HTTPS 사용**: 데이터 전송을 암호화하기 위해 항상 MCP 서버 URL에 HTTPS(HTTP Secure)를 사용하는 것이 좋습니다. +- **인증**: MCP 서버가 민감한 도구나 데이터를 노출하는 경우 강력한 인증 메커니즘을 구현하세요. +- **입력 검증**: MCP 서버가 모든 수신 요청과 매개변수를 반드시 검증하도록 하십시오. + +MCP 통합 보안에 대한 종합적인 안내는 [보안 고려사항](./security.mdx) 페이지와 공식 [MCP 전송 보안 문서](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations)를 참고하시기 바랍니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/arize-phoenix.mdx b/docs/v1.15.13/ko/observability/arize-phoenix.mdx new file mode 100644 index 0000000000..340652963f --- /dev/null +++ b/docs/v1.15.13/ko/observability/arize-phoenix.mdx @@ -0,0 +1,150 @@ +--- +title: Arize Phoenix +description: OpenTelemetry 및 OpenInference가 포함된 CrewAI용 Arize Phoenix 통합 +icon: magnifying-glass-chart +mode: "wide" +--- + +# Arize Phoenix 통합 + +이 가이드는 [OpenInference](https://github.com/openinference/openinference) SDK를 통해 OpenTelemetry를 사용하여 **Arize Phoenix**를 **CrewAI**와 통합하는 방법을 보여줍니다. 이 가이드를 완료하면 CrewAI agent를 추적하고 agent를 쉽게 디버그할 수 있습니다. + +> **Arize Phoenix란?** [Arize Phoenix](https://phoenix.arize.com)는 AI 애플리케이션을 위한 추적 및 평가 기능을 제공하는 LLM 가시성(observability) 플랫폼입니다. + +[![Phoenix와의 통합 영상 데모 보기](https://storage.googleapis.com/arize-assets/fixtures/setup_crewai.png)](https://www.youtube.com/watch?v=Yc5q3l6F7Ww) + +## 시작하기 + +CrewAI를 사용하고 OpenInference를 통해 OpenTelemetry와 Arize Phoenix를 연동하는 간단한 예제를 단계별로 안내합니다. + +이 가이드는 [Google Colab](https://colab.research.google.com/github/Arize-ai/phoenix/blob/main/tutorials/tracing/crewai_tracing_tutorial.ipynb)에서도 확인하실 수 있습니다. + +### 1단계: 의존성 설치 + +```bash +pip install openinference-instrumentation-crewai crewai crewai-tools arize-phoenix-otel +``` + +### 2단계: 환경 변수 설정 + +Phoenix Cloud API 키를 설정하고 OpenTelemetry를 구성하여 추적 정보를 Phoenix로 전송합니다. Phoenix Cloud는 Arize Phoenix의 호스팅 버전이지만, 이 통합을 사용하는 데 필수는 아닙니다. + +무료 Serper API 키는 [여기](https://serper.dev/)에서 받을 수 있습니다. + +```python +import os +from getpass import getpass + +# Get your Phoenix Cloud credentials +PHOENIX_API_KEY = getpass("🔑 Enter your Phoenix Cloud API Key: ") + +# Get API keys for services +OPENAI_API_KEY = getpass("🔑 Enter your OpenAI API key: ") +SERPER_API_KEY = getpass("🔑 Enter your Serper API key: ") + +# Set environment variables +os.environ["PHOENIX_CLIENT_HEADERS"] = f"api_key={PHOENIX_API_KEY}" +os.environ["PHOENIX_COLLECTOR_ENDPOINT"] = "https://app.phoenix.arize.com" # Phoenix Cloud, change this to your own endpoint if you are using a self-hosted instance +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +os.environ["SERPER_API_KEY"] = SERPER_API_KEY +``` + +### 3단계: Phoenix와 함께 OpenTelemetry 초기화하기 + +OpenInference OpenTelemetry 계측 SDK를 초기화하여 트레이스를 수집하고 Phoenix로 전송합니다. + +```python +from phoenix.otel import register + +tracer_provider = register( + project_name="crewai-tracing-demo", + auto_instrument=True, +) +``` + +### 4단계: CrewAI 애플리케이션 생성하기 + +두 명의 에이전트가 협력하여 AI 발전에 관한 블로그 글을 조사하고 작성하는 CrewAI 애플리케이션을 만들어 보겠습니다. + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool +from openinference.instrumentation.crewai import CrewAIInstrumentor +from phoenix.otel import register + +# crew에 대한 모니터링 설정 +tracer_provider = register( + endpoint="http://localhost:6006/v1/traces") +CrewAIInstrumentor().instrument(skip_dep_check=True, tracer_provider=tracer_provider) +search_tool = SerperDevTool() + +# 역할과 목표가 설정된 에이전트 정의 +researcher = Agent( + role="Senior Research Analyst", + goal="AI 및 데이터 과학의 최첨단 발전 사항 발견", + backstory="""당신은 최고 수준의 기술 싱크탱크에서 근무합니다. + 새로운 트렌드를 식별하는 데 전문성이 있습니다. + 복잡한 데이터를 분석하고 실행 가능한 인사이트로 제시하는 데 뛰어납니다.""", + verbose=True, + allow_delegation=False, + # 원하는 모델을 지정할 수 있는 optional llm 속성을 전달할 수 있습니다. + # llm=ChatOpenAI(model_name="gpt-3.5", temperature=0.7), + tools=[search_tool], +) +writer = Agent( + role="Tech Content Strategist", + goal="기술 발전에 대한 매력적인 콘텐츠 작성", + backstory="""당신은 통찰력 있고 흥미로운 기사로 유명한 콘텐츠 전략가입니다. + 복잡한 개념을 매력적인 스토리로 전환합니다.""", + verbose=True, + allow_delegation=True, +) + +# 에이전트를 위한 task 생성 +task1 = Task( + description="""2024년 AI 분야의 최신 발전 상황에 대한 포괄적인 분석을 수행하세요. + 주요 트렌드, 획기적 기술, 산업에 미칠 잠재적 영향을 식별하세요.""", + expected_output="주요 내용을 불릿 포인트로 정리한 전체 분석 보고서", + agent=researcher, +) + +task2 = Task( + description="""제공된 인사이트를 활용하여 + 가장 중요한 AI 발전 내용을 강조하는 흥미로운 블로그 글을 작성하세요. + 글은 정보성 있고, 기술에 밝은 독자를 대상으로 하면서 읽기 쉽게 써야 합니다. + 멋지게 들리도록 쓰되, 복잡한 단어는 피하여 AI처럼 들리지 않게 하세요.""", + expected_output="최소 4개의 단락으로 구성된 전체 블로그 글", + agent=writer, +) + +# 순차 프로세스 방식으로 crew 인스턴스화 +crew = Crew( + agents=[researcher, writer], tasks=[task1, task2], verbose=1, process=Process.sequential +) + +# crew에게 작업 시작 지시! +result = crew.kickoff() + +print("######################") +print(result) +``` + +### 5단계: Phoenix에서 트레이스 보기 + +에이전트를 실행한 후, Phoenix에서 CrewAI 애플리케이션에 의해 생성된 트레이스를 볼 수 있습니다. 에이전트 상호작용과 LLM 호출의 상세한 단계가 표시되어 AI 에이전트를 디버깅하고 최적화하는 데 도움이 됩니다. + +Phoenix Cloud 계정에 로그인한 다음 `project_name` 파라미터에서 지정한 프로젝트로 이동하세요. 모든 에이전트 상호작용, 도구 사용 및 LLM 호출이 포함된 트레이스의 타임라인 보기를 확인할 수 있습니다. + +![Phoenix에서 에이전트 상호작용을 보여주는 예시 트레이스](https://storage.googleapis.com/arize-assets/fixtures/crewai_traces.png) + +### 버전 호환성 정보 +- Python 3.8+ +- CrewAI >= 0.86.0 +- Arize Phoenix >= 7.0.1 +- OpenTelemetry SDK >= 1.31.0 + +### 참고 자료 +- [Phoenix 문서](https://docs.arize.com/phoenix/) - Phoenix 플랫폼 개요. +- [CrewAI 문서](https://docs.crewai.com/) - CrewAI 프레임워크 개요. +- [OpenTelemetry 문서](https://opentelemetry.io/docs/) - OpenTelemetry 가이드 +- [OpenInference GitHub](https://github.com/openinference/openinference) - OpenInference SDK 소스 코드. \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/braintrust.mdx b/docs/v1.15.13/ko/observability/braintrust.mdx new file mode 100644 index 0000000000..7a0349f8e7 --- /dev/null +++ b/docs/v1.15.13/ko/observability/braintrust.mdx @@ -0,0 +1,236 @@ +--- +title: Braintrust +description: OpenTelemetry 추적 및 평가를 포함한 CrewAI용 Braintrust 통합 +icon: magnifying-glass-chart +mode: "wide" +--- + +# Braintrust 통합 + +이 가이드는 **Braintrust**를 **CrewAI**와 OpenTelemetry를 사용하여 포괄적인 추적 및 평가와 함께 통합하는 방법을 보여줍니다. 이 가이드를 완료하면 CrewAI agent를 추적하고, 성능을 모니터링하며, Braintrust의 강력한 관찰성 플랫폼을 사용하여 출력을 평가할 수 있습니다. + +> **Braintrust란?** [Braintrust](https://www.braintrust.dev)는 내장된 실험 추적 및 성능 분석을 통해 AI 애플리케이션에 대한 포괄적인 추적, 평가 및 모니터링을 제공하는 AI 평가 및 관찰성 플랫폼입니다. + +## 시작하기 + +CrewAI를 사용하고 포괄적인 관찰성 및 평가를 위해 OpenTelemetry를 통해 Braintrust와 통합하는 간단한 예제를 단계별로 안내합니다. + +### 1단계: 의존성 설치 + +```bash +uv add braintrust[otel] crewai crewai-tools opentelemetry-instrumentation-openai opentelemetry-instrumentation-crewai python-dotenv +``` + +### 2단계: 환경 변수 설정 + +Braintrust API 키를 설정하고 추적을 Braintrust로 전송하도록 OpenTelemetry를 구성합니다. Braintrust API 키와 OpenAI API 키가 필요합니다. + +```python +import os +from getpass import getpass + +# Braintrust 자격 증명 가져오기 +BRAINTRUST_API_KEY = getpass("🔑 Braintrust API 키를 입력하세요: ") + +# 서비스용 API 키 가져오기 +OPENAI_API_KEY = getpass("🔑 OpenAI API 키를 입력하세요: ") + +# 환경 변수 설정 +os.environ["BRAINTRUST_API_KEY"] = BRAINTRUST_API_KEY +os.environ["BRAINTRUST_PARENT"] = "project_name:crewai-demo" +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +``` + +### 3단계: Braintrust와 함께 OpenTelemetry 초기화하기 + +추적을 캡처하고 Braintrust로 전송하기 시작하도록 Braintrust OpenTelemetry 계측을 초기화합니다. + +```python +import os +from typing import Any, Dict + +from braintrust.otel import BraintrustSpanProcessor +from crewai import Agent, Crew, Task +from crewai.llm import LLM +from opentelemetry import trace +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.instrumentation.openai import OpenAIInstrumentor +from opentelemetry.sdk.trace import TracerProvider + +def setup_tracing() -> None: + """Braintrust와 함께 OpenTelemetry 추적 설정.""" + current_provider = trace.get_tracer_provider() + if isinstance(current_provider, TracerProvider): + provider = current_provider + else: + provider = TracerProvider() + trace.set_tracer_provider(provider) + + provider.add_span_processor(BraintrustSpanProcessor()) + CrewAIInstrumentor().instrument(tracer_provider=provider) + OpenAIInstrumentor().instrument(tracer_provider=provider) + + +setup_tracing() +``` + +### 4단계: CrewAI 애플리케이션 생성하기 + +포괄적인 추적이 활성화된 CrewAI 애플리케이션을 생성합니다. + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool + +def create_crew() -> Crew: + """포괄적인 추적을 위한 다중 agent가 있는 crew 생성.""" + llm = LLM(model="gpt-4o-mini") + search_tool = SerperDevTool() + + # 특정 역할을 가진 agent 정의 + researcher = Agent( + role="시니어 연구 분석가", + goal="AI 및 데이터 과학의 최첨단 발전 사항 발견", + backstory="""당신은 최고 수준의 기술 싱크탱크에서 근무합니다. + 새로운 트렌드를 식별하는 데 전문성이 있습니다. + 복잡한 데이터를 분석하고 실행 가능한 인사이트로 제시하는 데 뛰어납니다.""", + verbose=True, + allow_delegation=False, + llm=llm, + tools=[search_tool], + ) + + writer = Agent( + role="기술 콘텐츠 전략가", + goal="기술 발전에 대한 매력적인 콘텐츠 작성", + backstory="""당신은 통찰력 있고 흥미로운 기사로 유명한 콘텐츠 전략가입니다. + 복잡한 개념을 매력적인 스토리로 전환합니다.""", + verbose=True, + allow_delegation=True, + llm=llm, + ) + + # agent를 위한 작업 생성 + research_task = Task( + description="""{topic} 분야의 최신 발전 상황에 대한 포괄적인 분석을 수행하세요. + 주요 트렌드, 획기적 기술, 산업에 미칠 잠재적 영향을 식별하세요.""", + expected_output="주요 내용을 불릿 포인트로 정리한 전체 분석 보고서", + agent=researcher, + ) + + writing_task = Task( + description="""제공된 인사이트를 활용하여 + 가장 중요한 {topic} 발전 내용을 강조하는 흥미로운 블로그 글을 작성하세요. + 글은 정보성 있고, 기술에 밝은 독자를 대상으로 하면서 읽기 쉽게 써야 합니다. + 멋지게 들리도록 쓰되, 복잡한 단어는 피하여 AI처럼 들리지 않게 하세요.""", + expected_output="최소 4개의 단락으로 구성된 전체 블로그 글", + agent=writer, + context=[research_task], + ) + + # 순차 프로세스 방식으로 crew 인스턴스화 + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True, + process=Process.sequential + ) + + return crew + +def run_crew(): + """crew를 실행하고 결과 반환.""" + crew = create_crew() + result = crew.kickoff(inputs={"topic": "AI 발전"}) + return result + +# crew 실행 +if __name__ == "__main__": + # 이 모듈에서 계측이 이미 초기화됨 + result = run_crew() + print(result) +``` + +### 5단계: Braintrust에서 추적 보기 + +crew를 실행한 후, Braintrust에서 다양한 관점으로 포괄적인 추적을 볼 수 있습니다: + + + + + Braintrust Trace View + + + + + + Braintrust Timeline View + + + + + + Braintrust Thread View + + + + +### 6단계: SDK를 통한 평가 (실험) + +Braintrust의 Eval SDK를 사용하여 평가를 실행할 수도 있습니다. 이는 버전을 비교하거나 출력을 오프라인으로 점수화하는 데 유용합니다. 아래는 위에서 생성한 crew를 사용하는 Python 예제입니다: + +```python +from braintrust import Eval +from autoevals import Levenshtein + +def evaluate_crew_task(input_data): + """crew를 평가하기 위해 감싸는 작업 함수.""" + crew = create_crew() + result = crew.kickoff(inputs={"topic": input_data["topic"]}) + return str(result) + +Eval( + "AI 연구 Crew", # 프로젝트 이름 + { + "data": lambda: [ + {"topic": "artificial intelligence trends 2024"}, + {"topic": "machine learning breakthroughs"}, + {"topic": "AI ethics and governance"}, + ], + "task": evaluate_crew_task, + "scores": [Levenshtein], + }, +) +``` + +API 키를 설정하고 실행: + +```bash +export BRAINTRUST_API_KEY="YOUR_API_KEY" +braintrust eval eval_crew.py +``` + +자세한 내용은 [Braintrust Eval SDK 가이드](https://www.braintrust.dev/docs/start/eval-sdk)를 참조하세요. + +### Braintrust 통합의 주요 기능 + +- **포괄적인 추적**: 모든 agent 상호작용, 도구 사용 및 LLM 호출 추적 +- **성능 모니터링**: 실행 시간, 토큰 사용량 및 성공률 모니터링 +- **실험 추적**: 다른 crew 구성 및 모델 비교 +- **자동화된 평가**: crew 출력에 대한 사용자 정의 평가 메트릭 설정 +- **오류 추적**: crew 실행 전반에 걸친 실패 모니터링 및 디버깅 +- **비용 분석**: 토큰 사용량 및 관련 비용 추적 + +### 버전 호환성 정보 +- Python 3.8+ +- CrewAI >= 0.86.0 +- Braintrust >= 0.1.0 +- OpenTelemetry SDK >= 1.31.0 + +### 참고 자료 +- [Braintrust 문서](https://www.braintrust.dev/docs) - Braintrust 플랫폼 개요 +- [Braintrust CrewAI 통합](https://www.braintrust.dev/docs/integrations/crew-ai) - 공식 CrewAI 통합 가이드 +- [Braintrust Eval SDK](https://www.braintrust.dev/docs/start/eval-sdk) - SDK를 통한 실험 실행 +- [CrewAI 문서](https://docs.crewai.com/) - CrewAI 프레임워크 개요 +- [OpenTelemetry 문서](https://opentelemetry.io/docs/) - OpenTelemetry 가이드 +- [Braintrust GitHub](https://github.com/braintrustdata/braintrust) - Braintrust SDK 소스 코드 diff --git a/docs/v1.15.13/ko/observability/datadog.mdx b/docs/v1.15.13/ko/observability/datadog.mdx new file mode 100644 index 0000000000..38bc778ce0 --- /dev/null +++ b/docs/v1.15.13/ko/observability/datadog.mdx @@ -0,0 +1,109 @@ +--- +title: Datadog 통합 +description: Datadog을 CrewAI와 통합하여 LLM Observability 트레이스들을 Datadog에 제출하는 방법을 알아보세요. +icon: dog +mode: "wide" +--- + +# Datadog을 CrewAI와 통합하기 + +이 가이드에서는 Datadog 자동 계측을 사용하여 **Datadog**을 **CrewAI**와 통합하는 방법을 보여드립니다. 이 가이드가 끝나면 LLM Observability 트레이스를 Datadog에 제출하고 CrewAI 에이전트 실행을 Datadog LLM Observability의 에이전트 실행 보기에서 볼 수 있게 됩니다. + +## Datadog LLM Observability란 무엇인가요? + +[Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/)는 AI 엔지니어, 데이터 과학자, 애플리케이션 개발자가 LLM 애플리케이션을 신속하게 개발, 평가, 모니터링할 수 있도록 도와줍니다. 구조화된 실험, AI 에이전트 전반의 엔드투엔드 추적, 평가를 통해 결과물 품질, 성능, 비용, 전반적인 위험을 확실하게 개선할 수 있습니다. + +## 시작하기 + +### 설치 종속성 + +```shell +pip install ddtrace crewai crewai-tools +``` + +### 환경 변수 설정하기 + +Datadog API 키가 없는 경우, [계정 만들기](https://www.datadoghq.com/) 및 [API 키 받기](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys)를 할 수 있습니다. + +또한 다음 환경 변수에 ML 애플리케이션 이름을 지정해야 합니다. ML 애플리케이션은 특정 LLM 기반 애플리케이션과 관련된 LLM Observability 트레이스의 그룹입니다. ML 애플리케이션 이름 제한에 대한 자세한 내용은 [ML 애플리케이션 이름 지정 가이드라인](https://docs.datadoghq.com/llm_observability/instrumentation/sdk?tab=python#application-naming-guidelines)을 참조하세요. + +```shell +export DD_API_KEY= +export DD_SITE= +export DD_LLMOBS_ENABLED=true +export DD_LLMOBS_ML_APP= +export DD_LLMOBS_AGENTLESS_ENABLED=true +export DD_APM_TRACING_ENABLED=false +``` + +또한 LLM 공급자 API 키를 설정합니다. + +```shell +export OPENAI_API_KEY= +export ANTHROPIC_API_KEY= +export GEMINI_API_KEY= +... +``` + +### 크루AI 에이전트 애플리케이션 생성하기 + +```python +# crewai_agent.py +from crewai import Agent, Task, Crew + +from crewai_tools import ( + WebsiteSearchTool +) + +web_rag_tool = WebsiteSearchTool() + +writer = Agent( + role="작가", + goal="시를 통해 어린이들이 수학을 흥미롭고 이해하기 쉽게 설명합니다", + backstory="당신은 하이쿠를 쓰는 전문가이지만 수학은 전혀 모릅니다.", + tools=[web_rag_tool], +) + +task = Task( + description=("{곱셈}이란 무엇인가요?"), + expected_output=("답을 포함하는 하이쿠를 작성하세요."), + agent=writer +) + +crew = Crew( + agents=[writer], + tasks=[task], + share_crew=False +) + +output = crew.kickoff(dict(곱셈="2 * 2")) +``` + +### Datadog 자동 계측을 사용하여 애플리케이션 실행하기 + +[환경 변수](#환경-변수-설정하기)를 설정하면 이제 Datadog 자동 계측을 통해 애플리케이션을 실행할 수 있습니다. + +```shell +ddtrace-run python crewai_agent.py +``` + +### Datadog에서 트레이스 추적하기 + +애플리케이션을 실행한 후 왼쪽 상단 드롭다운에서 선택한 ML 애플리케이션 이름을 선택하면 [Datadog LLM Observability의 트레이스 보기](https://app.datadoghq.com/llm/traces)에서 트레이스들을 확인할 수 있습니다. + +트레이스를 클릭하면 사용된 총 토큰, LLM 호출 수, 사용된 모델, 예상 비용 등 트레이스에 대한 세부 정보가 표시됩니다. 특정 스팬(span)을 클릭하면 이러한 세부 정보의 범위가 좁혀지고 관련 입력, 출력 및 메타데이터가 표시됩니다. + + +Datadog LLM 옵저버빌리티 추적 보기 + + +또한, 트레이스의 제어 및 데이터 흐름을 보여주는 트레이스의 실행 그래프 보기를 볼 수 있으며, 이는 더 큰 에이전트로 확장하여 LLM 호출, 도구 호출 및 에이전트 상호 작용 간의 핸드오프와 관계를 보여줍니다. + + +Datadog LLM Observability 에이전트 실행 흐름 보기 + + +## 참조 + +- [Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/) +- [Datadog LLM 옵저버빌리티 크루AI 자동 계측](https://docs.datadoghq.com/llm_observability/instrumentation/auto_instrumentation?tab=python#crew-ai) diff --git a/docs/v1.15.13/ko/observability/galileo.mdx b/docs/v1.15.13/ko/observability/galileo.mdx new file mode 100644 index 0000000000..f82b825740 --- /dev/null +++ b/docs/v1.15.13/ko/observability/galileo.mdx @@ -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 trace view](/images/galileo-trace-veiw.png) + +## 갈릴레오 통합 이해 + +Galileo는 이벤트 리스너를 등록하여 CrewAI와 통합됩니다. +승무원 실행 이벤트(예: 에이전트 작업, 도구 호출, 모델 응답)를 캡처합니다. +관찰 가능성과 평가를 위해 이를 갈릴레오에 전달합니다. + +### 이벤트 리스너 이해 + +`CrewAIEventListener()` 인스턴스를 생성하는 것이 전부입니다. +CrewAI 실행을 위해 Galileo를 활성화하는 데 필요합니다. 인스턴스화되면 리스너는 다음을 수행합니다. + +-CrewAI에 자동으로 등록됩니다. +-환경 변수에서 Galileo 구성을 읽습니다. +-모든 실행 데이터를 Galileo 프로젝트 및 다음에서 지정한 로그 스트림에 기록합니다. + `GALILEO_PROJECT` 및 `GALILEO_LOG_STREAM` + +추가 구성이나 코드 변경이 필요하지 않습니다. +이 실행의 모든 데이터는 Galileo 프로젝트에 기록되며 +환경 구성에 따라 지정된 로그 스트림 +(예: GALILEO_PROJECT 및 GALILEO_LOG_STREAM) diff --git a/docs/v1.15.13/ko/observability/langdb.mdx b/docs/v1.15.13/ko/observability/langdb.mdx new file mode 100644 index 0000000000..6a5442f494 --- /dev/null +++ b/docs/v1.15.13/ko/observability/langdb.mdx @@ -0,0 +1,285 @@ +--- +title: LangDB 통합 +description: LangDB AI Gateway로 CrewAI 워크플로우를 관리, 보안, 최적화하세요—350개 이상의 모델 액세스, 자동 라우팅, 비용 최적화, 완전한 가시성을 제공합니다. +icon: database +mode: "wide" +--- + +# 소개 + +[LangDB AI Gateway](https://langdb.ai)는 여러 대형 언어 모델과의 연결을 지원하는 OpenAI 호환 API를 제공하며, 350개 이상의 언어 모델에 접근할 수 있도록 해주는 관측 플랫폼입니다. 단 한 번의 `init()` 호출로 모든 에이전트 상호작용, 작업 실행 및 LLM 호출이 캡처되어, 애플리케이션을 위한 종합적인 관측성과 프로덕션 수준의 AI 인프라를 제공합니다. + + + LangDB CrewAI trace example + + +**확인:** [실시간 추적 예시 보기](https://app.langdb.ai/sharing/threads/3becbfed-a1be-ae84-ea3c-4942867a3e22) + +## 기능 + +### AI 게이트웨이 기능 +- **350개 이상의 LLM 접근**: 단일 통합을 통해 모든 주요 언어 모델에 연결 +- **가상 모델**: 특정 매개변수와 라우팅 규칙으로 맞춤형 모델 구성 생성 +- **가상 MCP**: 에이전트 간 향상된 통신을 위해 MCP(Model Context Protocol) 시스템과의 호환성 및 통합 지원 +- **가드레일**: 에이전트 행동에 대한 안전 조치 및 컴플라이언스 제어 구현 + +### 가시성 및 추적 +- **자동 추적**: 단일 `init()` 호출로 모든 CrewAI 상호작용을 캡처 +- **엔드-투-엔드 가시성**: 에이전트 워크플로우를 시작부터 끝까지 모니터링 +- **도구 사용 추적**: 에이전트가 사용하는 도구와 그 결과를 추적 +- **모델 호출 모니터링**: LLM 상호작용에 대한 상세한 인사이트 제공 +- **성능 분석**: 지연 시간, 토큰 사용량 및 비용 모니터링 +- **디버깅 지원**: 문제 해결을 위한 단계별 실행 +- **실시간 모니터링**: 라이브 트레이스 및 메트릭 대시보드 + +## 설치 안내 + + + + CrewAI 기능 플래그와 함께 LangDB 클라이언트를 설치하세요: + ```bash + pip install 'pylangdb[crewai]' + ``` + + + LangDB 자격 증명을 구성하세요: + ```bash + export LANGDB_API_KEY="" + export LANGDB_PROJECT_ID="" + export LANGDB_API_BASE_URL='https://api.us-east-1.langdb.ai' + ``` + + + CrewAI 코드를 설정하기 전에 LangDB를 임포트하고 초기화하세요: + ```python + from pylangdb.crewai import init + # Initialize LangDB + init() + ``` + + + LangDB 헤더와 함께 LLM을 설정하세요: + ```python + from crewai import Agent, Task, Crew, LLM + import os + + # Configure LLM with LangDB headers + llm = LLM( + model="openai/gpt-4o", # Replace with the model you want to use + api_key=os.getenv("LANGDB_API_KEY"), + base_url=os.getenv("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.getenv("LANGDB_PROJECT_ID")} + ) + ``` + + + +## 빠른 시작 예제 + +여기 LangDB와 CrewAI를 시작하는 간단한 예제가 있습니다: + +```python +import os +from pylangdb.crewai import init +from crewai import Agent, Task, Crew, LLM + +# Initialize LangDB before any CrewAI imports +init() + +def create_llm(model): + return LLM( + model=model, + api_key=os.environ.get("LANGDB_API_KEY"), + base_url=os.environ.get("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.environ.get("LANGDB_PROJECT_ID")} + ) + +# Define your agent +researcher = Agent( + role="Research Specialist", + goal="Research topics thoroughly", + backstory="Expert researcher with skills in finding information", + llm=create_llm("openai/gpt-4o"), # Replace with the model you want to use + verbose=True +) + +# Create a task +task = Task( + description="Research the given topic and provide a comprehensive summary", + agent=researcher, + expected_output="Detailed research summary with key findings" +) + +# Create and run the crew +crew = Crew(agents=[researcher], tasks=[task]) +result = crew.kickoff() +print(result) +``` + +## 완성된 예제: Research and Planning Agent + +이 포괄적인 예제는 연구 및 기획 기능을 갖춘 multi-agent 워크플로우를 보여줍니다. + +### 사전 준비 사항 + +```bash +pip install crewai 'pylangdb[crewai]' crewai_tools setuptools python-dotenv +``` + +### 환경 설정 + +```bash +# LangDB credentials +export LANGDB_API_KEY="" +export LANGDB_PROJECT_ID="" +export LANGDB_API_BASE_URL='https://api.us-east-1.langdb.ai' + +# Additional API keys (optional) +export SERPER_API_KEY="" # For web search capabilities +``` + +### 전체 구현 + +```python +#!/usr/bin/env python3 + +import os +import sys +from pylangdb.crewai import init +init() # Initialize LangDB before any CrewAI imports +from dotenv import load_dotenv +from crewai import Agent, Task, Crew, Process, LLM +from crewai_tools import SerperDevTool + +load_dotenv() + +def create_llm(model): + return LLM( + model=model, + api_key=os.environ.get("LANGDB_API_KEY"), + base_url=os.environ.get("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.environ.get("LANGDB_PROJECT_ID")} + ) + +class ResearchPlanningCrew: + def researcher(self) -> Agent: + return Agent( + role="Research Specialist", + goal="Research topics thoroughly and compile comprehensive information", + backstory="Expert researcher with skills in finding and analyzing information from various sources", + tools=[SerperDevTool()], + llm=create_llm("openai/gpt-4o"), + verbose=True + ) + + def planner(self) -> Agent: + return Agent( + role="Strategic Planner", + goal="Create actionable plans based on research findings", + backstory="Strategic planner who breaks down complex challenges into executable plans", + reasoning=True, + max_reasoning_attempts=3, + llm=create_llm("openai/anthropic/claude-3.7-sonnet"), + verbose=True + ) + + def research_task(self) -> Task: + return Task( + description="Research the topic thoroughly and compile comprehensive information", + agent=self.researcher(), + expected_output="Comprehensive research report with key findings and insights" + ) + + def planning_task(self) -> Task: + return Task( + description="Create a strategic plan based on the research findings", + agent=self.planner(), + expected_output="Strategic execution plan with phases, goals, and actionable steps", + context=[self.research_task()] + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.researcher(), self.planner()], + tasks=[self.research_task(), self.planning_task()], + verbose=True, + process=Process.sequential + ) + +def main(): + topic = sys.argv[1] if len(sys.argv) > 1 else "Artificial Intelligence in Healthcare" + + crew_instance = ResearchPlanningCrew() + + # Update task descriptions with the specific topic + crew_instance.research_task().description = f"Research {topic} thoroughly and compile comprehensive information" + crew_instance.planning_task().description = f"Create a strategic plan for {topic} based on the research findings" + + result = crew_instance.crew().kickoff() + print(result) + +if __name__ == "__main__": + main() +``` + +### 예제 실행하기 + +```bash +python main.py "Sustainable Energy Solutions" +``` + +## LangDB에서 트레이스 보기 + +CrewAI 애플리케이션을 실행한 후, LangDB 대시보드에서 자세한 트레이스를 확인할 수 있습니다: + + + LangDB 트레이스 대시보드에서 CrewAI 워크플로우 표시 + + +### 볼 수 있는 내용 + +- **에이전트 상호작용**: 에이전트 대화 및 작업 인계의 전체 흐름 +- **도구 사용**: 호출된 도구, 입력값 및 출력값 +- **모델 호출**: 프롬프트 및 응답과 함께하는 상세 LLM 상호작용 +- **성능 지표**: 지연 시간, 토큰 사용량, 비용 추적 +- **실행 타임라인**: 전체 워크플로우의 단계별 보기 + +## 문제 해결 + +### 일반적인 문제 + +- **추적이 나타나지 않음**: `init()`이 CrewAI 임포트 이전에 호출되었는지 확인하세요 +- **인증 오류**: LangDB API 키와 프로젝트 ID를 확인하세요 + +## 리소스 + + + + 공식 LangDB 문서 및 가이드 + + + AI 에이전트 구축을 위한 단계별 튜토리얼 + + + CrewAI 통합 전체 예제 + + + 트레이스 및 분석 액세스 + + + 350개 이상의 사용 가능한 언어 모델 살펴보기 + + + 셀프 호스팅 옵션 및 엔터프라이즈 기능 + + + +## 다음 단계 + +이 가이드에서는 LangDB AI Gateway를 CrewAI와 통합하는 기본 사항을 다루었습니다. AI 워크플로우를 더욱 강화하려면 다음을 탐색해보세요: + +- **Virtual Models**: 라우팅 전략을 사용한 맞춤형 모델 구성 만들기 +- **Guardrails & Safety**: 콘텐츠 필터링 및 컴플라이언스 제어 구현 +- **Production Deployment**: 폴백, 재시도, 로드 밸런싱 구성 + +보다 고급 기능 및 사용 사례에 대해서는 [LangDB Documentation](https://docs.langdb.ai)을 방문하거나, [Model Catalog](https://app.langdb.ai/models)를 탐색하여 사용 가능한 모든 모델을 확인해 보세요. \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/langfuse.mdx b/docs/v1.15.13/ko/observability/langfuse.mdx new file mode 100644 index 0000000000..ceefceaee7 --- /dev/null +++ b/docs/v1.15.13/ko/observability/langfuse.mdx @@ -0,0 +1,110 @@ +--- +title: Langfuse 통합 +description: OpenLit을 사용하여 OpenTelemetry를 통해 CrewAI와 Langfuse를 통합하는 방법을 알아보세요 +icon: vials +mode: "wide" +--- + +# Langfuse와 CrewAI 통합하기 + +이 노트북은 **OpenLit** SDK를 통해 OpenTelemetry를 사용하여 **Langfuse**를 **CrewAI**와 통합하는 방법을 보여줍니다. 이 노트북을 마치면 Langfuse를 사용해 CrewAI 애플리케이션을 추적하여 가시성과 디버깅을 향상시킬 수 있습니다. + +> **Langfuse란 무엇인가요?** [Langfuse](https://langfuse.com)는 오픈 소스 LLM 엔지니어링 플랫폼입니다. 이는 LLM 애플리케이션을 위한 추적 및 모니터링 기능을 제공하며, 개발자들이 AI 시스템을 디버그, 분석 및 최적화하는 데 도움을 줍니다. Langfuse는 네이티브 통합, OpenTelemetry, API/SDK를 통해 다양한 도구 및 프레임워크와 연동됩니다. + +[![Langfuse Overview Video](https://github.com/user-attachments/assets/3926b288-ff61-4b95-8aa1-45d041c70866)](https://langfuse.com/watch-demo) + +## 시작하기 + +CrewAI를 사용하고 OpenLit을 통해 OpenTelemetry로 Langfuse와 통합하는 간단한 예제를 함께 살펴보겠습니다. + +### 1단계: 의존성 설치 + +```python +%pip install langfuse openlit crewai crewai_tools +``` + +### 2단계: 환경 변수 설정 + +Langfuse API 키를 설정하고 OpenTelemetry 내보내기 설정을 구성하여 trace를 Langfuse로 전송합니다. Langfuse OpenTelemetry 엔드포인트 `/api/public/otel` 및 인증과 관련된 자세한 내용은 [Langfuse OpenTelemetry 문서](https://langfuse.com/docs/opentelemetry/get-started)를 참고하십시오. + + +```python +import os + +# 프로젝트에 대한 키를 프로젝트 설정 페이지에서 확인하세요: https://cloud.langfuse.com +os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..." +os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..." +os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # 🇪🇺 EU 지역 +# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # 🇺🇸 US 지역 + + +# OpenAI 키 +os.environ["OPENAI_API_KEY"] = "sk-proj-..." +``` +환경 변수를 설정하면 이제 Langfuse 클라이언트를 초기화할 수 있습니다. get_client()는 환경 변수에 제공된 자격 증명을 사용하여 Langfuse 클라이언트를 초기화합니다. + +```python +from langfuse import get_client + +langfuse = get_client() + +# 연결 확인 +if langfuse.auth_check(): + print("Langfuse 클라이언트가 인증되었으며 준비되었습니다!") +else: + print("인증에 실패했습니다. 자격 증명과 호스트를 확인하세요.") +``` + +### 3단계: OpenLit 초기화 + +OpenLit OpenTelemetry 계측 SDK를 초기화하여 OpenTelemetry 추적을 수집하기 시작합니다. + +```python +import openlit + +openlit.init() +``` + +### 4단계: 간단한 CrewAI 애플리케이션 만들기 + +여러 에이전트가 협력하여 사용자의 질문에 답하는 간단한 CrewAI 애플리케이션을 만들어보겠습니다. + + +```python +from crewai import Agent, Task, Crew + +from crewai_tools import ( + WebsiteSearchTool +) + +web_rag_tool = WebsiteSearchTool() + +writer = Agent( + role="Writer", + goal="You make math engaging and understandable for young children through poetry", + backstory="You're an expert in writing haikus but you know nothing of math.", + tools=[web_rag_tool], + ) + +task = Task(description=("What is {multiplication}?"), + expected_output=("Compose a haiku that includes the answer."), + agent=writer) + +crew = Crew( + agents=[writer], + tasks=[task], + share_crew=False +) +``` + +### 5단계: Langfuse에서 트레이스 확인하기 + +에이전트를 실행한 후 [Langfuse](https://cloud.langfuse.com)에서 CrewAI 애플리케이션에서 생성된 트레이스를 확인할 수 있습니다. 여기서 LLM 상호작용의 자세한 단계들을 볼 수 있으며, 이를 통해 AI 에이전트의 디버깅 및 최적화에 도움이 됩니다. + +![Langfuse의 CrewAI 예시 트레이스](https://langfuse.com/images/cookbook/integration_crewai/crewai-example-trace.png) + +_[Langfuse의 공개 예시 트레이스](https://cloud.langfuse.com/project/cloramnkj0002jz088vzn1ja4/traces/e2cf380ffc8d47d28da98f136140642b?timestamp=2025-02-05T15%3A12%3A02.717Z&observation=3b32338ee6a5d9af)_ + +## 참고 자료 + +- [Langfuse OpenTelemetry 문서](https://langfuse.com/docs/opentelemetry/get-started) \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/langtrace.mdx b/docs/v1.15.13/ko/observability/langtrace.mdx new file mode 100644 index 0000000000..05848d5868 --- /dev/null +++ b/docs/v1.15.13/ko/observability/langtrace.mdx @@ -0,0 +1,73 @@ +--- +title: Langtrace 연동 +description: 외부 가시성 도구인 Langtrace를 사용하여 CrewAI 에이전트의 비용, 지연 시간 및 성능을 모니터링하는 방법. +icon: chart-line +mode: "wide" +--- + +# Langtrace 개요 + +Langtrace는 대형 언어 모델(LLM), LLM 프레임워크, 벡터 데이터베이스에 대한 관측 가능성과 평가를 설정할 수 있도록 도와주는 오픈소스 외부 도구입니다. +Langtrace는 CrewAI에 직접 내장되어 있지는 않지만, CrewAI와 함께 사용하여 CrewAI 에이전트의 비용, 지연 시간, 성능에 대해 깊이 있는 가시성을 확보할 수 있습니다. +이 통합을 통해 하이퍼파라미터를 기록하고, 성능 회귀를 모니터링하며, 에이전트의 지속적인 개선을 위한 프로세스를 수립할 수 있습니다. + +![에이전트 세션 실행 시리즈 개요](/images/langtrace1.png) +![에이전트 트레이스 개요](/images/langtrace2.png) +![상세한 llm 트레이스 개요](/images/langtrace3.png) + +## 설정 지침 + + + + [https://langtrace.ai/signup](https://langtrace.ai/signup)에서 가입하세요. + + + 프로젝트 유형을 `CrewAI`로 설정하고 API 키를 생성하세요. + + + 다음 명령어를 사용하세요: + + ```bash + pip install langtrace-python-sdk + ``` + + + 스크립트의 시작 부분, CrewAI를 임포트하기 전에 Langtrace를 임포트하고 초기화하세요: + + ```python + from langtrace_python_sdk import langtrace + langtrace.init(api_key='') + + # 이제 CrewAI 모듈을 임포트하세요 + from crewai import Agent, Task, Crew + ``` + + + +### 기능 및 CrewAI에의 적용 + +1. **LLM 토큰 및 비용 추적** + + - 각 CrewAI 에이전트 상호작용에 대한 토큰 사용량과 관련 비용을 모니터링합니다. + +2. **실행 단계에 대한 추적 그래프** + + - CrewAI 작업의 실행 흐름을 시각화하며, 지연 시간과 로그를 포함합니다. + - 에이전트 워크플로우의 병목 지점을 파악하는 데 유용합니다. + +3. **수동 주석을 통한 데이터셋 큐레이션** + + - 미래의 학습 또는 평가를 위해 CrewAI 작업 출력으로부터 데이터셋을 생성합니다. + +4. **프롬프트 버전 관리 및 관리** + + - CrewAI 에이전트에서 사용된 다양한 프롬프트 버전을 추적합니다. + - A/B 테스트 및 에이전트 성능 최적화에 유용합니다. + +5. **프롬프트 플레이그라운드 및 모델 비교** + + - 배포 전에 CrewAI 에이전트에 사용할 다양한 프롬프트와 모델을 테스트 및 비교합니다. + +6. **테스트 및 평가** + + - CrewAI 에이전트 및 작업에 대한 자동화된 테스트를 설정합니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/maxim.mdx b/docs/v1.15.13/ko/observability/maxim.mdx new file mode 100644 index 0000000000..2db6498240 --- /dev/null +++ b/docs/v1.15.13/ko/observability/maxim.mdx @@ -0,0 +1,227 @@ +--- +title: "Maxim Integration" +description: "에이전트 모니터링, 평가 및 가시성 시작" +icon: "infinity" +mode: "wide" +--- + +# Maxim 개요 + +Maxim AI는 귀하의 CrewAI 애플리케이션을 위한 포괄적인 에이전트 모니터링, 평가 및 가시성을 제공합니다. Maxim의 원라인 통합을 통해 에이전트 상호작용, 성능 지표 등을 손쉽게 추적하고 분석할 수 있습니다. + +## 특징 + +### 프롬프트 관리 + +Maxim의 프롬프트 관리 기능을 통해 CrewAI 에이전트를 위한 프롬프트를 생성, 조직, 최적화할 수 있습니다. 지침을 하드코딩하는 대신, Maxim의 SDK를 활용하여 버전 관리가 되는 프롬프트를 동적으로 가져오고 적용하세요. + + + + 플레이그라운드를 통해 프롬프트를 생성, 정제, 실험 및 배포할 수 있습니다. 폴더와 버전을 활용하여 프롬프트를 정리하고, 도구 및 컨텍스트를 연결하여 실제 사례로 실험해 보며, 맞춤형 로직을 기반으로 배포할 수 있습니다. + + [**모델 구성**](https://www.getmaxim.ai/docs/introduction/quickstart/setting-up-workspace#add-model-api-keys)을 통해 여러 모델을 손쉽게 실험하고, 프롬프트 플레이그라운드 상단 드롭다운에서 원하는 모델을 선택하세요. + + + + + 팀이 AI 애플리케이션을 개발할 때, 실험의 중요한 부분은 프롬프트 구조를 반복적으로 개선하는 것입니다. 효과적으로 협업하고 변경 사항을 명확히 정리할 수 있도록 Maxim은 프롬프트 버전 관리와 버전 간 비교 실행을 지원합니다. + + + + + AI 애플리케이션을 발전시켜 나가면서 프롬프트를 반복 개선하기 위해서는 모델, 프롬프트 구조 등 다양한 요소로 실험이 필요합니다. 버전 간 비교 및 변화에 대한 정보에 기반한 결정을 위해, 비교 플레이그라운드는 결과를 나란히 볼 수 있게 해줍니다. + + ## **프롬프트 비교를 왜 사용해야 하나요?** + + 프롬프트 비교는 여러 개의 단일 프롬프트를 하나의 뷰에서 볼 수 있도록 하여 다양한 워크플로에 streamlined 접근을 제공합니다: + + 1. **모델 비교**: 동일한 프롬프트에서 서로 다른 모델의 성능을 평가합니다. + 2. **프롬프트 최적화**: 여러 버전의 프롬프트를 비교하여 가장 효과적인 구성을 식별합니다. + 3. **교차 모델 일관성**: 동일한 프롬프트에 대해 여러 모델에서 일관된 출력을 보장합니다. + 4. **성능 벤치마킹**: 다양한 모델과 프롬프트에 대해 지연 시간, 비용, 토큰 수 등의 지표를 분석합니다. + + + +### 관찰 가능성 & 평가 + +Maxim AI는 CrewAI 에이전트에 대한 포괄적인 관찰 가능성과 평가 기능을 제공하여, 각 실행 과정에서 무슨 일이 일어나고 있는지 정확히 파악할 수 있도록 지원합니다. + + + + 에이전트의 전체 라이프사이클(도구 호출, 에이전트 궤적, 결정 플로우 등)을 손쉽게 추적할 수 있습니다. + + + + + 전체 트레이스 또는 개별 노드에 대해 상세 평가를 실행할 수 있으며, 다음 기능을 지원합니다: + + - 다중 단계 상호작용 및 세분화된 트레이스 분석 + - 세션 수준 평가 + - 실제 환경 시뮬레이션 테스트 + + + + + +

+ 필터 및 샘플링을 기준으로 UI에서 캡처된 로그를 자동으로 평가할 수 있습니다. +

+
+ +

+ 로그의 품질을 평가하고, 사람의 평가 또는 등급을 이용해 로그를 검토할 수 있습니다. +

+
+ +

+ 트레이스 또는 로그의 모든 컴포넌트를 평가하여 에이전트의 행동에 대한 통찰을 얻을 수 있습니다. +

+
+
+ --- +
+ + **오류**, **비용, 토큰 사용량, 사용자 피드백, 지연 시간**에 임계값을 설정하고, Slack 또는 PagerDuty를 통해 실시간 알림을 받아보세요. + + + + + 시간 경과에 따른 트레이스, 사용량 측정지표, 지연 시간 및 오류율을 손쉽게 시각화할 수 있습니다. + + + +
+ +## 시작하기 + +### 사전 준비 사항 + +- Python 버전 \>=3.10 +- Maxim 계정 ([여기에서 가입](https://getmaxim.ai/)) +- Maxim API 키 생성 +- CrewAI 프로젝트 + +### 설치 + +Maxim SDK를 pip을 통해 설치하세요: + +```python +pip install maxim-py +``` + +또는 `requirements.txt`에 추가하세요: + +``` +maxim-py +``` + +### 기본 설정 + +### 1. 환경 변수 설정 + +```python +### Environment Variables Setup + +# Create a `.env` file in your project root: + +# Maxim API Configuration +MAXIM_API_KEY=your_api_key_here +MAXIM_LOG_REPO_ID=your_repo_id_here +``` + +### 2. 필수 패키지 임포트하기 + +```python +from crewai import Agent, Task, Crew, Process +from maxim import Maxim +from maxim.logger.crewai import instrument_crewai +``` + +### 3. API 키로 Maxim 초기화하기 + +```python {8} +# Instrument CrewAI with just one line +instrument_crewai(Maxim().logger()) +``` + +### 4. 일반적으로 CrewAI 애플리케이션 생성 및 실행하기 + +```python +# Create your agent +researcher = Agent( + role='Senior Research Analyst', + goal='Uncover cutting-edge developments in AI', + backstory="You are an expert researcher at a tech think tank...", + verbose=True, + llm=llm +) + +# Define the task +research_task = Task( + description="Research the latest AI advancements...", + expected_output="", + agent=researcher +) + +# Configure and run the crew +crew = Crew( + agents=[researcher], + tasks=[research_task], + verbose=True +) + +try: + result = crew.kickoff() +finally: + maxim.cleanup() # Ensure cleanup happens even if errors occur +``` + +이제 끝입니다! 모든 CrewAI 에이전트 상호작용이 Maxim 대시보드에 기록되고 확인할 수 있습니다. + +간단한 참고를 위해 이 Google Colab Notebook을 확인하세요 - [Notebook](https://colab.research.google.com/drive/1ZKIZWsmgQQ46n8TH9zLsT1negKkJA6K8?usp=sharing) + +## 트레이스 보기 + +CrewAI 애플리케이션을 실행한 후: + +1. [Maxim 대시보드](https://app.getmaxim.ai/login)에 로그인하세요. +2. 리포지토리로 이동하세요. +3. 다음을 포함한 에이전트 트레이스를 상세하게 확인할 수 있습니다: + - 에이전트 대화 내역 + - 도구 사용 패턴 + - 성능 지표 + - 비용 분석 + + + +## 문제 해결 + +### 흔한 문제 + +- **추적(trace)가 나타나지 않음**: API 키와 저장소 ID가 올바른지 확인하세요. +- crew를 실행하기 **_전에_** 반드시 **`instrument_crewai()`를 호출**했는지 확인하세요. 이 함수가 로깅 훅(logging hook)을 올바르게 초기화합니다. +- 내부 오류를 드러내기 위해 `instrument_crewai()` 호출 시 `debug=True`로 설정하세요: + + ```python + instrument_crewai(logger, debug=True) + ``` +- 에이전트에서 상세 로그를 캡처하기 위해 `verbose=True`로 설정하세요: + + ```python + agent = CrewAgent(..., verbose=True) + ``` +- `instrument_crewai()`가 에이전트를 생성하거나 실행하기 **전에** 호출되는지 다시 한 번 확인하세요. 너무 당연해 보일 수 있지만, 자주 발생하는 실수입니다. + +## 리소스 + + + + 공식 CrewAI 문서 + + + 공식 Maxim 문서 + + + Maxim Github + + \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/mlflow.mdx b/docs/v1.15.13/ko/observability/mlflow.mdx new file mode 100644 index 0000000000..10edb565e0 --- /dev/null +++ b/docs/v1.15.13/ko/observability/mlflow.mdx @@ -0,0 +1,206 @@ +--- +title: MLflow 통합 +description: MLflow를 사용하여 에이전트 모니터링을 빠르게 시작하세요. +icon: bars-staggered +mode: "wide" +--- + +# MLflow 개요 + +[MLflow](https://mlflow.org/)는 머신러닝 실무자와 팀이 머신러닝 프로세스의 복잡성을 관리할 수 있도록 돕는 오픈소스 플랫폼입니다. + +MLflow는 귀하의 생성형 AI 애플리케이션에서 서비스 실행에 대한 상세 정보를 캡처하여 LLM 가시성을 향상시키는 트레이싱 기능을 제공합니다. +트레이싱은 요청의 각 중간 단계에 관련된 입력값, 출력값, 메타데이터를 기록하는 방법을 제공하여, 버그 및 예기치 않은 동작의 원인을 쉽게 찾아낼 수 있게 합니다. + +![MLflow crewAI 트레이싱 사용 개요](/images/mlflow-tracing.gif) + +### 기능 + +- **트레이싱 대시보드**: crewAI 에이전트의 활동을 입력값, 출력값, 스팬의 메타데이터와 함께 자세한 대시보드로 모니터링할 수 있습니다. +- **자동 트레이싱**: 완전 자동화된 crewAI 통합 기능으로, `mlflow.crewai.autolog()`를 실행하여 활성화할 수 있습니다. +- **약간의 노력만으로 수동 추적 계측**: 데코레이터, 함수 래퍼, 컨텍스트 매니저 등 MLflow의 고수준 fluent API를 통해 추적 계측을 커스터마이즈할 수 있습니다. +- **OpenTelemetry 호환성**: MLflow Tracing은 OpenTelemetry Collector로 트레이스를 내보내는 것을 지원하며, 이를 통해 Jaeger, Zipkin, AWS X-Ray 등 다양한 백엔드로 트레이스를 내보낼 수 있습니다. +- **에이전트 패키징 및 배포**: crewAI 에이전트를 다양한 배포 대상으로 추론 서버에 패키징 및 배포할 수 있습니다. +- **LLM을 안전하게 호스팅**: 여러 공급자의 LLM을 MFflow 게이트웨이를 통해 하나의 통합 엔드포인트에서 호스팅할 수 있습니다. +- **평가**: 편리한 API `mlflow.evaluate()`를 사용하여 다양한 지표로 crewAI 에이전트를 평가할 수 있습니다. + +## 설치 안내 + + + + ```shell + # crewAI 연동은 mlflow>=2.19.0 에서 사용할 수 있습니다. + pip install mlflow + ``` + + + ```shell + # 이 과정은 선택 사항이지만, MLflow 추적 서버를 사용하면 더 나은 시각화와 더 많은 기능을 사용할 수 있습니다. + mlflow server + ``` + + + 다음 두 줄을 애플리케이션 코드에 추가하세요: + + ```python + import mlflow + + mlflow.crewai.autolog() + + # 선택 사항: 추적 서버를 사용하는 경우 tracking URI와 experiment 이름을 설정할 수 있습니다. + mlflow.set_tracking_uri("http://localhost:5000") + mlflow.set_experiment("CrewAI") + ``` + + CrewAI Agents 추적 예시 사용법: + + ```python + from crewai import Agent, Crew, Task + from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + from crewai_tools import SerperDevTool, WebsiteSearchTool + + from textwrap import dedent + + content = "Users name is John. He is 30 years old and lives in San Francisco." + string_source = StringKnowledgeSource( + content=content, metadata={"preference": "personal"} + ) + + search_tool = WebsiteSearchTool() + + + class TripAgents: + def city_selection_agent(self): + return Agent( + role="City Selection Expert", + goal="Select the best city based on weather, season, and prices", + backstory="An expert in analyzing travel data to pick ideal destinations", + tools=[ + search_tool, + ], + verbose=True, + ) + + def local_expert(self): + return Agent( + role="Local Expert at this city", + goal="Provide the BEST insights about the selected city", + backstory="""A knowledgeable local guide with extensive information + about the city, it's attractions and customs""", + tools=[search_tool], + verbose=True, + ) + + + class TripTasks: + def identify_task(self, agent, origin, cities, interests, range): + return Task( + description=dedent( + f""" + Analyze and select the best city for the trip based + on specific criteria such as weather patterns, seasonal + events, and travel costs. This task involves comparing + multiple cities, considering factors like current weather + conditions, upcoming cultural or seasonal events, and + overall travel expenses. + Your final answer must be a detailed + report on the chosen city, and everything you found out + about it, including the actual flight costs, weather + forecast and attractions. + + Traveling from: {origin} + City Options: {cities} + Trip Date: {range} + Traveler Interests: {interests} + """ + ), + agent=agent, + expected_output="Detailed report on the chosen city including flight costs, weather forecast, and attractions", + ) + + def gather_task(self, agent, origin, interests, range): + return Task( + description=dedent( + f""" + As a local expert on this city you must compile an + in-depth guide for someone traveling there and wanting + to have THE BEST trip ever! + Gather information about key attractions, local customs, + special events, and daily activity recommendations. + Find the best spots to go to, the kind of place only a + local would know. + This guide should provide a thorough overview of what + the city has to offer, including hidden gems, cultural + hotspots, must-visit landmarks, weather forecasts, and + high level costs. + The final answer must be a comprehensive city guide, + rich in cultural insights and practical tips, + tailored to enhance the travel experience. + + Trip Date: {range} + Traveling from: {origin} + Traveler Interests: {interests} + """ + ), + agent=agent, + expected_output="Comprehensive city guide including hidden gems, cultural hotspots, and practical travel tips", + ) + + + class TripCrew: + def __init__(self, origin, cities, date_range, interests): + self.cities = cities + self.origin = origin + self.interests = interests + self.date_range = date_range + + def run(self): + agents = TripAgents() + tasks = TripTasks() + + city_selector_agent = agents.city_selection_agent() + local_expert_agent = agents.local_expert() + + identify_task = tasks.identify_task( + city_selector_agent, + self.origin, + self.cities, + self.interests, + self.date_range, + ) + gather_task = tasks.gather_task( + local_expert_agent, self.origin, self.interests, self.date_range + ) + + crew = Crew( + agents=[city_selector_agent, local_expert_agent], + tasks=[identify_task, gather_task], + verbose=True, + memory=True, + knowledge={ + "sources": [string_source], + "metadata": {"preference": "personal"}, + }, + ) + + result = crew.kickoff() + return result + + + trip_crew = TripCrew("California", "Tokyo", "Dec 12 - Dec 20", "sports") + result = trip_crew.run() + + print(result) + ``` + 더 많은 설정 및 사용 예시는 [MLflow Tracing 문서](https://mlflow.org/docs/latest/llms/tracing/index.html)를 참고하세요. + + + 이제 crewAI agents의 추적 정보가 MLflow에서 캡처됩니다. + MLflow 추적 서버에 접속하여 추적 내역을 확인하고 에이전트의 인사이트를 얻으세요. + + 브라우저에서 `127.0.0.1:5000`을 열어 MLflow 추적 서버에 접속하세요. + + MLflow tracing example with crewai + + + diff --git a/docs/v1.15.13/ko/observability/neatlogs.mdx b/docs/v1.15.13/ko/observability/neatlogs.mdx new file mode 100644 index 0000000000..c017048237 --- /dev/null +++ b/docs/v1.15.13/ko/observability/neatlogs.mdx @@ -0,0 +1,129 @@ +--- +title: Neatlogs 통합 +description: CrewAI agent 실행을 이해하고, 디버그하며, 공유하기 +icon: magnifying-glass-chart +mode: "wide" +--- + +# 소개 + +Neatlogs는 **에이전트가 무엇을 했는지**, **이유는 무엇인지**, 그리고 **공유하는 방법**을 확인할 수 있도록 도와줍니다. + +모든 단계를 캡처합니다: 생각, 도구 호출, 응답, 평가 등. 원시 로그는 없습니다. 명확하고 구조화된 추적만 제공합니다. 디버깅과 협업에 탁월합니다. + +## 왜 Neatlogs를 사용해야 하나요? + +CrewAI 에이전트는 여러 도구와 추론 단계를 사용합니다. 문제가 발생했을 때, 단순한 오류만으로는 충분하지 않습니다 — 맥락이 필요합니다. + +Neatlogs를 사용하면 다음과 같은 이점이 있습니다: + +- 전체 의사 결정 경로를 따라갈 수 있습니다 +- 단계마다 직접 피드백을 남길 수 있습니다 +- AI 어시스턴트와 함께 트레이스에 대해 채팅할 수 있습니다 +- 실행 결과를 공개적으로 공유해 피드백을 받을 수 있습니다 +- 인사이트를 업무로 전환할 수 있습니다 + +모두 한 곳에서 가능합니다. + +트레이스를 손쉽게 관리하세요 + +![Traces](/images/neatlogs-1.png) +![Trace Response](/images/neatlogs-2.png) + +CrewAI 트레이스를 보기 위한 최고의 UX. 원하는 곳 어디든 댓글을 남기세요. AI를 활용해 디버깅할 수 있습니다. + +![Trace Details](/images/neatlogs-3.png) +![Ai Chat Bot With A Trace](/images/neatlogs-4.png) +![Comments Drawer](/images/neatlogs-5.png) + +## 핵심 기능 + +- **Trace Viewer**: 사고, 도구, 결정을 순서대로 추적 +- **인라인 댓글**: 모든 trace 단계에서 팀원을 태그 +- **피드백 및 평가**: 출력물을 올바름 또는 틀림으로 표시 +- **오류 하이라이팅**: API/도구 실패 자동 감지 +- **작업 전환**: 댓글을 할당된 작업으로 변환 +- **Ask the Trace (AI)**: Neatlogs AI 봇과 trace에서 채팅 +- **공개 공유**: trace 링크를 커뮤니티에 게시 + +## CrewAI로 빠른 설정하기 + + + + [neatlogs.com](https://neatlogs.com/?utm_source=crewAI-docs)에 방문하여 프로젝트를 생성하고, API 키를 복사하세요. + + + ```bash + pip install neatlogs + ``` + (최신 버전 0.8.0, Python 3.8+; MIT 라이선스) + + + Crew 에이전트를 시작하기 전에 다음을 추가하세요: + + ```python + import neatlogs + neatlogs.init("YOUR_PROJECT_API_KEY") + ``` + + 에이전트는 평소와 같이 실행됩니다. Neatlogs가 모든 것을 자동으로 캡처합니다. + + + + +## 내부 구조 + +GitHub에 따르면, Neatlogs는: + +- 생각, 도구 호출, 응답, 오류, 그리고 토큰 통계를 캡처합니다 +- AI 기반 작업 생성과 견고한 평가 워크플로우를 지원합니다 + +이 모든 것이 단 두 줄의 코드로 가능합니다. + +## 작동하는 모습을 살펴보기 + +### 🔍 전체 데모 (4 분) + + + +### ⚙️ CrewAI 통합 (30초) + + + +## 링크 & 지원 + +- 📘 [Neatlogs 문서](https://docs.neatlogs.com/) +- 🔐 [대시보드 & API 키](https://app.neatlogs.com/) +- 🐦 [트위터 팔로우](https://twitter.com/neatlogs) +- 📧 문의: hello@neatlogs.com +- 🛠 [GitHub SDK](https://github.com/NeatLogs/neatlogs) + +## TL;DR + +아래와 같이: + +```bash +pip install neatlogs + +import neatlogs +neatlogs.init("YOUR_API_KEY") + +You can now capture, understand, share, and act on your CrewAI agent runs in seconds. +No setup overhead. Full trace transparency. Full team collaboration. +``` + +이제 몇 초 만에 CrewAI agent 실행을 캡처, 이해, 공유하고 바로 조치할 수 있습니다. +별도의 설정이 필요하지 않습니다. 완전한 트레이스 투명성. 전체 팀 협업 지원. diff --git a/docs/v1.15.13/ko/observability/openlit.mdx b/docs/v1.15.13/ko/observability/openlit.mdx new file mode 100644 index 0000000000..68ecdd55ef --- /dev/null +++ b/docs/v1.15.13/ko/observability/openlit.mdx @@ -0,0 +1,181 @@ +--- +title: OpenLIT 통합 +description: OpenTelemetry와 함께 단 한 줄의 코드로 에이전트를 신속하게 모니터링을 시작하세요. +icon: magnifying-glass-chart +mode: "wide" +--- + +# OpenLIT 개요 + +[OpenLIT](https://github.com/openlit/openlit?src=crewai-docs)은 오픈 소스 도구로, 단 **한** 줄의 코드만으로 AI 에이전트, LLM, VectorDB, GPU의 성능을 간편하게 모니터링할 수 있습니다. + +OpenTelemetry-기반의 트레이싱 및 메트릭을 제공하여 비용, 지연 시간, 상호작용, 작업 시퀀스와 같은 주요 파라미터를 추적할 수 있습니다. +이 설정을 통해 하이퍼파라미터를 추적하고 성능 문제를 모니터링하며, 시간이 지남에 따라 에이전트를 개선하고 미세 조정할 방법을 찾을 수 있습니다. + + + 비용 및 토큰을 포함한 에이전트 사용 개요 + 에이전트 otel 트레이스 및 메트릭 개요 + 에이전트 트레이스 상세 개요 + + +### 기능 + +- **분석 대시보드**: 에이전트의 상태와 성능을 모니터링할 수 있는 대시보드를 통해 지표, 비용, 사용자 상호작용을 자세히 추적할 수 있습니다. +- **OpenTelemetry-네이티브 가시성 SDK**: Grafana, DataDog 등 기존 가시성 도구로 추적 및 지표를 전송할 수 있는 벤더 중립적 SDK를 제공합니다. +- **커스텀 및 파인튜닝 모델 비용 추적**: 정확한 예산 책정을 위해 커스텀 가격 파일을 사용하여 특정 모델의 비용 추정치를 맞춤화할 수 있습니다. +- **예외 모니터링 대시보드**: 모니터링 대시보드를 통해 일반적인 예외 및 오류를 추적하여 문제를 신속하게 찾아내고 해결할 수 있습니다. +- **컴플라이언스 및 보안**: 욕설 및 PII 유출과 같은 잠재적인 위협을 탐지합니다. +- **프롬프트 인젝션 탐지**: 잠재적인 코드 인젝션 및 비밀 유출을 식별합니다. +- **API 키 및 비밀 관리**: LLM API 키와 비밀을 중앙에서 안전하게 관리하여 안전하지 않은 관행을 방지합니다. +- **프롬프트 관리**: PromptHub을 사용하여 에이전트 프롬프트를 관리 및 버전 관리하고, 모든 에이전트에서 일관되고 쉽게 접근할 수 있습니다. +- **모델 플레이그라운드**: 배포 전에 CrewAI 에이전트에 사용할 다양한 모델을 테스트하고 비교할 수 있습니다. + +## 설치 안내 + + + + + + ```shell + git clone git@github.com:openlit/openlit.git + ``` + + + [OpenLIT 저장소](https://github.com/openlit/openlit)의 루트 디렉토리에서 아래 명령어를 실행하세요: + ```shell + docker compose up -d + ``` + + + + + ```shell + pip install openlit + ``` + + + 아래 두 줄을 애플리케이션 코드에 추가하세요: + + + ```python + import openlit + openlit.init(otlp_endpoint="http://127.0.0.1:4318") + ``` + + CrewAI Agent 모니터링 예제: + + ```python + from crewai import Agent, Task, Crew, Process + import openlit + + openlit.init(disable_metrics=True) + # 에이전트 정의 + researcher = Agent( + role="Researcher", + goal="Conduct thorough research and analysis on AI and AI agents", + backstory="You're an expert researcher, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently researching for a new client.", + allow_delegation=False, + llm='command-r' + ) + + + # 작업 정의 + task = Task( + description="Generate a list of 5 interesting ideas for an article, then write one captivating paragraph for each idea that showcases the potential of a full article on this topic. Return the list of ideas with their paragraphs and your notes.", + expected_output="5 bullet points, each with a paragraph and accompanying notes.", + ) + + # 매니저 에이전트 정의 + manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success. Your role is to coordinate the efforts of the crew members, ensuring that each task is completed on time and to the highest standard.", + allow_delegation=True, + llm='command-r' + ) + + # 커스텀 매니저로 crew 인스턴스화 + crew = Crew( + agents=[researcher], + tasks=[task], + manager_agent=manager, + process=Process.hierarchical, + ) + + # crew 작업 시작 + result = crew.kickoff() + + print(result) + ``` + + + + 아래 두 줄을 애플리케이션 코드에 추가하세요: + ```python + import openlit + + openlit.init() + ``` + + OTEL export endpoint를 설정하려면 다음 명령어를 실행하세요: + ```shell + export OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4318" + ``` + + CrewAI Async Agent 모니터링 예제: + + ```python + import asyncio + from crewai import Crew, Agent, Task + import openlit + + openlit.init(otlp_endpoint="http://127.0.0.1:4318") + + # 코드 실행이 활성화된 에이전트 생성 + coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True, + llm="command-r" + ) + + # 코드 실행이 필요한 작업 생성 + data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="5 bullet points, each with a paragraph and accompanying notes.", + ) + + # crew 생성 후 작업 추가 + analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] + ) + + # crew를 비동기적으로 kickoff 하는 함수 + async def async_crew_execution(): + result = await analysis_crew.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + + # 비동기 함수 실행 + asyncio.run(async_crew_execution()) + ``` + + + 더 고급 설정 및 사용 사례는 OpenLIT [Python SDK 저장소](https://github.com/openlit/openlit/tree/main/sdk/python)를 참고하세요. + + + 이제 에이전트 관찰 데이터가 수집되어 OpenLIT으로 전송되고 있으므로, 다음 단계는 이 데이터를 시각화하고 분석하여 에이전트의 성능, 행동 및 개선이 필요한 영역에 대한 인사이트를 얻는 것입니다. + + 브라우저에서 `127.0.0.1:3000`으로 접속하여 바로 시작할 수 있습니다. 기본 자격 증명으로 로그인 가능합니다 + - **이메일**: `user@openlit.io` + - **비밀번호**: `openlituser` + + + 비용 및 토큰을 포함한 에이전트 사용 개요 + 에이전트 otel trace 및 메트릭 개요 + + + + \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/opik.mdx b/docs/v1.15.13/ko/observability/opik.mdx new file mode 100644 index 0000000000..cbc891bf75 --- /dev/null +++ b/docs/v1.15.13/ko/observability/opik.mdx @@ -0,0 +1,131 @@ +--- +title: Opik 통합 +description: Comet Opik을 사용하여 CrewAI 애플리케이션을 포괄적인 트레이싱, 자동 평가, 프로덕션 준비 대시보드로 디버그, 평가 및 모니터링하는 방법을 알아보세요. +icon: meteor +mode: "wide" +--- + +# Opik 개요 + +[Comet Opik](https://www.comet.com/docs/opik/)을(를) 사용하여, 포괄적인 트레이싱, 자동 평가, 프로덕션 준비가 된 대시보드를 통해 LLM 애플리케이션, RAG 시스템, 에이전트 워크플로우를 디버깅, 평가 및 모니터링할 수 있습니다. + + + CrewAI와 함께하는 Opik 에이전트 모니터링 예시 + + +Opik은 CrewAI 애플리케이션 개발의 모든 단계에서 포괄적인 지원을 제공합니다: + +- **로그 트레이스 및 스팬**: 개발 및 프로덕션 시스템에서 LLM 호출과 애플리케이션 로직을 자동으로 추적하여 디버깅 및 분석이 가능합니다. 프로젝트 간 응답을 수동 또는 프로그램적으로 주석 달고, 조회하고, 비교할 수 있습니다. +- **LLM 애플리케이션 성능 평가**: 사용자 지정 테스트 세트로 평가하고, 내장된 평가 지표를 실행하거나 SDK 또는 UI에서 사용자만의 지표를 정의할 수 있습니다. +- **CI/CD 파이프라인 내 테스트**: PyTest 기반의 Opik LLM 단위 테스트로 신뢰할 수 있는 성능 기준선을 설정하세요. 프로덕션에서 연속 모니터링을 위한 온라인 평가도 실행할 수 있습니다. +- **프로덕션 데이터 모니터링 및 분석**: 프로덕션에서 보지 못한 데이터에 대한 모델의 성능을 이해하고, 새로운 개발 반복을 위한 데이터 세트를 생성할 수 있습니다. + +## 설치 + +Comet은 호스팅된 Opik 플랫폼을 제공하거나, 로컬에서 플랫폼을 실행할 수도 있습니다. + +호스팅 버전을 사용하려면 [무료 Comet 계정 만들기](https://www.comet.com/signup?utm_medium=github&utm_source=crewai_docs) 후 API 키를 발급받으세요. + +Opik 플랫폼을 로컬에서 실행하려면, [설치 가이드](https://www.comet.com/docs/opik/self-host/overview/)에서 자세한 정보를 확인하세요. + +이 가이드에서는 CrewAI의 빠른 시작 예제를 사용합니다. + + + + ```shell + pip install crewai crewai-tools opik --upgrade + ``` + + + ```python + import opik + opik.configure(use_local=False) + ``` + + + 먼저, LLM 제공업체의 API 키를 환경 변수로 설정합니다: + + ```python + import os + import getpass + + if "OPENAI_API_KEY" not in os.environ: + os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ") + ``` + + + 첫 번째 단계는 프로젝트를 만드는 것입니다. CrewAI 문서의 예제를 사용하겠습니다: + + ```python + from crewai import Agent, Crew, Task, Process + + + class YourCrewName: + def agent_one(self) -> Agent: + return Agent( + role="Data Analyst", + goal="Analyze data trends in the market", + backstory="An experienced data analyst with a background in economics", + verbose=True, + ) + + def agent_two(self) -> Agent: + return Agent( + role="Market Researcher", + goal="Gather information on market dynamics", + backstory="A diligent researcher with a keen eye for detail", + verbose=True, + ) + + def task_one(self) -> Task: + return Task( + name="Collect Data Task", + description="Collect recent market data and identify trends.", + expected_output="A report summarizing key trends in the market.", + agent=self.agent_one(), + ) + + def task_two(self) -> Task: + return Task( + name="Market Research Task", + description="Research factors affecting market dynamics.", + expected_output="An analysis of factors influencing the market.", + agent=self.agent_two(), + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.agent_one(), self.agent_two()], + tasks=[self.task_one(), self.task_two()], + process=Process.sequential, + verbose=True, + ) + + ``` + + 이제 Opik의 추적기를 임포트하고 crew를 실행할 수 있습니다: + + ```python + from opik.integrations.crewai import track_crewai + + track_crewai(project_name="crewai-integration-demo") + + my_crew = YourCrewName().crew() + result = my_crew.kickoff() + + print(result) + ``` + CrewAI 애플리케이션을 실행한 후에는 Opik 앱에서 다음을 확인할 수 있습니다: + - LLM 추적, span, 메타데이터 + - 에이전트 상호작용 및 태스크 실행 흐름 + - 지연 시간, 토큰 사용량 등의 성능 지표 + - 평가 지표(내장형 또는 사용자 정의) + + + +## 리소스 + +- [🦉 Opik 문서](https://www.comet.com/docs/opik/) +- [👉 Opik + CrewAI Colab](https://colab.research.google.com/github/comet-ml/opik/blob/main/apps/opik-documentation/documentation/docs/cookbook/crewai.ipynb) +- [🐦 X](https://x.com/cometml) +- [💬 Slack](https://slack.comet.com/) \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/overview.mdx b/docs/v1.15.13/ko/observability/overview.mdx new file mode 100644 index 0000000000..32f71e2cc4 --- /dev/null +++ b/docs/v1.15.13/ko/observability/overview.mdx @@ -0,0 +1,120 @@ +--- +title: "개요" +description: "포괄적인 관측 도구로 CrewAI agent를 모니터링, 평가 및 최적화하세요" +icon: "face-smile" +mode: "wide" +--- + +## CrewAI를 위한 관측 가능성 + +관측 가능성은 CrewAI 에이전트의 성능을 이해하고, 병목 현상을 식별하며, 프로덕션 환경에서 신뢰할 수 있는 운영을 보장하는 데 매우 중요합니다. 이 섹션에서는 에이전트 워크플로우에 대한 모니터링, 평가, 최적화 기능을 제공하는 다양한 도구와 플랫폼을 다룹니다. + +## 관측 가능성이 중요한 이유 + +- **성능 모니터링**: 에이전트 실행 시간, 토큰 사용량, 자원 소비량 추적 +- **품질 보증**: 다양한 시나리오에서 출력 품질과 일관성 평가 +- **디버깅**: 에이전트 동작 및 태스크 실행에서의 문제 식별 및 해결 +- **비용 관리**: LLM API 사용량 및 관련 비용 모니터링 +- **지속적인 개선**: 시간 경과에 따른 에이전트 성능 최적화를 위한 인사이트 수집 + +## 사용 가능한 Observability 도구 + +### 모니터링 & 트레이싱 플랫폼 + + + + + 자동 에이전트 상호작용 캡처를 포함한 CrewAI 워크플로의 엔드-투-엔드 트레이싱. + + + + 비용 추적 및 성능 분석 기능이 포함된 OpenTelemetry 네이티브 모니터링. + + + + 트레이싱 및 평가 기능을 갖춘 머신러닝 라이프사이클 관리. + + + + 상세한 트레이싱과 분석을 제공하는 LLM 엔지니어링 플랫폼. + + + + LLM 및 에이전트 프레임워크를 위한 오픈소스 관측성 지원. + + + + 모니터링 및 문제 해결을 위한 AI 관측성 플랫폼. + + + + 종합적인 모니터링 및 신뢰성 기능을 갖춘 AI 게이트웨이. + + + + 포괄적인 트레이싱을 통한 LLM 애플리케이션 디버깅, 평가, 모니터링. + + + + AI 애플리케이션의 추적 및 평가를 위한 Weights & Biases 플랫폼. + + + +### 평가 및 품질 보증 + + + + LLM 출력 및 에이전트 행동에 대한 종합 평가 플랫폼입니다. + + + +## 주요 관측성 메트릭스 + +### 성능 지표 +- **실행 시간**: 에이전트가 작업을 완료하는 데 걸리는 시간 +- **토큰 사용량**: LLM 호출 시 소비된 입력/출력 토큰 +- **API 지연 시간**: 외부 서비스의 응답 시간 +- **성공률**: 성공적으로 완료된 작업의 비율 + +### 품질 지표 +- **출력 정확성**: 에이전트 응답의 정확성 +- **일관성**: 유사한 입력에 대한 신뢰성 +- **관련성**: 출력이 기대 결과와 얼마나 잘 일치하는지 +- **안전성**: 콘텐츠 정책 및 가이드라인 준수 + +### 비용 지표 +- **API 비용**: LLM 제공자 사용에 따른 지출 +- **리소스 활용**: 컴퓨팅 및 메모리 사용량 +- **작업당 비용**: 에이전트 운영의 경제적 효율성 +- **예산 추적**: 지출 한도 대비 모니터링 + +## 시작하기 + +1. **도구 선택하기**: 필요에 맞는 Observability 플랫폼을 선택하세요 +2. **코드 계측하기**: CrewAI 애플리케이션에 모니터링을 추가하세요 +3. **대시보드 설정하기**: 주요 지표에 대한 시각화를 구성하세요 +4. **알림 정의하기**: 중요한 이벤트에 대한 알림을 생성하세요 +5. **기준선 설정하기**: 비교를 위한 초기 성능을 측정하세요 +6. **반복 및 개선**: 인사이트를 활용하여 에이전트를 최적화하세요 + +## 모범 사례 + +### 개발 단계 +- 에이전트 행동을 이해하기 위해 상세 트레이싱 사용 +- 개발 초기에 평가 지표 구현 +- 테스트 중 리소스 사용량 모니터링 +- 자동화된 품질 검사 설정 + +### 운영 단계 +- 포괄적인 모니터링 및 알림 구현 +- 시간 경과에 따른 성능 추이 추적 +- 이상 현상 및 성능 저하 모니터링 +- 비용 가시성 및 통제 유지 + +### 지속적인 개선 +- 정기적인 성과 리뷰 및 최적화 +- 다양한 에이전트 구성의 A/B 테스트 +- 품질 향상을 위한 피드백 루프 +- 교훈 문서화 + +사용 사례, 인프라, 모니터링 요구 사항에 가장 적합한 observability 도구를 선택하여 CrewAI 에이전트가 신뢰성 있고 효율적으로 작동하도록 하세요. \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/patronus-evaluation.mdx b/docs/v1.15.13/ko/observability/patronus-evaluation.mdx new file mode 100644 index 0000000000..23e037ad6e --- /dev/null +++ b/docs/v1.15.13/ko/observability/patronus-evaluation.mdx @@ -0,0 +1,206 @@ +--- +title: Patronus AI 평가 +description: Patronus AI의 종합 평가 플랫폼을 사용하여 CrewAI 에이전트의 성능과 LLM 출력 및 에이전트 행동을 모니터링하고 평가합니다. +icon: shield-check +mode: "wide" +--- + +# Patronus AI 평가 + +## 개요 + +[Patronus AI](https://patronus.ai)는 CrewAI 에이전트를 위한 종합적인 평가 및 모니터링 기능을 제공하여, 모델 출력, 에이전트 동작, 전체 시스템 성능을 평가할 수 있게 해줍니다. 이 통합을 통해 품질과 신뢰성을 유지하기 위한 지속적인 평가 워크플로우를 프로덕션 환경에 구현할 수 있습니다. + +## 주요 기능 + +- **자동 평가**: 에이전트 출력 및 행동의 실시간 평가 +- **맞춤 기준**: 사용 사례에 맞게 특정 평가 기준 정의 +- **성능 모니터링**: 에이전트 성능 지표를 시간에 따라 추적 +- **품질 보증**: 다양한 시나리오에서 일관된 출력 품질 보장 +- **안전성 및 준수**: 잠재적인 문제 및 정책 위반 모니터링 + +## 평가 도구 + +Patronus는 다양한 사용 사례를 위한 세 가지 주요 평가 도구를 제공합니다: + +1. **PatronusEvalTool**: 에이전트가 평가 작업에 가장 적합한 평가자와 기준을 선택할 수 있도록 합니다. +2. **PatronusPredefinedCriteriaEvalTool**: 사용자가 지정한 미리 정의된 평가자와 기준을 사용합니다. +3. **PatronusLocalEvaluatorTool**: 사용자가 정의한 커스텀 함수 평가자를 사용합니다. + +## 설치 + +이 도구들을 사용하려면 Patronus 패키지를 설치해야 합니다: + +```shell +uv add patronus +``` + +또한 Patronus API 키를 환경 변수로 설정해야 합니다: + +```shell +export PATRONUS_API_KEY="your_patronus_api_key" +``` + +## 시작 단계 + +Patronus 평가 도구를 효과적으로 사용하려면 다음 단계를 따르세요: + +1. **Patronus 설치**: 위의 명령어를 사용하여 Patronus 패키지를 설치합니다. +2. **API 키 설정**: Patronus API 키를 환경 변수로 설정합니다. +3. **적합한 도구 선택**: 필요에 따라 적절한 Patronus 평가 도구를 선택합니다. +4. **도구 구성**: 필요한 파라미터로 도구를 구성합니다. + +## 예시 + +### PatronusEvalTool 사용하기 + +다음 예제는 에이전트가 가장 적합한 평가자와 평가 기준을 선택할 수 있도록 해주는 `PatronusEvalTool`의 사용 방법을 보여줍니다: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusEvalTool + +# Initialize the tool +patronus_eval_tool = PatronusEvalTool() + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code and verify that the output is code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate and evaluate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence. Select the most appropriate evaluator and criteria for evaluating your output.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +### PatronusPredefinedCriteriaEvalTool 사용하기 + +다음 예제는 미리 정의된 evaluator와 criteria를 사용하는 `PatronusPredefinedCriteriaEvalTool`의 사용 방법을 보여줍니다: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusPredefinedCriteriaEvalTool + +# Initialize the tool with predefined criteria +patronus_eval_tool = PatronusPredefinedCriteriaEvalTool( + evaluators=[{"evaluator": "judge", "criteria": "contains-code"}] +) + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +### PatronusLocalEvaluatorTool 사용하기 + +다음 예시는 커스텀 함수 평가자를 사용하는 `PatronusLocalEvaluatorTool`의 사용 방법을 보여줍니다: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusLocalEvaluatorTool +from patronus import Client, EvaluationResult +import random + +# Initialize the Patronus client +client = Client() + +# Register a custom evaluator +@client.register_local_evaluator("random_evaluator") +def random_evaluator(**kwargs): + score = random.random() + return EvaluationResult( + score_raw=score, + pass_=score >= 0.5, + explanation="example explanation", + ) + +# Initialize the tool with the custom evaluator +patronus_eval_tool = PatronusLocalEvaluatorTool( + patronus_client=client, + evaluator="random_evaluator", + evaluated_model_gold_answer="example label", +) + +# Define an agent that uses the tool +coding_agent = Agent( + role="Coding Agent", + goal="Generate high quality code", + backstory="An experienced coder who can generate high quality python code.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate code +generate_code_task = Task( + description="Create a simple program to generate the first N numbers in the Fibonacci sequence.", + expected_output="Program that generates the first N numbers in the Fibonacci sequence.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +## 파라미터 + +### PatronusEvalTool + +`PatronusEvalTool`은(는) 초기화 시에 어떠한 매개변수도 필요로 하지 않습니다. Patronus API에서 사용 가능한 평가자와 기준을 자동으로 가져옵니다. + +### PatronusPredefinedCriteriaEvalTool + +`PatronusPredefinedCriteriaEvalTool`은(는) 초기화 시 다음과 같은 파라미터를 받습니다: + +- **evaluators**: 필수. 사용할 evaluator와 criteria가 포함된 딕셔너리의 리스트입니다. 예시: `[{"evaluator": "judge", "criteria": "contains-code"}]`. + +### PatronusLocalEvaluatorTool + +`PatronusLocalEvaluatorTool`은(는) 초기화 시 다음과 같은 파라미터를 허용합니다: + +- **patronus_client**: 필수. Patronus 클라이언트 인스턴스입니다. +- **evaluator**: 선택 사항. 사용할 등록된 로컬 evaluator의 이름입니다. 기본값은 빈 문자열입니다. +- **evaluated_model_gold_answer**: 선택 사항. 평가에 사용할 gold answer입니다. 기본값은 빈 문자열입니다. + +## 사용법 + +Patronus 평가 도구를 사용할 때, 모델 입력, 출력 및 컨텍스트를 제공하면 도구가 Patronus API로부터 평가 결과를 반환합니다. + +`PatronusEvalTool` 및 `PatronusPredefinedCriteriaEvalTool`을 호출할 때는 다음과 같은 매개변수가 필요합니다: + +- **evaluated_model_input**: 에이전트의 작업 설명(간단한 텍스트). +- **evaluated_model_output**: 에이전트의 작업 결과. +- **evaluated_model_retrieved_context**: 에이전트의 컨텍스트. + +`PatronusLocalEvaluatorTool`의 경우에도 동일한 매개변수가 필요하지만, 평가자와 정답은 초기화 시에 지정합니다. + +## 결론 + +Patronus 평가 도구는 Patronus AI 플랫폼을 사용하여 모델 입력 및 출력을 평가하고 점수를 매길 수 있는 강력한 방법을 제공합니다. 에이전트가 자신의 출력 또는 다른 에이전트의 출력을 평가할 수 있도록 함으로써, 이러한 도구는 CrewAI 워크플로의 품질과 신뢰성을 향상시키는 데 도움을 줄 수 있습니다. \ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/portkey.mdx b/docs/v1.15.13/ko/observability/portkey.mdx new file mode 100644 index 0000000000..019cb35ea8 --- /dev/null +++ b/docs/v1.15.13/ko/observability/portkey.mdx @@ -0,0 +1,821 @@ +--- +title: Portkey 통합 +description: CrewAI에서 Portkey를 사용하는 방법 +icon: key +mode: "wide" +--- + +Portkey CrewAI 헤더 이미지 + +## 소개 + +Portkey는 CrewAI에 프로덕션 적합성을 위한 기능을 추가하여 실험적인 agent crew를 다음과 같이 견고한 시스템으로 전환합니다. + +- **모든 agent 단계, 도구 사용, 상호작용에 대한 완전한 관찰 가능성** +- **내장된 신뢰성**: 폴백, 재시도, 로드 밸런싱 기능 제공 +- **AI 비용 관리**를 위한 비용 추적 및 최적화 +- **단일 통합을 통한 200개 이상의 LLM 접근** +- **agent의 행동을 안전하고 규정 준수로 유지하는 가드레일** +- **일관된 agent 성능을 위한 버전 관리되는 prompt** + +### 설치 및 설정 + + + +```bash +pip install -U crewai portkey-ai +``` + + + +[Portkey 대시보드](https://app.portkey.ai/)에서 예산/속도 제한을 선택적으로 설정하여 Portkey API 키를 생성하세요. 이 키에는 신뢰성, 캐싱 등 여러 가지 구성을 추가로 적용할 수 있습니다. 자세한 내용은 추후 설명합니다. + + + +통합은 매우 간단합니다. CrewAI 설정의 LLM 구성을 다음과 같이 업데이트하기만 하면 됩니다: + +```python +from crewai import LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Portkey 통합으로 LLM 인스턴스 생성 +gpt_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", # Virtual key를 사용하므로 이 값은 단순한 placeholder입니다. + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_LLM_VIRTUAL_KEY", + trace_id="unique-trace-id", # 요청 추적을 위한 선택 사항 + ) +) + +#Crew Agents에서 다음처럼 사용하세요: + + @agent + def lead_market_analyst(self) -> Agent: + return Agent( + config=self.agents_config['lead_market_analyst'], + verbose=True, + memory=False, + llm=gpt_llm + ) + +``` + + +**Virtual Key란?** Portkey의 Virtual Key는 LLM 제공업체의 API 키(OpenAI, Anthropic 등)를 암호화된 금고에 안전하게 저장합니다. 이를 통해 키 교체 및 예산 관리를 더 쉽게 할 수 있습니다. [Virtual Key에 대해 자세히 알아보기](https://portkey.ai/docs/product/ai-gateway/virtual-keys). + + + + +## 프로덕션 기능 + +### 1. 향상된 가시성 + +Portkey는 CrewAI agent에 대한 종합적인 가시성을 제공하여 각 실행 중에 어떤 일이 일어나고 있는지 정확히 이해할 수 있게 도와줍니다. + + + + + + + +Traces는 crew의 실행을 계층적으로 보여주며, LLM 호출, 도구 호출, 상태 전환의 순서를 확인할 수 있습니다. + +```python +# Portkey에서 계층적 추적을 활성화하려면 trace_id를 추가하세요 +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + trace_id="unique-session-id" # 고유한 trace ID 추가 + ) +) +``` + + + + + + + +Portkey는 LLM과의 모든 상호작용을 로그로 남깁니다. 여기에는 다음이 포함됩니다: + +- 전체 요청 및 응답 페이로드 +- 지연 시간 및 토큰 사용량 지표 +- 비용 계산 +- 도구 호출 및 함수 실행 + +모든 로그는 메타데이터, trace ID, 모델 등으로 필터링할 수 있어 특정 crew 실행을 쉽게 디버깅할 수 있습니다. + + + + + + + +Portkey는 사용자가 다음을 할 수 있도록 지원하는 내장 대시보드를 제공합니다: + +- 모든 crew 실행에서 비용 및 토큰 사용량 추적 +- 지연 시간, 성공률과 같은 성능 지표 분석 +- agent workflow의 병목 지점 식별 +- 서로 다른 crew 구성 및 LLM 비교 + +사용자는 모든 지표를 사용자 정의 메타데이터별로 필터링 및 세분화하여 특정 crew 유형, 사용자 그룹 또는 사용 사례를 분석할 수 있습니다. + + + + + Analytics with metadata filters + + +CrewAI LLM 구성에 사용자 정의 메타데이터를 추가하여 강력한 필터링 및 세분화를 활성화할 수 있습니다: + +```python +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + metadata={ + "crew_type": "research_crew", + "environment": "production", + "_user": "user_123", # 사용자 분석을 위한 특수 _user 필드 + "request_source": "mobile_app" + } + ) +) +``` + +이 메타데이터는 Portkey 대시보드에서 로그, trace, 지표를 필터링하는 데 사용될 수 있으며, 특정 crew 실행, 사용자 또는 환경을 분석할 수 있습니다. + + + +### 2. 신뢰성 - Crew를 원활하게 운영하세요 + +프로덕션에서 crew를 운영할 때, API 속도 제한, 네트워크 이슈 또는 공급자 장애와 같이 문제가 발생할 수 있습니다. Portkey의 신뢰성 기능은 문제가 발생해도 에이전트가 원활하게 동작하도록 보장합니다. + +Portkey Config를 사용하여 CrewAI 설정에서 페일오버를 간단하게 활성화할 수 있습니다: + +```python +from crewai import LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Create LLM with fallback configuration +portkey_llm = LLM( + model="gpt-4o", + max_tokens=1000, + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + config={ + "strategy": { + "mode": "fallback" + }, + "targets": [ + { + "provider": "openai", + "api_key": "YOUR_OPENAI_API_KEY", + "override_params": {"model": "gpt-4o"} + }, + { + "provider": "anthropic", + "api_key": "YOUR_ANTHROPIC_API_KEY", + "override_params": {"model": "claude-3-opus-20240229"} + } + ] + } + ) +) + +# Use this LLM configuration with your agents +``` + +이 설정은 GPT-4o 요청이 실패할 경우 자동으로 Claude를 시도하여 crew가 계속 운영될 수 있도록 보장합니다. + + + + 일시적인 실패를 자동으로 처리합니다. LLM 호출에 실패하면 Portkey가 지정된 횟수만큼 동일한 요청을 재시도합니다. 속도 제한이나 네트워크 장애에서 완벽하게 사용할 수 있습니다. + + + 에이전트가 멈추는 것을 방지합니다. 타임아웃을 설정하여 요구되는 시간 내에 응답을 받거나(혹은 우아하게 실패할 수 있도록) 합니다. + + + 다양한 요청을 다양한 공급자에게 보낼 수 있습니다. 복잡한 reasoning은 GPT-4로, 창의적인 작업은 Claude로, 빠른 응답은 Gemini로 필요에 따라 라우팅하세요. + + + 기본 공급자가 실패해도 계속 운영됩니다. 백업 공급자로 자동으로 전환되어 가용성을 유지합니다. + + + 여러 API 키 또는 공급자에 요청을 분산시킵니다. 대량 crew 운영 및 속도 제한 내에서 작업할 때 유용합니다. + + + +### 3. CrewAI에서의 프롬프트 사용 + +Portkey의 Prompt Engineering Studio는 CrewAI 에이전트에서 사용하는 프롬프트를 생성, 관리, 최적화하도록 도와줍니다. 프롬프트나 지시문을 하드코딩하는 대신 Portkey의 프롬프트 렌더링 API를 사용하여 버전 관리된 프롬프트를 동적으로 가져와 적용할 수 있습니다. + + +![Prompt Playground Interface](https://raw.githubusercontent.com/siddharthsambharia-portkey/Portkey-Product-Images/refs/heads/main/CrewAI%20Portkey%20Docs.webp) + + + + +Prompt Playground는 여러분의 AI 애플리케이션을 위해 완벽한 프롬프트를 비교, 테스트, 배포할 수 있는 공간입니다. 이곳은 다양한 모델을 실험하고, 변수들을 테스트하며, 출력값을 비교하고, 배포 전에 프롬프트 엔지니어링 전략을 다듬을 수 있는 곳입니다. 이를 통해 다음과 같은 작업이 가능합니다: + +1. 에이전트에서 사용하기 전에 프롬프트를 반복적으로 개발 +2. 다양한 변수와 모델로 프롬프트 테스트 +3. 서로 다른 프롬프트 버전의 출력값 비교 +4. 팀원들과 프롬프트 개발 협업 + +이 시각적 환경을 통해 CrewAI 에이전트 워크플로우의 각 단계에 효과적인 프롬프트를 쉽게 작성할 수 있습니다. + + + +Prompt Render API를 통해 모든 파라미터가 구성된 프롬프트 템플릿을 가져올 수 있습니다: + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL, Portkey + +# Initialize Portkey admin client +portkey_admin = Portkey(api_key="YOUR_PORTKEY_API_KEY") + +# Retrieve prompt using the render API +prompt_data = portkey_client.prompts.render( + prompt_id="YOUR_PROMPT_ID", + variables={ + "agent_role": "Senior Research Scientist", + } +) + +backstory_agent_prompt=prompt_data.data.messages[0]["content"] + + +# Set up LLM with Portkey integration +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY" + ) +) + +# Create agent using the rendered prompt +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory=backstory_agent, # Use the rendered prompt + verbose=True, + llm=portkey_llm +) +``` + + + +다음과 같은 작업을 수행할 수 있습니다: +- 동일한 프롬프트의 여러 버전을 생성 +- 버전 간의 성능 비교 +- 필요시 이전 버전으로 롤백 +- 코드에서 사용할 버전을 지정: + +```python +# Use a specific prompt version +prompt_data = portkey_admin.prompts.render( + prompt_id="YOUR_PROMPT_ID@version_number", + variables={ + "agent_role": "Senior Research Scientist", + "agent_goal": "Discover groundbreaking insights" + } +) +``` + + + +Portkey 프롬프트는 손쉬운 변수 치환을 위해 머스태시(Mustache) 스타일의 템플릿을 사용합니다: + +``` +You are a {{agent_role}} with expertise in {{domain}}. + +Your mission is to {{agent_goal}} by leveraging your knowledge +and experience in the field. + +Always maintain a {{tone}} tone and focus on providing {{focus_area}}. +``` + +렌더링할 때는 변수를 간단하게 전달하면 됩니다: + +```python +prompt_data = portkey_admin.prompts.render( + prompt_id="YOUR_PROMPT_ID", + variables={ + "agent_role": "Senior Research Scientist", + "domain": "artificial intelligence", + "agent_goal": "discover groundbreaking insights", + "tone": "professional", + "focus_area": "practical applications" + } +) +``` + + + + + Portkey의 프롬프트 관리 기능에 대해 더 알아보기 + + +### 4. 안전한 Crew를 위한 가드레일 + +가드레일은 CrewAI agent가 모든 상황에서 안전하게 작동하고 적절하게 응답하도록 보장합니다. + +**가드레일을 사용하는 이유는 무엇인가요?** + +CrewAI agent는 다양한 실패 모드를 경험할 수 있습니다: +- 유해하거나 부적절한 콘텐츠 생성 +- PII와 같은 민감 정보 유출 +- 잘못된 정보의 환각 +- 잘못된 형식의 출력 생성 + +Portkey의 가드레일은 입력과 출력 모두에 대한 보호를 추가합니다. + +**가드레일 구현하기** + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Create LLM with guardrails +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "input_guardrails": ["guardrails-id-xxx", "guardrails-id-yyy"], + "output_guardrails": ["guardrails-id-zzz"] + } + ) +) + +# Create agent with guardrailed LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +Portkey의 가드레일은 다음을 수행할 수 있습니다: +- 입력 및 출력의 PII 감지 및 마스킹 +- 유해하거나 부적절한 콘텐츠 필터링 +- 응답 형식을 스키마에 따라 검증 +- 근거 자료와 비교하여 환각 여부 확인 +- 맞춤형 비즈니스 로직 및 규칙 적용 + + + Portkey의 가드레일 기능을 탐색하여 agent의 안전성을 높여보세요 + + +### 5. 메타데이터로 사용자 추적 + +Portkey의 메타데이터 시스템을 사용하여 CrewAI 에이전트를 통해 개별 사용자를 추적할 수 있습니다. + +**Portkey에서의 메타데이터란?** + +메타데이터를 사용하면 각 요청에 사용자 지정 데이터를 연결할 수 있어 필터링, 세분화, 분석이 가능합니다. 특별한 `_user` 필드는 사용자 추적을 위해 특별히 설계되었습니다. + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# 사용자 추적이 설정된 LLM 구성 +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + metadata={ + "_user": "user_123", # 사용자 분석을 위한 특별 _user 필드 + "user_tier": "premium", + "user_company": "Acme Corp", + "session_id": "abc-123" + } + ) +) + +# 추적된 LLM으로 에이전트 생성 +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +**사용자별로 분석 필터링** + +메타데이터가 설정되어 있으면, 사용자별로 분석을 필터링하고 사용자 단위의 성능 지표를 분석할 수 있습니다: + + + + + +이를 통해 다음이 가능합니다: +- 사용자별 비용 추적 및 예산 관리 +- 개인화된 사용자 분석 +- 팀 또는 조직 단위의 지표 +- 환경별 모니터링(스테이징 vs. 프로덕션) + + + 맞춤형 메타데이터를 활용하여 분석 기능을 향상시키는 방법을 살펴보세요 + + +### 6. 효율적인 Crews를 위한 캐싱 + +캐싱을 구현하여 CrewAI agent를 보다 효율적이고 비용 효율적으로 만드세요: + + + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLM with simple caching +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "cache": { + "mode": "simple" + } + } + ) +) + +# Create agent with cached LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +Simple 캐싱은 입력 프롬프트에 대한 정확한 일치 항목을 수행하며, 동일한 요청을 캐시에 저장하여 중복된 모델 실행을 방지합니다. + + + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLM with semantic caching +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "cache": { + "mode": "semantic" + } + } + ) +) + +# Create agent with semantically cached LLM +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +Semantic 캐싱은 입력 요청 간의 맥락적 유사성을 고려하여, 의미적으로 유사한 입력에 대한 응답을 캐시에 저장합니다. + + + +### 7. 모델 상호 운용성 + +CrewAI는 여러 LLM 제공업체를 지원하며, Portkey는 통합 인터페이스를 통해 200개 이상의 LLM에 대한 액세스를 제공함으로써 이 기능을 확장합니다. 코어 에이전트 로직을 변경하지 않고도 다양한 모델 간에 쉽게 전환할 수 있습니다: + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Set up LLMs with different providers +openai_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY" + ) +) + +anthropic_llm = LLM( + model="claude-3-5-sonnet-latest", + max_tokens=1000, + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_ANTHROPIC_VIRTUAL_KEY" + ) +) + +# Choose which LLM to use for each agent based on your needs +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=openai_llm # Use anthropic_llm for Anthropic +) +``` + +Portkey는 다음을 포함한 제공업체의 LLM에 액세스를 제공합니다: + +- OpenAI (GPT-4o, GPT-4 Turbo 등) +- Anthropic (Claude 3.5 Sonnet, Claude 3 Opus 등) +- Mistral AI (Mistral Large, Mistral Medium 등) +- Google Vertex AI (Gemini 1.5 Pro 등) +- Cohere (Command, Command-R 등) +- AWS Bedrock (Claude, Titan 등) +- 로컬/프라이빗 모델 + + + Portkey에서 지원하는 전체 LLM 제공업체 목록 보기 + + +## CrewAI를 위한 엔터프라이즈 거버넌스 설정 + +**엔터프라이즈 거버넌스가 필요한 이유** +조직 내에서 CrewAI를 사용하는 경우, 여러 거버넌스 측면을 고려해야 합니다: +- **비용 관리**: 팀별 AI 사용 비용 통제 및 추적 +- **접근 제어**: 특정 팀이 특정 모델을 사용할 수 있도록 관리 +- **사용 분석**: 조직 전반에서 AI 사용 현황 파악 +- **보안 및 컴플라이언스**: 엔터프라이즈 수준의 보안 기준 유지 +- **신뢰성**: 모든 사용자에게 일관된 서비스 제공 보장 + +Portkey는 이러한 엔터프라이즈 요구를 해결하는 종합적인 거버넌스 계층을 추가합니다. 이제 이러한 컨트롤을 단계별로 구현해보겠습니다. + + + +Virtual Key는 Portkey의 안전한 LLM 공급자 API 키 관리 방식입니다. 주요 제어 기능을 제공합니다: +- API 사용에 대한 예산 제한 +- 속도 제한(Rate limiting) 기능 +- 안전한 API 키 저장 + +Virtual Key를 생성하려면: +Portkey 앱에서 [Virtual Keys](https://app.portkey.ai/virtual-keys)로 이동하세요. Virtual Key ID를 저장하고 복사하세요. + + + + + + +Virtual Key ID를 저장하세요. 다음 단계에서 필요합니다. + + + + +Portkey에서 Config는 요청 라우팅 방식을 정의하며, 고급 라우팅·폴백·재시도 등 기능을 제공합니다. + +Config를 생성하려면: +1. Portkey 대시보드의 [Configs](https://app.portkey.ai/configs)로 이동 +2. 아래와 같은 새 config 생성: + ```json + { + "virtual_key": "YOUR_VIRTUAL_KEY_FROM_STEP1", + "override_params": { + "model": "gpt-4o" // 선호하는 모델명 + } + } + ``` +3. Config 이름을 저장하고 다음 단계에 사용하세요. + + + + + + + +이제 Portkey API 키를 생성하고, 2단계에서 만든 config에 연결하세요: + +1. Portkey의 [API Keys](https://app.portkey.ai/api-keys)로 이동해 새 API 키 생성 +2. `2단계`에서 만든 config 선택 +3. API 키를 생성 및 저장 + + + + + + + +Portkey API 키와 config를 설정한 후, 이를 CrewAI agent에 연결하세요: + +```python +from crewai import Agent, LLM +from portkey_ai import PORTKEY_GATEWAY_URL + +# API 키로 LLM 구성 +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="YOUR_PORTKEY_API_KEY" +) + +# Portkey가 적용된 LLM으로 agent 생성 +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + + + + + + +### 1단계: 예산 통제 및 속도 제한 구현 + +Virtual Keys를 사용하면 팀/부서 수준에서 LLM 접근을 세밀하게 제어할 수 있습니다. 이를 통해 다음과 같은 이점이 있습니다: +- [예산 한도](https://portkey.ai/docs/product/ai-gateway/virtual-keys/budget-limits) 설정 +- 속도 제한을 통해 예기치 않은 사용량 급증 방지 +- 부서별 지출 추적 + +#### 부서별 제어 설정하기: +1. Portkey 대시보드에서 [Virtual Keys](https://app.portkey.ai/virtual-keys)로 이동하세요. +2. 각 부서마다 예산 한도와 속도 제한이 포함된 새로운 Virtual Key를 생성하세요. +3. 부서별 한도를 구성하세요. + + + + + + + + +### 단계 2: 모델 접근 규칙 정의 + +AI 사용이 확장됨에 따라, 각 팀이 특정 모델에 접근할 수 있도록 제어하는 것이 중요해집니다. Portkey Configs는 다음과 같은 기능을 제공하여 이러한 제어 계층을 지원합니다: + +#### 접근 제어 기능: +- **모델 제한**: 특정 모델에 대한 액세스 제한 +- **데이터 보호**: 민감한 데이터에 대한 가드레일 구현 +- **신뢰성 제어**: 폴백 및 재시도 로직 추가 + +#### 예시 구성: +다음은 OpenAI, 특히 GPT-4o로 요청을 라우팅하는 기본 구성입니다: + +```json +{ + "strategy": { + "mode": "single" + }, + "targets": [ + { + "virtual_key": "YOUR_OPENAI_VIRTUAL_KEY", + "override_params": { + "model": "gpt-4o" + } + } + ] +} +``` + +Portkey 대시보드에서 [구성 페이지](https://app.portkey.ai/configs)에서 자신의 구성을 생성하세요. + + +구성은 언제든지 업데이트하여 실행 중인 애플리케이션에 영향을 주지 않고 제어를 조정할 수 있습니다. + + + + +### 3단계: 액세스 제어 구현 + +사용자별 API 키를 생성하면 자동으로 다음을 수행합니다: +- 가상 키를 활용하여 사용자/팀별 사용량 추적 +- 요청 라우팅을 위한 적절한 구성 적용 +- 로그를 필터링하기 위한 관련 메타데이터 수집 +- 액세스 권한 적용 + +[Portkey App](https://app.portkey.ai/)를 통해 API 키를 생성하세요 + +Python SDK를 사용한 예시: +```python +from portkey_ai import Portkey + +portkey = Portkey(api_key="YOUR_ADMIN_API_KEY") + +api_key = portkey.api_keys.create( + name="engineering-team", + type="organisation", + workspace_id="YOUR_WORKSPACE_ID", + defaults={ + "config_id": "your-config-id", + "metadata": { + "environment": "production", + "department": "engineering" + } + }, + scopes=["logs.view", "configs.read"] +) +``` + +자세한 키 관리 방법은 [Portkey 문서](https://portkey.ai/docs)를 참조하세요. + + + +### 4단계: 배포 및 모니터링 +팀원들에게 API 키를 배포한 후, 엔터프라이즈 준비가 완료된 CrewAI 설정이 준비됩니다. 이제 각 팀원은 지정된 API 키로 적절한 액세스 수준 및 예산 제어와 함께 사용할 수 있습니다. + +Portkey 대시보드에서 사용량 모니터링: +- 부서별 비용 추적 +- 모델 사용 패턴 +- 요청량 +- 오류율 + + + + + + +### 엔터프라이즈 기능이 이제 사용 가능합니다 +**귀하의 CrewAI 통합에는 이제 다음과 같은 기능이 포함됩니다:** +- 부서별 예산 관리 +- 모델 접근 거버넌스 +- 사용량 추적 및 귀속 +- 보안 가드레일 +- 신뢰성 기능 + + +## 자주 묻는 질문 + + + + Portkey는 종합적인 가시성(트레이스, 로그, 메트릭), 신뢰성 기능(폴백, 재시도, 캐싱) 및 통합 인터페이스를 통한 200개 이상의 LLM 접속을 통해 CrewAI에 프로덕션 환경에 적합한 기능을 추가합니다. 이를 통해 에이전트 애플리케이션을 더 쉽게 디버깅, 최적화, 확장할 수 있습니다. + + + + 네! Portkey는 기존 CrewAI 애플리케이션과 매끄럽게 통합됩니다. LLM 구성 코드를 Portkey가 적용된 버전으로 업데이트하기만 하면 됩니다. 나머지 에이전트 및 crew 코드는 변경하지 않아도 됩니다. + + + + Portkey는 에이전트, 도구, human-in-the-loop 워크플로우, 모든 태스크 프로세스 유형(순차적, 계층적 등)을 포함하여 모든 CrewAI 기능을 지원합니다. 프레임워크의 기능에 제한을 두지 않으면서 가시성과 신뢰성을 추가합니다. + + + + 네, Portkey를 사용하면 crew 내 여러 에이전트에 일관된 `trace_id`를 적용하여 전체 워크플로우를 추적할 수 있습니다. 특히 여러 에이전트가 포함된 복잡한 crew에서 전체 실행 경로를 파악할 때 유용합니다. + + + + Portkey를 통해 LLM 구성에 사용자 지정 메타데이터를 추가할 수 있으며, 이를 필터링에 활용할 수 있습니다. `crew_name`, `crew_type`, `session_id`와 같은 필드를 추가해 손쉽게 특정 crew 실행을 찾아 분석할 수 있습니다. + + + + 네! Portkey는 다양한 LLM 제공업체에 대해 사용자의 API 키를 사용합니다. API 키를 가상 키로 안전하게 저장하여, 코드 변경 없이 쉽게 키를 관리하고 교체할 수 있습니다. + + + + +## 자료 + + + +

공식 CrewAI 문서

+
+ +

이 통합 구현에 대한 맞춤형 안내를 받아보세요

+
+
\ No newline at end of file diff --git a/docs/v1.15.13/ko/observability/tracing.mdx b/docs/v1.15.13/ko/observability/tracing.mdx new file mode 100644 index 0000000000..eae6188f60 --- /dev/null +++ b/docs/v1.15.13/ko/observability/tracing.mdx @@ -0,0 +1,214 @@ +--- +title: CrewAI Tracing +description: CrewAI AMP 플랫폼을 사용한 CrewAI Crews 및 Flows의 내장 추적 +icon: magnifying-glass-chart +mode: "wide" +--- + +# CrewAI 내장 추적 (Built-in Tracing) + +CrewAI는 Crews와 Flows를 실시간으로 모니터링하고 디버깅할 수 있는 내장 추적 기능을 제공합니다. 이 가이드는 CrewAI의 통합 관측 가능성 플랫폼을 사용하여 **Crews**와 **Flows** 모두에 대한 추적을 활성화하는 방법을 보여줍니다. + +> **CrewAI Tracing이란?** CrewAI의 내장 추적은 agent 결정, 작업 실행 타임라인, 도구 사용, LLM 호출을 포함한 AI agent에 대한 포괄적인 관측 가능성을 제공하며, 모두 [CrewAI AMP 플랫폼](https://app.crewai.com)을 통해 액세스할 수 있습니다. + +![CrewAI Tracing Interface](/images/crewai-tracing.png) + +## 사전 요구 사항 + +CrewAI 추적을 사용하기 전에 다음이 필요합니다: + +1. **CrewAI AMP 계정**: [app.crewai.com](https://app.crewai.com)에서 무료 계정에 가입하세요 +2. **CLI 인증**: CrewAI CLI를 사용하여 로컬 환경을 인증하세요 + +```bash +crewai login +``` + +## 설정 지침 + +### 1단계: CrewAI AMP 계정 생성 + +[app.crewai.com](https://app.crewai.com)을 방문하여 무료 계정을 만드세요. 이를 통해 추적, 메트릭을 보고 crews를 관리할 수 있는 CrewAI AMP 플랫폼에 액세스할 수 있습니다. + +### 2단계: CrewAI CLI 설치 및 인증 + +아직 설치하지 않았다면 CLI 도구와 함께 CrewAI를 설치하세요: + +```bash +uv add 'crewai[tools]' +``` + +그런 다음 CrewAI AMP 계정으로 CLI를 인증하세요: + +```bash +crewai login +``` + +이 명령은 다음을 수행합니다: + +1. 브라우저에서 인증 페이지를 엽니다 +2. 장치 코드를 입력하라는 메시지를 표시합니다 +3. CrewAI AMP 계정으로 로컬 환경을 인증합니다 +4. 로컬 개발을 위한 추적 기능을 활성화합니다 + +### 3단계: Crew에서 추적 활성화 + +`tracing` 매개변수를 `True`로 설정하여 Crew에 대한 추적을 활성화할 수 있습니다: + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool + +# Define your agents +researcher = Agent( + role="Senior Research Analyst", + goal="Uncover cutting-edge developments in AI and data science", + backstory=\"\"\"You work at a leading tech think tank. + Your expertise lies in identifying emerging trends. + You have a knack for dissecting complex data and presenting actionable insights.\"\"\", + verbose=True, + tools=[SerperDevTool()], +) + +writer = Agent( + role="Tech Content Strategist", + goal="Craft compelling content on tech advancements", + backstory=\"\"\"You are a renowned Content Strategist, known for your insightful and engaging articles. + You transform complex concepts into compelling narratives.\"\"\", + verbose=True, +) + +# Create tasks for your agents +research_task = Task( + description=\"\"\"Conduct a comprehensive analysis of the latest advancements in AI in 2024. + Identify key trends, breakthrough technologies, and potential industry impacts.\"\"\", + expected_output="Full analysis report in bullet points", + agent=researcher, +) + +writing_task = Task( + description=\"\"\"Using the insights provided, develop an engaging blog + post that highlights the most significant AI advancements. + Your post should be informative yet accessible, catering to a tech-savvy audience.\"\"\", + expected_output="Full blog post of at least 4 paragraphs", + agent=writer, +) + +# Enable tracing in your crew +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + tracing=True, # Enable built-in tracing + verbose=True +) + +# Execute your crew +result = crew.kickoff() +``` + +### 4단계: Flow에서 추적 활성화 + +마찬가지로 CrewAI Flows에 대한 추적을 활성화할 수 있습니다: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + counter: int = 0 + message: str = "" + +class ExampleFlow(Flow[ExampleState]): + def __init__(self): + super().__init__(tracing=True) # Enable tracing for the flow + + @start() + def first_method(self): + print("Starting the flow") + self.state.counter = 1 + self.state.message = "Flow started" + return "continue" + + @listen("continue") + def second_method(self): + print("Continuing the flow") + self.state.counter += 1 + self.state.message = "Flow continued" + return "finish" + + @listen("finish") + def final_method(self): + print("Finishing the flow") + self.state.counter += 1 + self.state.message = "Flow completed" + +# Create and run the flow with tracing enabled +flow = ExampleFlow(tracing=True) +result = flow.kickoff() +``` + +### 5단계: CrewAI AMP 대시보드에서 추적 보기 + +crew 또는 flow를 실행한 후 CrewAI AMP 대시보드에서 CrewAI 애플리케이션이 생성한 추적을 볼 수 있습니다. agent 상호 작용, 도구 사용 및 LLM 호출의 세부 단계를 볼 수 있습니다. +아래 링크를 클릭하여 추적을 보거나 대시보드의 추적 탭으로 이동하세요 [여기](https://app.crewai.com/crewai_plus/trace_batches) +![CrewAI Tracing Interface](/images/view-traces.png) + +### 대안: 환경 변수 구성 + +환경 변수를 설정하여 전역적으로 추적을 활성화할 수도 있습니다: + +```bash +export CREWAI_TRACING_ENABLED=true +``` + +또는 `.env` 파일에 추가하세요: + +```env +CREWAI_TRACING_ENABLED=true +``` + +이 환경 변수가 설정되면 `tracing=True`를 명시적으로 설정하지 않아도 모든 Crews와 Flows에 자동으로 추적이 활성화됩니다. + +## 추적 보기 + +### CrewAI AMP 대시보드 액세스 + +1. [app.crewai.com](https://app.crewai.com)을 방문하여 계정에 로그인하세요 +2. 프로젝트 대시보드로 이동하세요 +3. **Traces** 탭을 클릭하여 실행 세부 정보를 확인하세요 + +### 추적에서 볼 수 있는 내용 + +CrewAI 추적은 다음에 대한 포괄적인 가시성을 제공합니다: + +- **Agent 결정**: agent가 작업을 통해 어떻게 추론하고 결정을 내리는지 확인하세요 +- **작업 실행 타임라인**: 작업 시퀀스 및 종속성의 시각적 표현 +- **도구 사용**: 어떤 도구가 호출되고 그 결과를 모니터링하세요 +- **LLM 호출**: 프롬프트 및 응답을 포함한 모든 언어 모델 상호 작용을 추적하세요 +- **성능 메트릭**: 실행 시간, 토큰 사용량 및 비용 +- **오류 추적**: 세부 오류 정보 및 스택 추적 + +### 추적 기능 + +- **실행 타임라인**: 실행의 다양한 단계를 클릭하여 확인하세요 +- **세부 로그**: 디버깅을 위한 포괄적인 로그에 액세스하세요 +- **성능 분석**: 실행 패턴을 분석하고 성능을 최적화하세요 +- **내보내기 기능**: 추가 분석을 위해 추적을 다운로드하세요 + +### 인증 문제 + +인증 문제가 발생하는 경우: + +1. 로그인되어 있는지 확인하세요: `crewai login` +2. 인터넷 연결을 확인하세요 +3. [app.crewai.com](https://app.crewai.com)에서 계정을 확인하세요 + +### 추적이 나타나지 않음 + +대시보드에 추적이 표시되지 않는 경우: + +1. Crew/Flow에서 `tracing=True`가 설정되어 있는지 확인하세요 +2. 환경 변수를 사용하는 경우 `CREWAI_TRACING_ENABLED=true`인지 확인하세요 +3. `crewai login`으로 인증되었는지 확인하세요 +4. crew/flow가 실제로 실행되고 있는지 확인하세요 diff --git a/docs/v1.15.13/ko/observability/truefoundry.mdx b/docs/v1.15.13/ko/observability/truefoundry.mdx new file mode 100644 index 0000000000..5d89a337c6 --- /dev/null +++ b/docs/v1.15.13/ko/observability/truefoundry.mdx @@ -0,0 +1,147 @@ +--- +title: TrueFoundry Integration +icon: chart-line +mode: "wide" +--- + +TrueFoundry provides an enterprise-ready [AI Gateway](https://www.truefoundry.com/ai-gateway) which can integrate with agentic frameworks like CrewAI and provides governance and observability for your AI Applications. TrueFoundry AI Gateway serves as a unified interface for LLM access, providing: + +- **Unified API Access**: Connect to 250+ LLMs (OpenAI, Claude, Gemini, Groq, Mistral) through one API +- **Low Latency**: Sub-3ms internal latency with intelligent routing and load balancing +- **Enterprise Security**: SOC 2, HIPAA, GDPR compliance with RBAC and audit logging +- **Quota and cost management**: Token-based quotas, rate limiting, and comprehensive usage tracking +- **Observability**: Full request/response logging, metrics, and traces with customizable retention + +## How TrueFoundry Integrates with CrewAI + + +### Installation & Setup + + + +```bash +pip install crewai +``` + + + +1. Sign up for a [TrueFoundry account](https://www.truefoundry.com/register) +2. Follow the steps here in [Quick start](https://docs.truefoundry.com/gateway/quick-start) + + + +![TrueFoundry Code Configuration](/images/new-code-snippet.png) + +```python +from crewai import LLM + +# Create an LLM instance with TrueFoundry AI Gateway +truefoundry_llm = LLM( + model="openai-main/gpt-4o", # Similarly, you can call any model from any provider + base_url="your_truefoundry_gateway_base_url", + api_key="your_truefoundry_api_key" +) + +# Use in your CrewAI agents +from crewai import Agent + +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + llm=truefoundry_llm, + verbose=True + ) +``` + + + +### Complete CrewAI Example + +```python +from crewai import Agent, Task, Crew, LLM + +# Configure LLM with TrueFoundry +llm = LLM( + model="openai-main/gpt-4o", + base_url="your_truefoundry_gateway_base_url", + api_key="your_truefoundry_api_key" +) + +# Create agents +researcher = Agent( + role='Research Analyst', + goal='Conduct detailed market research', + backstory='Expert market analyst with attention to detail', + llm=llm, + verbose=True +) + +writer = Agent( + role='Content Writer', + goal='Create comprehensive reports', + backstory='Experienced technical writer', + llm=llm, + verbose=True +) + +# Create tasks +research_task = Task( + description='Research AI market trends for 2024', + agent=researcher, + expected_output='Comprehensive research summary' +) + +writing_task = Task( + description='Create a market research report', + agent=writer, + expected_output='Well-structured report with insights', + context=[research_task] +) + +# Create and execute crew +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True +) + +result = crew.kickoff() +``` + +### Observability and Governance + +Monitor your CrewAI agents through TrueFoundry's metrics tab: +![TrueFoundry metrics](/images/gateway-metrics.png) + +With Truefoundry's AI gateway, you can monitor and analyze: + +- **Performance Metrics**: Track key latency metrics like Request Latency, Time to First Token (TTFS), and Inter-Token Latency (ITL) with P99, P90, and P50 percentiles +- **Cost and Token Usage**: Gain visibility into your application's costs with detailed breakdowns of input/output tokens and the associated expenses for each model +- **Usage Patterns**: Understand how your application is being used with detailed analytics on user activity, model distribution, and team-based usage +- **Rate limit and Load balancing**: You can set up rate limiting, load balancing and fallback for your models + +## Tracing + +For a more detailed understanding on tracing, please see [getting-started-tracing](https://docs.truefoundry.com/docs/tracing/tracing-getting-started).For tracing, you can add the Traceloop SDK: +For tracing, you can add the Traceloop SDK: + +```bash +pip install traceloop-sdk +``` + +```python +from traceloop.sdk import Traceloop + +# Initialize enhanced tracing +Traceloop.init( + api_endpoint="https://your-truefoundry-endpoint/api/tracing", + headers={ + "Authorization": f"Bearer {your_truefoundry_pat_token}", + "TFY-Tracing-Project": "your_project_name", + }, +) +``` + +This provides additional trace correlation across your entire CrewAI workflow. +![TrueFoundry CrewAI Tracing](/images/tracing_crewai.png) diff --git a/docs/v1.15.13/ko/observability/weave.mdx b/docs/v1.15.13/ko/observability/weave.mdx new file mode 100644 index 0000000000..195fd403f3 --- /dev/null +++ b/docs/v1.15.13/ko/observability/weave.mdx @@ -0,0 +1,125 @@ +--- +title: Weave 통합 +description: Weights & Biases(W&B) Weave를 사용하여 CrewAI 애플리케이션을 추적, 실험, 평가 및 개선하는 방법을 알아보세요. +icon: radar +mode: "wide" +--- + +# Weave 개요 + +[Weights & Biases (W&B) Weave](https://weave-docs.wandb.ai/)는 LLM 기반 애플리케이션을 추적, 실험, 평가, 배포 및 개선하기 위한 프레임워크입니다. + +![W&B Weave CrewAI 트레이싱 사용 개요](/images/weave-tracing.gif) + +Weave는 CrewAI 애플리케이션 개발의 모든 단계에서 포괄적인 지원을 제공합니다: + +- **트레이싱 및 모니터링**: LLM 호출과 애플리케이션 로직을 자동으로 추적하여 프로덕션 시스템을 디버그하고 분석 +- **체계적인 반복**: prompt, 데이터셋, 모델을 개선하고 반복 +- **평가**: 맞춤형 또는 사전 구축된 스코어러를 사용하여 agent 성능을 체계적으로 평가하고 향상 +- **가드레일**: 콘텐츠 모더레이션과 prompt 안전성을 위한 사전 및 사후 보호조치로 agent를 보호 + +Weave는 CrewAI 애플리케이션의 트레이스를 자동으로 캡처하여 agent의 성능, 상호 작용 및 실행 흐름을 모니터링하고 분석할 수 있게 해줍니다. 이를 통해 더 나은 평가 데이터셋을 구축하고 agent 워크플로우를 최적화할 수 있습니다. + +## 설치 안내 + + + + ```shell + pip install crewai weave + ``` + + + [Weights & Biases 계정](https://wandb.ai)에 가입하세요. 아직 계정이 없다면 가입이 필요합니다. 트레이스와 메트릭을 확인하려면 계정이 필요합니다. + + + 다음 코드를 애플리케이션에 추가하세요: + + ```python + import weave + + # 프로젝트 이름으로 Weave를 초기화 + weave.init(project_name="crewai_demo") + ``` + + 초기화 후, Weave는 트레이스와 메트릭을 확인할 수 있는 URL을 제공합니다. + + + ```python + from crewai import Agent, Task, Crew, LLM, Process + + # 결정론적 출력을 위해 temperature를 0으로 설정하여 LLM 생성 + llm = LLM(model="gpt-4o", temperature=0) + + # 에이전트 생성 + researcher = Agent( + role='Research Analyst', + goal='Find and analyze the best investment opportunities', + backstory='Expert in financial analysis and market research', + llm=llm, + verbose=True, + allow_delegation=False, + ) + + writer = Agent( + role='Report Writer', + goal='Write clear and concise investment reports', + backstory='Experienced in creating detailed financial reports', + llm=llm, + verbose=True, + allow_delegation=False, + ) + + # 작업 생성 + research_task = Task( + description='Deep research on the {topic}', + expected_output='Comprehensive market data including key players, market size, and growth trends.', + agent=researcher + ) + + writing_task = Task( + description='Write a detailed report based on the research', + expected_output='The report should be easy to read and understand. Use bullet points where applicable.', + agent=writer + ) + + # 크루 생성 + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True, + process=Process.sequential, + ) + + # 크루 실행 + result = crew.kickoff(inputs={"topic": "AI in material science"}) + print(result) + ``` + + + CrewAI 애플리케이션 실행 후, 초기화 시 제공된 Weave URL에 방문하여 다음 항목을 확인할 수 있습니다: + - LLM 호출 및 그 메타데이터 + - 에이전트 상호작용 및 작업 실행 흐름 + - 대기 시간 및 토큰 사용량과 같은 성능 메트릭 + - 실행 중 발생한 오류 또는 이슈 + + + Weave tracing example with CrewAI + + + + +## 특징 + +- Weave는 모든 CrewAI 작업을 자동으로 캡처합니다: agent 상호작용 및 태스크 실행; 메타데이터와 토큰 사용량을 포함한 LLM 호출; 도구 사용 및 결과. +- 이 통합은 모든 CrewAI 실행 메서드를 지원합니다: `kickoff()`, `kickoff_for_each()`, `kickoff_async()`, 그리고 `kickoff_for_each_async()`. +- 모든 [crewAI-tools](https://github.com/crewAIInc/crewAI-tools) 작업의 자동 추적. +- 데코레이터 패칭(`@start`, `@listen`, `@router`, `@or_`, `@and_`)을 통한 flow 기능 지원. +- `@weave.op()`과 함께 CrewAI `Task`에 전달된 커스텀 guardrails 추적. + +지원되는 항목에 대한 자세한 정보는 [Weave CrewAI 문서](https://weave-docs.wandb.ai/guides/integrations/crewai/#getting-started-with-flow)를 참조하세요. + +## 자료 + +- [📘 Weave 문서](https://weave-docs.wandb.ai) +- [📊 예시 Weave x CrewAI 대시보드](https://wandb.ai/ayut/crewai_demo/weave/traces?cols=%7B%22wb_run_id%22%3Afalse%2C%22attributes.weave.client_version%22%3Afalse%2C%22attributes.weave.os_name%22%3Afalse%2C%22attributes.weave.os_release%22%3Afalse%2C%22attributes.weave.os_version%22%3Afalse%2C%22attributes.weave.source%22%3Afalse%2C%22attributes.weave.sys_version%22%3Afalse%7D&peekPath=%2Fayut%2Fcrewai_demo%2Fcalls%2F0195c838-38cb-71a2-8a15-651ecddf9d89) +- [🐦 X](https://x.com/weave_wb) \ No newline at end of file diff --git a/docs/v1.15.13/ko/quickstart.mdx b/docs/v1.15.13/ko/quickstart.mdx new file mode 100644 index 0000000000..f081ba299d --- /dev/null +++ b/docs/v1.15.13/ko/quickstart.mdx @@ -0,0 +1,257 @@ +--- +title: 퀵스타트 +description: 몇 분 안에 첫 CrewAI Flow를 만듭니다 — 오케스트레이션, 상태, 그리고 실제 보고서를 만드는 에이전트 crew까지. +icon: rocket +mode: "wide" +--- + +### 영상: 코딩 에이전트 스킬을 활용한 CrewAI Agents & Flows 구축 + +코딩 에이전트 스킬(Claude Code, Codex 등)을 설치하여 CrewAI로 코딩 에이전트를 빠르게 시작하세요. + +`npx skills add crewaiinc/skills` 명령어로 설치할 수 있습니다 + + + +이 가이드에서는 **Flow**를 만들어 연구 주제를 정하고, **에이전트 한 명으로 구성된 crew**(웹 검색을 쓰는 연구원)를 실행한 뒤, 디스크에 **Markdown 보고서**를 남깁니다. Flow는 프로덕션 앱을 구성하는 권장 방식으로, **상태**와 **실행 순서**를 담당하고 **에이전트**는 crew 단계 안에서 실제 작업을 수행합니다. + +CrewAI를 아직 설치하지 않았다면 먼저 [설치 가이드](/ko/installation)를 따르세요. + +## 사전 요건 + +- Python 환경과 CrewAI CLI([설치](/ko/installation) 참고) +- 올바른 API 키로 설정한 LLM — [LLM](/ko/concepts/llms#setting-up-your-llm) 참고 +- 이 튜토리얼의 웹 검색용 [Serper.dev](https://serper.dev/) API 키(`SERPER_API_KEY`) + +## 첫 번째 Flow 만들기 + + + + 터미널에서 Flow 프로젝트를 생성합니다(폴더 이름은 밑줄 형식입니다. 예: `latest_ai_flow`). + + + ```shell Terminal + crewai create flow latest-ai-flow + cd latest_ai_flow + ``` + + + 이렇게 하면 `src/latest_ai_flow/` 아래에 Flow 앱이 만들어지고, 다음 단계에서 **단일 에이전트** 연구 crew로 바꿀 시작용 crew가 `crews/content_crew/`에 포함됩니다. + + + + `src/latest_ai_flow/crews/content_crew/agents/researcher.jsonc`를 만듭니다(`agents/` 디렉터리가 없으면 생성). `{topic}` 같은 변수는 `crew.kickoff(inputs=...)`로 채워집니다. + + ```jsonc agents/researcher.jsonc + { + "role": "{topic} 시니어 데이터 리서처", + "goal": "{topic} 분야의 최신 동향을 파악한다", + "backstory": "당신은 가장 관련성 높은 정보를 찾아 명확하게 전달하는 연구원입니다.", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true + } + } + ``` + + + + + `src/latest_ai_flow/crews/content_crew/crew.jsonc`를 만듭니다: + + ```jsonc crew.jsonc + { + "name": "Research Crew", + "agents": ["researcher"], + "tasks": [ + { + "name": "research_task", + "description": "{topic}에 대해 철저히 조사하세요. 웹 검색으로 최신이고 신뢰할 수 있는 정보를 찾으세요.", + "expected_output": "마크다운 보고서로, 주요 트렌드·주목할 도구나 기업·시사점 등으로 섹션을 나누세요. 분량은 약 800~1200단어. 문서 전체를 코드 펜스로 감싸지 마세요.", + "agent": "researcher", + "output_file": "output/report.md", + "markdown": true + } + ], + "process": "sequential", + "verbose": true + } + ``` + + + + + 생성된 `content_crew.py`를 `crew.jsonc`를 `Crew`로 바꾸는 작은 loader로 교체합니다. + + ```python content_crew.py + # src/latest_ai_flow/crews/content_crew/content_crew.py + from pathlib import Path + + from crewai.project import load_crew + + + def kickoff_content_crew(inputs: dict): + crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc")) + return crew.kickoff(inputs={**default_inputs, **inputs}) + ``` + + + + + crew를 Flow에 연결합니다: `@start()` 단계에서 주제를 **상태**에 넣고, `@listen` 단계에서 crew를 실행합니다. 작업의 `output_file`은 그대로 `output/report.md`에 씁니다. + + ```python main.py + # src/latest_ai_flow/main.py + from pydantic import BaseModel + + from crewai.flow import Flow, listen, start + + from latest_ai_flow.crews.content_crew.content_crew import kickoff_content_crew + + + class ResearchFlowState(BaseModel): + topic: str = "" + report: str = "" + + + class LatestAiFlow(Flow[ResearchFlowState]): + @start() + def prepare_topic(self, crewai_trigger_payload: dict | None = None): + if crewai_trigger_payload: + self.state.topic = crewai_trigger_payload.get("topic", "AI Agents") + else: + self.state.topic = "AI Agents" + print(f"주제: {self.state.topic}") + + @listen(prepare_topic) + def run_research(self): + result = kickoff_content_crew(inputs={"topic": self.state.topic}) + self.state.report = result.raw + print("연구 crew 실행 완료.") + + @listen(run_research) + def summarize(self): + print("보고서 경로: output/report.md") + + + def kickoff(): + LatestAiFlow().kickoff() + + + def plot(): + LatestAiFlow().plot() + + + if __name__ == "__main__": + kickoff() + ``` + + + 패키지 이름이 `latest_ai_flow`가 아니면 `kickoff_content_crew` import 경로를 프로젝트 모듈 경로에 맞게 바꾸세요. + + + + + 프로젝트 루트의 `.env`에 다음을 설정합니다. + + - `SERPER_API_KEY` — [Serper.dev](https://serper.dev/)에서 발급 + - 모델 제공자 키 — [LLM 설정](/ko/concepts/llms#setting-up-your-llm) 참고 + + + + + ```shell Terminal + crewai install + crewai run + ``` + + + `crewai run`은 프로젝트에 정의된 Flow 진입점을 실행합니다(crew와 동일한 명령이며, `pyproject.toml`의 프로젝트 유형은 `"flow"`입니다). + + + + Flow와 crew 로그가 출력되어야 합니다. 생성된 보고서는 **`output/report.md`**에서 확인하세요(발췌): + + + ```markdown output/report.md + # AI 에이전트: 최신 동향과 전망 + + ## 요약 + … + + ## 주요 트렌드 + - **도구 사용과 오케스트레이션** — … + - **엔터프라이즈 도입** — … + + ## 시사점 + … + ``` + + + 실제 파일은 더 길고 실시간 검색 결과를 반영합니다. + + + +## 한 번에 이해하기 + +1. **Flow** — `LatestAiFlow`는 `prepare_topic` → `run_research` → `summarize` 순으로 실행됩니다. 상태(`topic`, `report`)는 Flow에 있습니다. +2. **Crew** — `kickoff_content_crew`가 `crew.jsonc`를 로드하고 에이전트 한 명·작업 하나로 실행합니다. 연구원이 **Serper**로 웹을 검색하고 구조화된 보고서를 씁니다. +3. **결과물** — 작업의 `output_file`이 `output/report.md`에 보고서를 씁니다. + +Flow 패턴(라우팅, 지속성, human-in-the-loop)을 더 보려면 [첫 Flow 만들기](/ko/guides/flows/first-flow)와 [Flows](/ko/concepts/flows)를 참고하세요. Flow 없이 crew만 쓰려면 [Crews](/ko/concepts/crews)를, 작업 없이 단일 `Agent`의 `kickoff()`만 쓰려면 [Agents](/ko/concepts/agents#direct-agent-interaction-with-kickoff)를 참고하세요. + + +에이전트 crew와 저장된 보고서까지 이어진 Flow를 완성했습니다. 이제 단계·crew·도구를 더해 확장할 수 있습니다. + + +### 이름 일치 + +`crew.jsonc`의 이름은 파일과 참조에 맞아야 합니다: + +- `agents: ["researcher"]`는 `agents/researcher.jsonc`를 로드합니다. +- `tasks[].agent: "researcher"`는 해당 태스크를 그 에이전트에 배정합니다. + +## 배포 + +로컬에서 정상 실행되고 프로젝트가 **GitHub** 저장소에 있으면 Flow를 **[CrewAI AMP](https://app.crewai.com)**에 올릴 수 있습니다. 프로젝트 루트에서: + + +```bash 인증 +crewai login +``` + +```bash 배포 생성 +crewai deploy create +``` + +```bash 상태 및 로그 +crewai deploy status +crewai deploy logs +``` + +```bash 코드 변경 후 반영 +crewai deploy push +``` + +```bash 배포 목록 또는 삭제 +crewai deploy list +crewai deploy remove +``` + + + + 첫 배포는 보통 **약 1분** 정도 걸립니다. 전체 사전 요건과 웹 UI 절차는 [AMP에 배포](https://docs-platform.crewai.com/platform/ko/guides/deploy-to-amp)를 참고하세요. + + + + + AMP 배포 단계별 안내(CLI 및 대시보드). + + + 아이디어를 나누고 프로젝트를 공유하며 다른 CrewAI 개발자와 소통하세요. + + diff --git a/docs/v1.15.13/ko/skills.mdx b/docs/v1.15.13/ko/skills.mdx new file mode 100644 index 0000000000..f39e7f592b --- /dev/null +++ b/docs/v1.15.13/ko/skills.mdx @@ -0,0 +1,50 @@ +--- +title: Skills +description: skills.sh의 공식 레지스트리에서 crewaiinc/skills를 설치하세요. Claude Code, Cursor, Codex 등을 위한 Flow, Crew, 문서 연동 스킬. +icon: wand-magic-sparkles +mode: "wide" +--- + +# Skills + +**한 번의 명령으로 코딩 에이전트에 CrewAI 컨텍스트를 제공하세요.** + +CrewAI **Skills**는 **[skills.sh/crewaiinc/skills](https://skills.sh/crewaiinc/skills)**에 게시됩니다. `crewaiinc/skills`의 공식 레지스트리로, 개별 스킬(예: **design-agent**, **getting-started**, **design-task**, **ask-docs**), 설치 수, 감사 정보를 확인할 수 있습니다. Claude Code, Cursor, Codex 같은 코딩 에이전트에게 Flow 구성, Crew 설정, 도구 사용, CrewAI 패턴을 가르칩니다. 아래를 실행하거나 에이전트에 붙여 넣으세요. + +```shell Terminal +npx skills add crewaiinc/skills +``` + +에이전트 워크플로에 스킬 팩이 추가되어 세션마다 프레임워크를 다시 설명하지 않아도 CrewAI 관례를 적용할 수 있습니다. 소스와 이슈는 [GitHub](https://github.com/crewAIInc/skills)에서 관리합니다. + +## 에이전트가 얻는 것 + +- **Flows** — CrewAI 방식의 상태ful 앱, 단계, crew kickoff +- **Crew & 에이전트** — JSON-first 패턴(`crew.jsonc`, `agents/*.jsonc`), 역할, 작업, 위임 +- **도구 & 통합** — 검색, API, 일반적인 CrewAI 도구 연결 +- **프로젝트 구조** — CLI 스캐폴드 및 저장소 관례와 정렬 +- **최신 패턴** — 스킬이 현재 CrewAI 문서 및 권장 사항을 반영 + +## 이 사이트에서 더 알아보기 + + + + CrewAI와 `AGENTS.md`, 코딩 에이전트 워크플로 사용법. + + + 첫 Flow와 crew를 처음부터 끝까지 구축합니다. + + + CrewAI CLI와 Python 패키지를 설치합니다. + + + `crewaiinc/skills` 공식 목록—스킬, 설치 수, 감사. + + + 스킬 팩 소스, 업데이트, 이슈. + + + +### 영상: 코딩 에이전트 스킬과 CrewAI + + + +### 11. Chaves de API + +Ao executar o comando `crewai create crew`, o CLI mostrará provedores de LLM disponíveis e depois a seleção de modelo para o provedor escolhido. O modelo selecionado é salvo no `.env` gerado, e cada agente JSONC pode definir seu próprio `llm`. + +Após selecionar um provedor de LLM, será solicitado que você informe as chaves de API. + +#### Provedores iniciais de chave de API + +Inicialmente, o CLI solicitará as chaves de API para os seguintes serviços: + +- OpenAI +- Groq +- Anthropic +- Google Gemini +- SambaNova + +Ao selecionar um provedor, o CLI solicitará que você insira sua chave de API. + +#### Outras opções + +Se você selecionar a opção 6, será possível escolher de uma lista de provedores suportados pelo LiteLLM. + +Ao escolher um provedor, o CLI solicitará que você informe o nome da chave e a chave de API. + +Veja o seguinte link para o nome de chave de cada provedor: + +- [LiteLLM Providers](https://docs.litellm.ai/docs/providers) + +### 12. Gerenciamento de Configuração + +Gerencie as configurações do CLI para CrewAI. + +```shell Terminal +crewai config [COMANDO] [OPÇÕES] +``` + +#### Comandos: + +- `list`: Exibir todos os parâmetros de configuração do CLI + +```shell Terminal +crewai config list +``` + +- `set`: Definir um parâmetro de configuração do CLI + +```shell Terminal +crewai config set +``` + +- `reset`: Redefinir todos os parâmetros de configuração do CLI para valores padrão + +```shell Terminal +crewai config reset +``` + +#### Parâmetros de Configuração Disponíveis + +- `enterprise_base_url`: URL base da instância CrewAI AMP +- `oauth2_provider`: Provedor OAuth2 usado para autenticação (ex: workos, okta, auth0) +- `oauth2_audience`: Valor de audiência OAuth2, tipicamente usado para identificar a API ou recurso de destino +- `oauth2_client_id`: ID do cliente OAuth2 emitido pelo provedor, usado durante solicitações de autenticação +- `oauth2_domain`: Domínio do provedor OAuth2 (ex: sua-org.auth0.com) usado para emissão de tokens + +#### Exemplos + +Exibir configuração atual: + +```shell Terminal +crewai config list +``` + +Exemplo de saída: + +| Parâmetro | Valor | Descrição | +| :------------------ | :--------------------- | :------------------------------------------------------------- | +| enterprise_base_url | https://app.crewai.com | URL base da instância CrewAI AMP | +| org_name | Not set | Nome da organização atualmente ativa | +| org_uuid | Not set | UUID da organização atualmente ativa | +| oauth2_provider | workos | Provedor OAuth2 (ex.: workos, okta, auth0) | +| oauth2_audience | client_01YYY | Audience usada para identificar a API/recurso de destino | +| oauth2_client_id | client_01XXX | Client ID OAuth2 emitido pelo provedor (usado na autenticação) | +| oauth2_domain | login.crewai.com | Domínio do provedor OAuth2 (ex.: your-org.auth0.com) | + +Definir a URL base do enterprise: + +```shell Terminal +crewai config set enterprise_base_url https://minha-empresa.crewai.com +``` + +Definir provedor OAuth2: + +```shell Terminal +crewai config set oauth2_provider auth0 +``` + +Definir domínio OAuth2: + +```shell Terminal +crewai config set oauth2_domain minha-empresa.auth0.com +``` + +Redefinir todas as configurações para padrões: + +```shell Terminal +crewai config reset +``` + + + As configurações são armazenadas em `~/.config/crewai/settings.json`. Algumas + configurações como nome da organização e UUID são somente leitura e + gerenciadas através de comandos de autenticação e organização. Configurações + relacionadas ao repositório de ferramentas são ocultas e não podem ser + definidas diretamente pelo usuário. + diff --git a/docs/v1.15.13/pt-BR/concepts/collaboration.mdx b/docs/v1.15.13/pt-BR/concepts/collaboration.mdx new file mode 100644 index 0000000000..6dbf6d3ac9 --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/collaboration.mdx @@ -0,0 +1,361 @@ +--- +title: Colaboração +description: Como permitir que agentes trabalhem juntos, deleguem tarefas e se comuniquem de forma eficaz em equipes CrewAI. +icon: screen-users +mode: "wide" +--- + +## Visão Geral + +A colaboração no CrewAI permite que agentes trabalhem juntos como uma equipe, delegando tarefas e fazendo perguntas para aproveitar a expertise uns dos outros. Quando `allow_delegation=True`, os agentes automaticamente têm acesso a poderosas ferramentas de colaboração. + +## Guia Rápido: Habilite a Colaboração + +```python +from crewai import Agent, Crew, Task + +# Enable collaboration for agents +researcher = Agent( + role="Especialista em Pesquisa", + goal="Realizar pesquisas aprofundadas sobre qualquer tema", + backstory="Pesquisador especialista com acesso a diversas fontes", + allow_delegation=True, # 🔑 Configuração chave para colaboração + verbose=True +) + +writer = Agent( + role="Redator de Conteúdo", + goal="Criar conteúdo envolvente com base em pesquisas", + backstory="Redator habilidoso que transforma pesquisas em conteúdo atraente", + allow_delegation=True, # 🔑 Permite fazer perguntas a outros agentes + verbose=True +) + +# Agents can now collaborate automatically +crew = Crew( + agents=[researcher, writer], + tasks=[...], + verbose=True +) +``` + +## Como Funciona a Colaboração entre Agentes + +Quando `allow_delegation=True`, o CrewAI automaticamente fornece aos agentes duas ferramentas poderosas: + +### 1. **Ferramenta de Delegação de Trabalho** +Permite que agentes designem tarefas para colegas com expertise específica. + +```python +# Agent automatically gets this tool: +# Delegate work to coworker(task: str, context: str, coworker: str) +``` + +### 2. **Ferramenta de Fazer Pergunta** +Permite que agentes façam perguntas específicas para obter informações de colegas. + +```python +# Agent automatically gets this tool: +# Ask question to coworker(question: str, context: str, coworker: str) +``` + +## Colaboração em Ação + +Veja um exemplo completo onde agentes colaboram em uma tarefa de criação de conteúdo: + +```python +from crewai import Agent, Crew, Task, Process + +# Create collaborative agents +researcher = Agent( + role="Especialista em Pesquisa", + goal="Realizar pesquisas aprofundadas sobre qualquer tema", + backstory="Pesquisador especialista com acesso a diversas fontes", + allow_delegation=True, + verbose=True +) + +writer = Agent( + role="Redator de Conteúdo", + goal="Criar conteúdo envolvente com base em pesquisas", + backstory="Redator habilidoso que transforma pesquisas em conteúdo atraente", + allow_delegation=True, + verbose=True +) + +editor = Agent( + role="Content Editor", + goal="Ensure content quality and consistency", + backstory="""You're an experienced editor with an eye for detail, + ensuring content meets high standards for clarity and accuracy.""", + allow_delegation=True, + verbose=True +) + +# Create a task that encourages collaboration +article_task = Task( + description="""Escreva um artigo abrangente de 1000 palavras sobre 'O Futuro da IA na Saúde'. + +O artigo deve incluir: +- Aplicações atuais de IA na saúde +- Tendências e tecnologias emergentes +- Desafios potenciais e considerações éticas +- Previsões de especialistas para os próximos 5 anos + +Colabore com seus colegas para garantir precisão e qualidade.""", + expected_output="Um artigo bem pesquisado, envolvente, com 1000 palavras, estrutura adequada e citações", + agent=writer # O redator lidera, mas pode delegar pesquisa ao pesquisador +) + +# Create collaborative crew +crew = Crew( + agents=[researcher, writer, editor], + tasks=[article_task], + process=Process.sequential, + verbose=True +) + +result = crew.kickoff() +``` + +## Padrões de Colaboração + +### Padrão 1: Pesquisa → Redação → Edição +```python +research_task = Task( + description="Pesquise os últimos avanços em computação quântica", + expected_output="Resumo abrangente da pesquisa com principais descobertas e fontes", + agent=researcher +) + +writing_task = Task( + description="Escreva um artigo com base nos achados da pesquisa", + expected_output="Artigo envolvente de 800 palavras sobre computação quântica", + agent=writer, + context=[research_task] # Recebe a saída da pesquisa como contexto +) + +editing_task = Task( + description="Edite e revise o artigo para publicação", + expected_output="Artigo pronto para publicação, com clareza e fluidez aprimoradas", + agent=editor, + context=[writing_task] # Recebe o rascunho do artigo como contexto +) +``` + +### Padrão 2: Tarefa Única Colaborativa +```python +collaborative_task = Task( + description="""Crie uma estratégia de marketing para um novo produto de IA. + +Redator: Foque em mensagens e estratégia de conteúdo +Pesquisador: Forneça análise de mercado e insights de concorrentes + +Trabalhem juntos para criar uma estratégia abrangente.""", + expected_output="Estratégia de marketing completa com embasamento em pesquisa", + agent=writer # Agente líder, mas pode delegar ao pesquisador +) +``` + +## Colaboração Hierárquica + +Para projetos complexos, utilize um processo hierárquico com um agente gerente: + +```python +from crewai import Agent, Crew, Task, Process + +# Manager agent coordinates the team +manager = Agent( + role="Gerente de Projetos", + goal="Coordenar esforços da equipe e garantir o sucesso do projeto", + backstory="Gerente de projetos experiente, habilidoso em delegação e controle de qualidade", + allow_delegation=True, + verbose=True +) + +# Specialist agents +researcher = Agent( + role="Pesquisador", + goal="Fornecer pesquisa e análise precisas", + backstory="Pesquisador especialista com habilidades analíticas profundas", + allow_delegation=False, # Especialistas focam em sua expertise + verbose=True +) + +writer = Agent( + role="Redator", + goal="Criar conteúdo envolvente", + backstory="Redator habilidoso que cria conteúdo atraente", + allow_delegation=False, + verbose=True +) + +# Manager-led task +project_task = Task( + description="Crie um relatório de análise de mercado completo com recomendações", + expected_output="Resumo executivo, análise detalhada e recomendações estratégicas", + agent=manager # O gerente delega para especialistas +) + +# Hierarchical crew +crew = Crew( + agents=[manager, researcher, writer], + tasks=[project_task], + process=Process.hierarchical, # Manager coordinates everything + manager_llm="gpt-4o", # Specify LLM for manager + verbose=True +) +``` + +## Melhores Práticas para Colaboração + +### 1. **Definição Clara de Papéis** +```python +# ✅ Bom: papéis específicos e complementares +researcher = Agent(role="Market Research Analyst", ...) +writer = Agent(role="Technical Content Writer", ...) + +# ❌ Evite: Papéis sobrepostos ou vagos +agent1 = Agent(role="General Assistant", ...) +agent2 = Agent(role="Helper", ...) +``` + +### 2. **Delegação Estratégica Habilitada** +```python +# ✅ Habilite delegação para coordenadores e generalistas +lead_agent = Agent( + role="Content Lead", + allow_delegation=True, # Can delegate to specialists + ... +) + +# ✅ Desative para especialistas focados (opcional) +specialist_agent = Agent( + role="Data Analyst", + allow_delegation=False, # Focuses on core expertise + ... +) +``` + +### 3. **Compartilhamento de Contexto** +```python +# ✅ Use o parâmetro context para dependências entre tarefas +writing_task = Task( + description="Write article based on research", + agent=writer, + context=[research_task], # Shares research results + ... +) +``` + +### 4. **Descrições Claras de Tarefas** +```python +# ✅ Descrições específicas e acionáveis +Task( + description="""Research competitors in the AI chatbot space. + Focus on: pricing models, key features, target markets. + Provide data in a structured format.""", + ... +) + +# ❌ Descrições vagas que não orientam a colaboração +Task(description="Do some research about chatbots", ...) +``` + +## Solução de Problemas em Colaboração + +### Problema: Agentes Não Colaboram +**Sintomas:** Agentes trabalham isoladamente, sem ocorrer delegação +```python +# ✅ Solução: Certifique-se que a delegação está habilitada +agent = Agent( + role="...", + allow_delegation=True, # This is required! + ... +) +``` + +### Problema: Troca Excessiva de Perguntas +**Sintomas:** Agentes fazem perguntas em excesso, progresso lento +```python +# ✅ Solução: Forneça melhor contexto e papéis específicos +Task( + description="""Write a technical blog post about machine learning. + + Context: Target audience is software developers with basic ML knowledge. + Length: 1200 words + Include: code examples, practical applications, best practices + + If you need specific technical details, delegate research to the researcher.""", + ... +) +``` + +### Problema: Loops de Delegação +**Sintomas:** Agentes delegam tarefas repetidamente uns para os outros indefinidamente +```python +# ✅ Solução: Hierarquia e responsabilidades bem definidas +manager = Agent(role="Manager", allow_delegation=True) +specialist1 = Agent(role="Specialist A", allow_delegation=False) # No re-delegation +specialist2 = Agent(role="Specialist B", allow_delegation=False) +``` + +## Recursos Avançados de Colaboração + +### Regras Personalizadas de Colaboração +```python +# Set specific collaboration guidelines in agent backstory +agent = Agent( + role="Senior Developer", + backstory="""You lead development projects and coordinate with team members. + + Collaboration guidelines: + - Delegate research tasks to the Research Analyst + - Ask the Designer for UI/UX guidance + - Consult the QA Engineer for testing strategies + - Only escalate blocking issues to the Project Manager""", + allow_delegation=True +) +``` + +### Monitoramento da Colaboração +```python +def track_collaboration(output): + """Track collaboration patterns""" + if "Delegate work to coworker" in output.raw: + print("🤝 Delegation occurred") + if "Ask question to coworker" in output.raw: + print("❓ Question asked") + +crew = Crew( + agents=[...], + tasks=[...], + step_callback=track_collaboration, # Monitor collaboration + verbose=True +) +``` + +## Memória e Aprendizado + +Permita que agentes se lembrem de colaborações passadas: + +```python +agent = Agent( + role="Content Lead", + memory=True, # Remembers past interactions + allow_delegation=True, + verbose=True +) +``` + +Com a memória ativada, os agentes aprendem com colaborações anteriores e aprimoram suas decisões de delegação ao longo do tempo. + +## Próximos Passos + +- **Teste os exemplos**: Comece pelo exemplo básico de colaboração +- **Experimente diferentes papéis**: Teste combinações variadas de papéis de agentes +- **Monitore as interações**: Use `verbose=True` para ver a colaboração em ação +- **Otimize descrições de tarefas**: Tarefas claras geram melhor colaboração +- **Escale**: Experimente processos hierárquicos para projetos complexos + +A colaboração transforma agentes de IA individuais em equipes poderosas capazes de enfrentar desafios complexos e multifacetados juntos. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/concepts/crews.mdx b/docs/v1.15.13/pt-BR/concepts/crews.mdx new file mode 100644 index 0000000000..a8317e5251 --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/crews.mdx @@ -0,0 +1,460 @@ +--- +title: Crews +description: Compreendendo e utilizando crews no framework crewAI com atributos e funcionalidades abrangentes. +icon: people-group +mode: "wide" +--- + +## Visão Geral + +Uma crew no crewAI representa um grupo colaborativo de agentes trabalhando em conjunto para alcançar um conjunto de tarefas. Cada crew define a estratégia de execução de tarefas, colaboração entre agentes e o fluxo de trabalho geral. + +## Atributos de Crew + +| Atributo | Parâmetros | Descrição | +| :------------------------------------ | :---------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Tasks** | `tasks` | Uma lista de tasks atribuídas à crew. | +| **Agents** | `agents` | Uma lista de agentes que fazem parte da crew. | +| **Process** _(opcional)_ | `process` | O fluxo de processo (por exemplo, sequencial, hierárquico) seguido pela crew. O padrão é `sequential`. | +| **Verbose** _(opcional)_ | `verbose` | O nível de verbosidade para logging durante a execução. O padrão é `False`. | +| **Manager LLM** _(opcional)_ | `manager_llm` | O modelo de linguagem utilizado pelo agente gerenciador em um processo hierárquico. **Obrigatório ao usar um processo hierárquico.** | +| **Function Calling LLM** _(opcional)_ | `function_calling_llm` | Se definido, a crew utilizará este LLM para invocar funções das ferramentas para todos os agentes da crew. Cada agente pode ter seu próprio LLM, que substitui o LLM da crew para chamadas de função. | +| **Config** _(opcional)_ | `config` | Configurações opcionais para a crew, no formato `Json` ou `Dict[str, Any]`. | +| **Max RPM** _(opcional)_ | `max_rpm` | Número máximo de requisições por minuto que a crew respeita durante a execução. O padrão é `None`. | +| **Memory** _(opcional)_ | `memory` | Utilizada para armazenar memórias de execução (curto prazo, longo prazo, memória de entidade). | | +| **Cache** _(opcional)_ | `cache` | Especifica se deve usar cache para armazenar os resultados da execução de ferramentas. O padrão é `True`. | +| **Embedder** _(opcional)_ | `embedder` | Configuração do embedder a ser utilizado pela crew. Atualmente mais usado por memory. O padrão é `{"provider": "openai"}`. | +| **Step Callback** _(opcional)_ | `step_callback` | Uma função chamada após cada etapa de cada agente. Pode ser usada para registrar as ações do agente ou executar outras operações; não sobrescreve o `step_callback` específico do agente. | +| **Task Callback** _(opcional)_ | `task_callback` | Uma função chamada após a conclusão de cada tarefa. Útil para monitoramento ou para operações adicionais pós-execução da task. | +| **Share Crew** _(opcional)_ | `share_crew` | Se deseja compartilhar as informações completas da crew e execução com a equipe do crewAI para melhorar a biblioteca e nos permitir treinar modelos. | +| **Output Log File** _(opcional)_ | `output_log_file` | Defina como True para salvar logs como logs.txt no diretório atual ou forneça um caminho de arquivo. Os logs estarão em formato JSON se o nome terminar com .json, caso contrário .txt. O padrão é `None`. | +| **Manager Agent** _(opcional)_ | `manager_agent` | `manager` define um agente customizado que será utilizado como gerente. | +| **Prompt File** _(opcional)_ | `prompt_file` | Caminho para o arquivo JSON de prompt a ser utilizado pela crew. | +| **Planning** *(opcional)* | `planning` | Adiciona habilidade de planejamento à Crew. Quando ativado, antes de cada iteração, todos os dados da Crew são enviados a um AgentPlanner que planejará as tasks e este plano será adicionado à descrição de cada task. | +| **Planning LLM** *(opcional)* | `planning_llm` | O modelo de linguagem usado pelo AgentPlanner em um processo de planejamento. | +| **Knowledge Sources** _(opcional)_ | `knowledge_sources` | Fontes de conhecimento disponíveis no nível da crew, acessíveis a todos os agentes. | +| **Stream** _(opcional)_ | `stream` | Habilita saída em streaming para receber atualizações em tempo real durante a execução da crew. Retorna um objeto `CrewStreamingOutput` que pode ser iterado para chunks. O padrão é `False`. | + + +**Crew Max RPM**: O atributo `max_rpm` define o número máximo de requisições por minuto que a crew pode executar para evitar limites de taxa e irá sobrescrever as configurações de `max_rpm` dos agentes individuais se você o definir. + + +## Criando Crews + +Existem duas maneiras principais de criar crews no CrewAI: utilizando **configuração JSONC (recomendada para novas crews)** ou definindo a crew **em código** para projetos clássicos e casos avançados. + +### Configuração JSONC (Recomendado) + +Novos projetos criados com `crewai create crew ` usam `crew.jsonc` para configurações da crew e tarefas, além de um arquivo por agente em `agents/`. `crewai run` detecta `crew.jsonc` ou `crew.json`, carrega os agentes referenciados, pergunta por placeholders ausentes e inicia a crew. + +```jsonc crew.jsonc +{ + "name": "Market Research Crew", + "agents": ["researcher", "analyst"], + "tasks": [ + { + "name": "research", + "description": "Research {topic} and collect the most relevant facts.", + "expected_output": "Structured research notes about {topic}.", + "agent": "researcher" + }, + { + "name": "analysis", + "description": "Analyze the research and write a concise report.", + "expected_output": "A markdown report with findings and recommendations.", + "agent": "analyst", + "context": ["research"], + "output_file": "output/report.md" + } + ], + "process": "sequential", + "verbose": true, + "memory": true, + "inputs": { + "topic": "AI Agents" + } +} +``` + +Cada string em `agents` resolve primeiro para `agents/.jsonc` e depois para `agents/.json`. Para crews hierárquicas, use `"process": "hierarchical"` com `manager_llm` ou `manager_agent`. + + +Execute projetos JSON apenas de fontes confiáveis. Ferramentas `custom:` e referências `{"python": "module.attribute"}` executam código Python local quando a crew é carregada. + + +### Configuração YAML Clássica + +Projetos clássicos criados com `crewai create crew --classic` usam `crew.py`, `config/agents.yaml`, `config/tasks.yaml` e os decorators `@CrewBase`, `@agent`, `@task` e `@crew`. + +Essa abordagem continua suportada para projetos existentes em Python/YAML e para equipes que precisam de controle explícito via decorators. + +Após criar um projeto clássico, você pode definir sua crew em uma classe que herda de `CrewBase` e utiliza decorators para definir agentes, tarefas e a própria crew. + +#### Exemplo de Classe Crew com Decorators + +```python code +from crewai import Agent, Crew, Task, Process +from crewai.project import CrewBase, agent, task, crew, before_kickoff, after_kickoff +from crewai.agents.agent_builder.base_agent import BaseAgent +from typing import List + +@CrewBase +class YourCrewName: + """Descrição da sua crew""" + + agents: List[BaseAgent] + tasks: List[Task] + + # Caminhos para seus arquivos de configuração YAML + # Para um exemplo de agente e tarefa definidos em YAML, confira: + # - Task: https://docs.crewai.com/concepts/tasks#yaml-configuration-recommended + # - Agents: https://docs.crewai.com/concepts/agents#yaml-configuration-recommended + agents_config = 'config/agents.yaml' + tasks_config = 'config/tasks.yaml' + + @before_kickoff + def prepare_inputs(self, inputs): + # Modifique inputs antes da crew iniciar + inputs['additional_data'] = "Alguma informação extra" + return inputs + + @after_kickoff + def process_output(self, output): + # Modifique a saída após a crew finalizar + output.raw += "\nProcessado após kickoff." + return output + + @agent + def agent_one(self) -> Agent: + return Agent( + config=self.agents_config['agent_one'], # type: ignore[index] + verbose=True + ) + + @agent + def agent_two(self) -> Agent: + return Agent( + config=self.agents_config['agent_two'], # type: ignore[index] + verbose=True + ) + + @task + def task_one(self) -> Task: + return Task( + config=self.tasks_config['task_one'] # type: ignore[index] + ) + + @task + def task_two(self) -> Task: + return Task( + config=self.tasks_config['task_two'] # type: ignore[index] + ) + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, # Coletado automaticamente pelo decorator @agent + tasks=self.tasks, # Coletado automaticamente pelo decorator @task + process=Process.sequential, + verbose=True, + ) +``` + +Como executar o código acima: + +```python code +YourCrewName().crew().kickoff(inputs={"any": "input here"}) +``` + + +As tarefas serão executadas na ordem em que forem definidas. + + +A classe `CrewBase`, junto com esses decorators, automatiza a coleta de agentes e tarefas, reduzindo a necessidade de gerenciamento manual. + +#### Visão geral dos Decorators de `annotations.py` + +O CrewAI fornece vários decorators no arquivo `annotations.py` que são usados para marcar métodos dentro de sua classe crew para tratamento especial: + +- `@CrewBase`: Marca a classe como classe base de crew. +- `@agent`: Denota um método que retorna um objeto `Agent`. +- `@task`: Denota um método que retorna um objeto `Task`. +- `@crew`: Denota o método que retorna o objeto `Crew`. +- `@before_kickoff`: (Opcional) Marca um método a ser executado antes da crew iniciar. +- `@after_kickoff`: (Opcional) Marca um método a ser executado após a crew finalizar. + +Esses decorators ajudam na organização da estrutura da sua crew e coletam automaticamente agentes e tasks sem precisar listá-los manualmente. + +### Definição Direta em Código (Alternativa) + +Como alternativa, você pode definir a crew diretamente em código sem utilizar arquivos de configuração YAML. + +```python code +from crewai import Agent, Crew, Task, Process +from crewai_tools import YourCustomTool + +class YourCrewName: + def agent_one(self) -> Agent: + return Agent( + role="Analista de Dados", + goal="Analisar tendências de dados no mercado brasileiro", + backstory="Analista experiente com formação em economia", + verbose=True, + tools=[YourCustomTool()] + ) + + def agent_two(self) -> Agent: + return Agent( + role="Pesquisador de Mercado", + goal="Coletar informações sobre a dinâmica do mercado nacional", + backstory="Pesquisador dedicado com olhar atento aos detalhes", + verbose=True + ) + + def task_one(self) -> Task: + return Task( + description="Coletar dados recentes do mercado brasileiro e identificar tendências.", + expected_output="Um relatório resumido com as principais tendências do mercado.", + agent=self.agent_one() + ) + + def task_two(self) -> Task: + return Task( + description="Pesquisar fatores que afetam a dinâmica do mercado nacional.", + expected_output="Uma análise dos fatores que influenciam o mercado.", + agent=self.agent_two() + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.agent_one(), self.agent_two()], + tasks=[self.task_one(), self.task_two()], + process=Process.sequential, + verbose=True + ) +``` +Como executar o código acima: + +```python code +YourCrewName().crew().kickoff(inputs={}) +``` + +Neste exemplo: + +- Agentes e tarefas são definidos diretamente dentro da classe, sem decorators. +- Criamos e gerenciamos manualmente a lista de agentes e tasks. +- Essa abordagem fornece mais controle, mas pode ser menos sustentável para projetos maiores. + +## Saída da Crew + +A saída de uma crew no framework CrewAI é encapsulada na classe `CrewOutput`. +Essa classe fornece uma forma estruturada de acessar os resultados da execução da crew, incluindo vários formatos como string bruta, JSON e modelos Pydantic. +O `CrewOutput` inclui os resultados da tarefa final, uso de tokens e as saídas das tasks individuais. + +### Atributos do Crew Output + +| Atributo | Parâmetros | Tipo | Descrição | +| :--------------- | :------------- | :------------------------ | :------------------------------------------------------------------------------------------------ | +| **Raw** | `raw` | `str` | A saída bruta da crew. Este é o formato padrão da saída. | +| **Pydantic** | `pydantic` | `Optional[BaseModel]` | Um objeto modelo Pydantic representando a saída estruturada da crew. | +| **JSON Dict** | `json_dict` | `Optional[Dict[str, Any]]`| Um dicionário representando a saída da crew em formato JSON. | +| **Tasks Output** | `tasks_output` | `List[TaskOutput]` | Uma lista de objetos `TaskOutput`, cada um representando a saída de uma task na crew. | +| **Token Usage** | `token_usage` | `Dict[str, Any]` | Um resumo do uso de tokens, oferecendo informações sobre a performance do modelo de linguagem. | + +### Métodos e Propriedades do Crew Output + +| Método/Propriedade | Descrição | +| :----------------- | :------------------------------------------------------------------------------------------------- | +| **json** | Retorna a representação em string JSON da saída da crew caso o formato seja JSON. | +| **to_dict** | Converte as saídas JSON e Pydantic em um dicionário. | +| **__str__** | Retorna a representação em string do resultado da crew, priorizando Pydantic, depois JSON, depois raw.| + +### Acessando a Saída da Crew + +Após executar uma crew, sua saída pode ser acessada pelo atributo `output` do objeto `Crew`. A classe `CrewOutput` oferece várias formas de interagir com esta saída. + +#### Exemplo + +```python Code +# Execução de exemplo da crew +crew = Crew( + agents=[research_agent, writer_agent], + tasks=[research_task, write_article_task], + verbose=True +) + +crew_output = crew.kickoff() + +# Acessando a saída da crew +print(f"Raw Output: {crew_output.raw}") +if crew_output.json_dict: + print(f"JSON Output: {json.dumps(crew_output.json_dict, indent=2)}") +if crew_output.pydantic: + print(f"Pydantic Output: {crew_output.pydantic}") +print(f"Tasks Output: {crew_output.tasks_output}") +print(f"Token Usage: {crew_output.token_usage}") +``` + +## Acessando Logs da Crew + +Você pode visualizar o log em tempo real da execução da crew, definindo `output_log_file` como `True(Boolean)` ou um `file_name(str)`. Suporta logging de eventos como tanto `file_name.txt` quanto `file_name.json`. +Se for `True(Boolean)`, salvará como `logs.txt`. + +Caso `output_log_file` seja `False(Boolean)` ou `None`, os logs não serão gerados. + +```python Code +# Salvar logs da crew +crew = Crew(output_log_file = True) # Logs serão salvos como logs.txt +crew = Crew(output_log_file = file_name) # Logs serão salvos como file_name.txt +crew = Crew(output_log_file = file_name.txt) # Logs serão salvos como file_name.txt +crew = Crew(output_log_file = file_name.json) # Logs serão salvos como file_name.json +``` + +## Utilização de Memória + +As crews podem utilizar memória (curto prazo, longo prazo e memória de entidade) para potencializar sua execução e aprendizado ao longo do tempo. Este recurso permite que as crews armazenem e recuperem memórias de execução, auxiliando na tomada de decisão e nas estratégias de execução de tasks. + +## Utilização de Cache + +Caches podem ser utilizados para armazenar resultados de execuções de ferramentas, tornando o processo mais eficiente ao evitar a reexecução de tasks idênticas. + +## Métricas de Uso da Crew + +Após a execução da crew, você pode acessar o atributo `usage_metrics` para visualizar as métricas de uso do modelo de linguagem (LLM) para todas as tasks executadas pela crew. Isso fornece insights sobre eficiência operacional e oportunidades de melhoria. + +`total_tokens` é o total faturado (`prompt_tokens + completion_tokens`). Campos de breakdown como `cached_prompt_tokens` e `cache_creation_tokens` descrevem subconjuntos já incluídos nesses totais e não são somados novamente a `total_tokens`. Consulte a seção **UsageMetrics field semantics** na documentação do conceito Flows para o contrato completo. + +```python Code +# Acessar as métricas de uso da crew +crew = Crew(agents=[agent1, agent2], tasks=[task1, task2]) +crew.kickoff() +print(crew.usage_metrics) +``` + +## Processo de Execução da Crew + +- **Sequential Process**: As tasks são executadas uma após a outra, permitindo um fluxo de trabalho linear. +- **Hierarchical Process**: Um agente gerente coordena a crew, delegando tarefas e validando resultados antes de prosseguir. **Nota**: Um `manager_llm` ou `manager_agent` é necessário para este processo e é essencial para validar o fluxo. + +### Iniciando uma Crew + +Uma vez que sua crew esteja montada, inicie o workflow com o método `kickoff()`. Isso inicia a execução conforme o fluxo de processo definido. + +```python Code +# Iniciar execução das tasks da crew +result = my_crew.kickoff() +print(result) +``` + +### Diferentes Formas de Iniciar uma Crew + +Assim que sua crew estiver definida, inicie o fluxo de trabalho com o método kickoff apropriado. O CrewAI oferece vários métodos para melhor controle do processo. + +#### Métodos Síncronos + +- `kickoff()`: Inicia o processo de execução seguindo o fluxo definido. +- `kickoff_for_each()`: Executa tasks sequencialmente para cada evento de entrada ou item da coleção fornecida. + +#### Métodos Assíncronos + +O CrewAI oferece duas abordagens para execução assíncrona: + +| Método | Tipo | Descrição | +|--------|------|-------------| +| `akickoff()` | Async nativo | Async/await verdadeiro em toda a cadeia de execução | +| `akickoff_for_each()` | Async nativo | Execução async nativa para cada entrada em uma lista | +| `kickoff_async()` | Baseado em thread | Envolve execução síncrona em `asyncio.to_thread` | +| `kickoff_for_each_async()` | Baseado em thread | Async baseado em thread para cada entrada em uma lista | + + +Para cargas de trabalho de alta concorrência, `akickoff()` e `akickoff_for_each()` são recomendados pois usam async nativo para execução de tasks, operações de memória e recuperação de conhecimento. + + +```python Code +# Iniciar execução das tasks da crew +result = my_crew.kickoff() +print(result) + +# Exemplo com kickoff_for_each +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +results = my_crew.kickoff_for_each(inputs=inputs_array) +for result in results: + print(result) + +# Exemplo usando async nativo com akickoff +inputs = {'topic': 'AI in healthcare'} +async_result = await my_crew.akickoff(inputs=inputs) +print(async_result) + +# Exemplo usando async nativo com akickoff_for_each +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +async_results = await my_crew.akickoff_for_each(inputs=inputs_array) +for async_result in async_results: + print(async_result) + +# Exemplo usando kickoff_async baseado em thread +inputs = {'topic': 'AI in healthcare'} +async_result = await my_crew.kickoff_async(inputs=inputs) +print(async_result) + +# Exemplo usando kickoff_for_each_async baseado em thread +inputs_array = [{'topic': 'AI in healthcare'}, {'topic': 'AI in finance'}] +async_results = await my_crew.kickoff_for_each_async(inputs=inputs_array) +for async_result in async_results: + print(async_result) +``` + +Esses métodos fornecem flexibilidade para gerenciar e executar tasks dentro de sua crew, permitindo fluxos de trabalho síncronos e assíncronos de acordo com sua necessidade. Para exemplos detalhados de async, consulte o guia [Inicie uma Crew de Forma Assíncrona](/pt-BR/learn/kickoff-async). + +### Streaming na Execução da Crew + +Para visibilidade em tempo real da execução da crew, você pode habilitar streaming para receber saída conforme é gerada: + +```python Code +# Habilitar streaming +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True +) + +# Iterar sobre saída em streaming +streaming = crew.kickoff(inputs={"topic": "AI"}) +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# Acessar resultado final +result = streaming.result +``` + +Saiba mais sobre streaming no guia [Streaming na Execução da Crew](/pt-BR/learn/streaming-crew-execution). + +### Repetindo Execução a partir de uma Task Específica + +Agora é possível reiniciar a execução a partir de uma task específica usando o comando CLI `replay`. + +O recurso de replay no CrewAI permite reexecutar a partir de uma task específica através da interface de linha de comando (CLI). Rodando o comando `crewai replay -t `, você pode especificar o `task_id` para o processo de replay. + +Kickoffs agora salvam localmente as saídas das tasks dos kickoffs recentes para permitir replay posteriormente. + +### Repetindo a Partir de uma Task Específica Usando o CLI + +Para usar o recurso de replay, siga estes passos: + +1. Abra seu terminal ou prompt de comando. +2. Navegue até o diretório do seu projeto CrewAI. +3. Execute o seguinte comando: + +Para visualizar os IDs das últimas tasks do kickoff, utilize: + +```shell +crewai log-tasks-outputs +``` + +Depois, para repetir a partir de uma task específica, utilize: + +```shell +crewai replay -t +``` + +Esses comandos permitem repetir tasks dos seus últimos kickoffs, mantendo o contexto das tasks já executadas anteriormente. diff --git a/docs/v1.15.13/pt-BR/concepts/event-listener.mdx b/docs/v1.15.13/pt-BR/concepts/event-listener.mdx new file mode 100644 index 0000000000..412440ab5d --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/event-listener.mdx @@ -0,0 +1,415 @@ +--- +title: "Listeners de Evento" +description: "Acesse eventos do CrewAI para criar integrações e monitoramento personalizados" +icon: spinner +mode: "wide" +--- + +## Visão Geral + +O CrewAI oferece um sistema de eventos poderoso que permite escutar e reagir a diversos eventos que ocorrem durante a execução do seu Crew. Esse recurso possibilita a criação de integrações personalizadas, soluções de monitoramento, sistemas de log ou qualquer outra funcionalidade que precise ser acionada com base nos eventos internos do CrewAI. + +## Como Funciona + +O CrewAI utiliza uma arquitetura de event bus para emitir eventos ao longo do ciclo de vida da execução. O sistema de eventos é construído a partir dos seguintes componentes: + +1. **CrewAIEventsBus**: Um event bus singleton que gerencia o registro e emissão de eventos +2. **BaseEvent**: Classe base para todos os eventos do sistema +3. **BaseEventListener**: Classe base abstrata para criar listeners de evento personalizados + +Quando ações específicas ocorrem no CrewAI (como a inicialização de um Crew, um Agent concluindo uma tarefa ou o uso de uma ferramenta), o sistema emite os eventos correspondentes. Você pode registrar handlers para esses eventos para executar código personalizado quando eles acontecerem. + + +O CrewAI AMP fornece o recurso Prompt Tracing, que aproveita o sistema de eventos para rastrear, armazenar e visualizar todos os prompts, respostas e metadados associados. Isso proporciona poderosas capacidades de depuração e transparência nas operações dos seus agentes. + +![Prompt Tracing Dashboard](/images/enterprise/traces-overview.png) + +Com o Prompt Tracing você pode: + +- Visualizar o histórico completo de todos os prompts enviados ao seu LLM +- Monitorar o uso de tokens e custos +- Depurar falhas de raciocínio dos agentes +- Compartilhar sequências de prompts com sua equipe +- Comparar diferentes estratégias de prompts +- Exportar rastreamentos para compliance e auditoria + + +## Criando um Listener de Evento Personalizado + +Para criar um listener de evento personalizado, você precisa: + +1. Criar uma classe que herde de `BaseEventListener` +2. Implementar o método `setup_listeners` +3. Registrar handles para os eventos de seu interesse +4. Instanciar seu listener no arquivo apropriado + +Veja um exemplo simples de uma classe de listener de evento personalizado: + +```python +from crewai.events import ( + CrewKickoffStartedEvent, + CrewKickoffCompletedEvent, + AgentExecutionCompletedEvent, +) +from crewai.events import BaseEventListener + +class MeuListenerPersonalizado(BaseEventListener): + def __init__(self): + super().__init__() + + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(CrewKickoffStartedEvent) + def ao_iniciar_crew(source, event): + print(f"Crew '{event.crew_name}' iniciou a execução!") + + @crewai_event_bus.on(CrewKickoffCompletedEvent) + def ao_finalizar_crew(source, event): + print(f"Crew '{event.crew_name}' finalizou a execução!") + print(f"Saída: {event.output}") + + @crewai_event_bus.on(AgentExecutionCompletedEvent) + def ao_finalizar_execucao_agente(source, event): + print(f"Agente '{event.agent.role}' concluiu a tarefa") + print(f"Saída: {event.output}") +``` + +## Registrando Corretamente Seu Listener + +Apenas definir sua classe de listener não é suficiente. É necessário criar uma instância dela e garantir que ela seja importada na sua aplicação. Isso garante que: + +1. Os event handlers estejam registrados no event bus +2. A instância do listener permaneça em memória (não seja coletada pelo garbage collector) +3. O listener esteja ativo quando os eventos forem emitidos + +### Opção 1: Importar e Instanciar no Seu Crew ou Implementação de Flow + +O mais importante é criar uma instância do seu listener no arquivo onde seu Crew ou Flow está definido e executado: + +#### Para Aplicações Baseadas em Crew + +Crie e importe seu listener no início do arquivo de implementação do seu Crew: + +```python +# No seu arquivo crew.py +from crewai import Agent, Crew, Task +from my_listeners import MyCustomListener + +# Crie uma instância do seu listener +my_listener = MyCustomListener() + +class MyCustomCrew: + # Sua implementação do crew... + + def crew(self): + return Crew( + agents=[...], + tasks=[...], + # ... + ) +``` + +#### Para Aplicações Baseadas em Flow + +Crie e importe seu listener no início do arquivo de implementação do seu Flow: + +```python +# Em seu arquivo main.py ou flow.py +from crewai.flow import Flow, listen, start +from my_listeners import MyCustomListener + +# Crie uma instância do seu listener +my_listener = MyCustomListener() + +class MyCustomFlow(Flow): + # Sua implementação do flow... + + @start() + def first_step(self): + # ... +``` + +Isso assegura que seu listener será carregado e estará ativo quando seu Crew ou Flow for executado. + +### Opção 2: Criar um Pacote para Seus Listeners + +Para uma abordagem mais estruturada, especialmente se houver múltiplos listeners: + +1. Crie um pacote para seus listeners: + +``` +my_project/ + ├── listeners/ + │ ├── __init__.py + │ ├── my_custom_listener.py + │ └── another_listener.py +``` + +2. Em `my_custom_listener.py`, defina sua classe de listener e crie uma instância: + +```python +# my_custom_listener.py +from crewai.events import BaseEventListener +# ... importe events ... + +class MyCustomListener(BaseEventListener): + # ... implementação ... + +# Crie uma instância do seu listener +my_custom_listener = MyCustomListener() +``` + +3. Em `__init__.py`, importe as instâncias dos listeners para garantir seu carregamento: + +```python +# __init__.py +from .my_custom_listener import my_custom_listener +from .another_listener import another_listener + +# Opcionalmente exporte-os se precisar acessá-los em outros lugares +__all__ = ['my_custom_listener', 'another_listener'] +``` + +4. Importe seu pacote de listeners no arquivo do seu Crew ou Flow: + +```python +# No seu arquivo crew.py ou flow.py +import my_project.listeners # Isso carrega todos os seus listeners + +class MyCustomCrew: + # Sua implementação do crew... +``` + +É assim que listeners de eventos de terceiros são registrados no código do CrewAI. + +## Tipos de Eventos Disponíveis + +O CrewAI fornece uma ampla variedade de eventos para escuta: + +### Eventos de Crew + +- **CrewKickoffStartedEvent**: Emitido quando um Crew inicia a execução +- **CrewKickoffCompletedEvent**: Emitido quando um Crew conclui a execução +- **CrewKickoffFailedEvent**: Emitido quando um Crew falha ao concluir a execução +- **CrewTestStartedEvent**: Emitido ao iniciar o teste de um Crew +- **CrewTestCompletedEvent**: Emitido ao concluir o teste de um Crew +- **CrewTestFailedEvent**: Emitido ao falhar no teste de um Crew +- **CrewTrainStartedEvent**: Emitido ao iniciar o treinamento de um Crew +- **CrewTrainCompletedEvent**: Emitido ao concluir o treinamento de um Crew +- **CrewTrainFailedEvent**: Emitido ao falhar no treinamento de um Crew +- **CrewTestResultEvent**: Emitido quando um resultado de teste de Crew está disponível. Contém a pontuação de qualidade, duração da execução e modelo utilizado. + +### Eventos de Agent + +- **AgentExecutionStartedEvent**: Emitido quando um Agent inicia a execução de uma tarefa +- **AgentExecutionCompletedEvent**: Emitido quando um Agent conclui a execução de uma tarefa +- **AgentExecutionErrorEvent**: Emitido quando um Agent encontra um erro durante a execução +- **LiteAgentExecutionStartedEvent**: Emitido quando um LiteAgent inicia a execução. Contém as informações do agente, ferramentas e mensagens. +- **LiteAgentExecutionCompletedEvent**: Emitido quando um LiteAgent conclui a execução. Contém as informações do agente e a saída. +- **LiteAgentExecutionErrorEvent**: Emitido quando um LiteAgent encontra um erro durante a execução. Contém as informações do agente e a mensagem de erro. +- **AgentEvaluationStartedEvent**: Emitido quando uma avaliação de agente é iniciada. Contém o ID do agente, papel do agente, ID da tarefa opcional e número da iteração. +- **AgentEvaluationCompletedEvent**: Emitido quando uma avaliação de agente é concluída. Contém o ID do agente, papel do agente, ID da tarefa opcional, número da iteração, categoria da métrica e pontuação. +- **AgentEvaluationFailedEvent**: Emitido quando uma avaliação de agente falha. Contém o ID do agente, papel do agente, ID da tarefa opcional, número da iteração e mensagem de erro. + +### Eventos de Task + +- **TaskStartedEvent**: Emitido ao iniciar a execução de uma Task +- **TaskCompletedEvent**: Emitido ao concluir a execução de uma Task +- **TaskFailedEvent**: Emitido ao falhar na execução de uma Task +- **TaskEvaluationEvent**: Emitido quando uma Task é avaliada + +### Eventos de Uso de Ferramentas + +- **ToolUsageStartedEvent**: Emitido ao iniciar a execução de uma ferramenta +- **ToolUsageFinishedEvent**: Emitido ao concluir a execução de uma ferramenta +- **ToolUsageErrorEvent**: Emitido quando ocorre erro na execução de uma ferramenta +- **ToolValidateInputErrorEvent**: Emitido ao ocorrer erro de validação de entrada na ferramenta +- **ToolExecutionErrorEvent**: Emitido quando ocorre erro na execução de uma ferramenta +- **ToolSelectionErrorEvent**: Emitido ao ocorrer erro na seleção de uma ferramenta + +### Eventos de MCP + +- **MCPConnectionStartedEvent**: Emitido ao iniciar a conexão com um servidor MCP. Contém o nome do servidor, URL, tipo de transporte, timeout de conexão e se é uma tentativa de reconexão. +- **MCPConnectionCompletedEvent**: Emitido ao conectar com sucesso a um servidor MCP. Contém o nome do servidor, duração da conexão em milissegundos e se foi uma reconexão. +- **MCPConnectionFailedEvent**: Emitido quando a conexão com um servidor MCP falha. Contém o nome do servidor, mensagem de erro e tipo de erro (`timeout`, `authentication`, `network`, etc.). +- **MCPToolExecutionStartedEvent**: Emitido ao iniciar a execução de uma ferramenta MCP. Contém o nome do servidor, nome da ferramenta e argumentos da ferramenta. +- **MCPToolExecutionCompletedEvent**: Emitido quando a execução de uma ferramenta MCP é concluída com sucesso. Contém o nome do servidor, nome da ferramenta, resultado e duração da execução em milissegundos. +- **MCPToolExecutionFailedEvent**: Emitido quando a execução de uma ferramenta MCP falha. Contém o nome do servidor, nome da ferramenta, mensagem de erro e tipo de erro (`timeout`, `validation`, `server_error`, etc.). +- **MCPConfigFetchFailedEvent**: Emitido quando a obtenção da configuração de um servidor MCP falha (ex.: o MCP não está conectado na sua conta, erro de API ou falha de conexão após a configuração ser obtida). Contém o slug, mensagem de erro e tipo de erro (`not_connected`, `api_error`, `connection_failed`). + +### Eventos de Knowledge + +- **KnowledgeRetrievalStartedEvent**: Emitido ao iniciar recuperação de conhecimento +- **KnowledgeRetrievalCompletedEvent**: Emitido ao concluir recuperação de conhecimento +- **KnowledgeQueryStartedEvent**: Emitido ao iniciar consulta de conhecimento +- **KnowledgeQueryCompletedEvent**: Emitido ao concluir consulta de conhecimento +- **KnowledgeQueryFailedEvent**: Emitido ao falhar consulta de conhecimento +- **KnowledgeSearchQueryFailedEvent**: Emitido ao falhar consulta de busca de conhecimento + +### Eventos de Guardrail do LLM + +- **LLMGuardrailStartedEvent**: Emitido ao iniciar validação dos guardrails. Contém detalhes do guardrail aplicado e tentativas. +- **LLMGuardrailCompletedEvent**: Emitido ao concluir validação dos guardrails. Contém detalhes sobre sucesso/falha na validação, resultados e mensagens de erro, se houver. +- **LLMGuardrailFailedEvent**: Emitido quando a validação do guardrail falha. Contém a mensagem de erro e o número de tentativas. + +### Eventos de Flow + +- **FlowCreatedEvent**: Emitido ao criar um Flow +- **FlowStartedEvent**: Emitido ao iniciar a execução de um Flow +- **FlowFinishedEvent**: Emitido ao concluir a execução de um Flow +- **FlowFailedEvent**: Emitido quando a execução de um Flow falha. Contém o nome do flow e a exceção que encerrou a execução. +- **FlowPausedEvent**: Emitido quando um Flow é pausado aguardando feedback humano. Contém o nome do flow, ID do flow, nome do método, estado atual, mensagem exibida ao solicitar feedback e lista opcional de resultados possíveis para roteamento. +- **FlowPlotEvent**: Emitido ao plotar um Flow +- **MethodExecutionStartedEvent**: Emitido ao iniciar a execução de um método do Flow +- **MethodExecutionFinishedEvent**: Emitido ao concluir a execução de um método do Flow +- **MethodExecutionFailedEvent**: Emitido ao falhar na execução de um método do Flow +- **MethodExecutionPausedEvent**: Emitido quando um método do Flow é pausado aguardando feedback humano. Contém o nome do flow, nome do método, estado atual, ID do flow, mensagem exibida ao solicitar feedback e lista opcional de resultados possíveis para roteamento. + +### Eventos de Human In The Loop + +- **FlowInputRequestedEvent**: Emitido quando um Flow solicita entrada do usuário via `Flow.ask()`. Contém o nome do flow, nome do método, a pergunta ou prompt exibido ao usuário e metadados opcionais (ex.: ID do usuário, canal, contexto da sessão). +- **FlowInputReceivedEvent**: Emitido quando a entrada do usuário é recebida após `Flow.ask()`. Contém o nome do flow, nome do método, a pergunta original, a resposta do usuário (ou `None` se expirou), metadados opcionais da solicitação e metadados opcionais da resposta do provedor (ex.: quem respondeu, ID do thread, timestamps). +- **HumanFeedbackRequestedEvent**: Emitido quando um método decorado com `@human_feedback` requer entrada de um revisor humano. Contém o nome do flow, nome do método, a saída do método exibida ao humano para revisão, a mensagem exibida ao solicitar feedback e lista opcional de resultados possíveis para roteamento. +- **HumanFeedbackReceivedEvent**: Emitido quando um humano fornece feedback em resposta a um método decorado com `@human_feedback`. Contém o nome do flow, nome do método, o texto bruto do feedback fornecido pelo humano e a string de resultado consolidada (se emit foi especificado). + +### Eventos de LLM + +- **LLMCallStartedEvent**: Emitido ao iniciar uma chamada LLM +- **LLMCallCompletedEvent**: Emitido ao concluir uma chamada LLM +- **LLMCallFailedEvent**: Emitido ao falhar uma chamada LLM +- **LLMStreamChunkEvent**: Emitido para cada chunk recebido durante respostas em streaming do LLM +- **LLMThinkingChunkEvent**: Emitido quando um chunk de pensamento/raciocínio é recebido de um modelo de pensamento. Contém o texto do chunk e ID de resposta opcional. + +### Eventos de Memória + +- **MemoryQueryStartedEvent**: Emitido quando uma consulta de memória é iniciada. Contém a consulta, limite e threshold de pontuação opcional. +- **MemoryQueryCompletedEvent**: Emitido quando uma consulta de memória é concluída com sucesso. Contém a consulta, resultados, limite, threshold de pontuação e tempo de execução da consulta. +- **MemoryQueryFailedEvent**: Emitido quando uma consulta de memória falha. Contém a consulta, limite, threshold de pontuação e mensagem de erro. +- **MemorySaveStartedEvent**: Emitido quando uma operação de salvamento de memória é iniciada. Contém o valor a ser salvo, metadados e papel do agente opcional. +- **MemorySaveCompletedEvent**: Emitido quando uma operação de salvamento de memória é concluída com sucesso. Contém o valor salvo, metadados, papel do agente e tempo de salvamento. +- **MemorySaveFailedEvent**: Emitido quando uma operação de salvamento de memória falha. Contém o valor, metadados, papel do agente e mensagem de erro. +- **MemoryRetrievalStartedEvent**: Emitido quando a recuperação de memória para um prompt de tarefa é iniciada. Contém o ID da tarefa opcional. +- **MemoryRetrievalCompletedEvent**: Emitido quando a recuperação de memória para um prompt de tarefa é concluída com sucesso. Contém o ID da tarefa, conteúdo da memória e tempo de execução da recuperação. +- **MemoryRetrievalFailedEvent**: Emitido quando a recuperação de memória para um prompt de tarefa falha. Contém o ID da tarefa opcional e mensagem de erro. + +### Eventos de Raciocínio + +- **AgentReasoningStartedEvent**: Emitido quando um agente começa a raciocinar sobre uma tarefa. Contém o papel do agente, ID da tarefa e número da tentativa. +- **AgentReasoningCompletedEvent**: Emitido quando um agente finaliza seu processo de raciocínio. Contém o papel do agente, ID da tarefa, o plano produzido e se o agente está pronto para prosseguir. +- **AgentReasoningFailedEvent**: Emitido quando o processo de raciocínio falha. Contém o papel do agente, ID da tarefa e mensagem de erro. + +### Eventos de Observação + +- **StepObservationStartedEvent**: Emitido quando o Planner começa a observar o resultado de um passo. Disparado após cada execução de passo, antes da chamada LLM de observação. Contém o papel do agente, número do passo e descrição do passo. +- **StepObservationCompletedEvent**: Emitido quando o Planner finaliza a observação do resultado de um passo. Contém se o passo foi concluído com sucesso, informações-chave aprendidas, se o plano restante ainda é válido, se é necessário um replanejamento completo e refinamentos sugeridos. +- **StepObservationFailedEvent**: Emitido quando a chamada LLM de observação falha. O sistema continua o plano por padrão. Contém a mensagem de erro. +- **PlanRefinementEvent**: Emitido quando o Planner refina descrições de passos futuros sem replanejamento completo. Contém o número de passos refinados e os refinamentos aplicados. +- **PlanReplanTriggeredEvent**: Emitido quando o Planner dispara um replanejamento completo porque o plano restante foi considerado fundamentalmente incorreto. Contém o motivo do replanejamento, contagem de replanejamentos e número de passos concluídos preservados. +- **GoalAchievedEarlyEvent**: Emitido quando o Planner detecta que o objetivo foi alcançado antecipadamente e os passos restantes serão ignorados. Contém o número de passos restantes e passos concluídos. + +### Eventos A2A (Agent-to-Agent) + +#### Eventos de Delegação + +- **A2ADelegationStartedEvent**: Emitido quando a delegação A2A é iniciada. Contém a URL do endpoint, descrição da tarefa, ID do agente, ID do contexto, se é multiturn, número do turno, metadados do agent card, versão do protocolo, informações do provedor e ID da skill opcional. +- **A2ADelegationCompletedEvent**: Emitido quando a delegação A2A é concluída. Contém o status de conclusão (`completed`, `input_required`, `failed`, etc.), resultado, mensagem de erro, ID do contexto e metadados do agent card. +- **A2AParallelDelegationStartedEvent**: Emitido quando a delegação paralela para múltiplos agentes A2A é iniciada. Contém a lista de endpoints e a descrição da tarefa. +- **A2AParallelDelegationCompletedEvent**: Emitido quando a delegação paralela para múltiplos agentes A2A é concluída. Contém a lista de endpoints, contagem de sucessos, contagem de falhas e resumo dos resultados. + +#### Eventos de Conversação + +- **A2AConversationStartedEvent**: Emitido uma vez no início de uma conversação multiturn A2A, antes da primeira troca de mensagens. Contém o ID do agente, endpoint, ID do contexto, metadados do agent card, versão do protocolo e informações do provedor. +- **A2AMessageSentEvent**: Emitido quando uma mensagem é enviada ao agente A2A. Contém o conteúdo da mensagem, número do turno, ID do contexto, ID da mensagem e se é multiturn. +- **A2AResponseReceivedEvent**: Emitido quando uma resposta é recebida do agente A2A. Contém o conteúdo da resposta, número do turno, ID do contexto, ID da mensagem, status e se é a resposta final. +- **A2AConversationCompletedEvent**: Emitido uma vez ao final de uma conversação multiturn A2A. Contém o status final (`completed` ou `failed`), resultado final, mensagem de erro, ID do contexto e número total de turnos. + +#### Eventos de Streaming + +- **A2AStreamingStartedEvent**: Emitido quando o modo streaming é iniciado para delegação A2A. Contém o ID da tarefa, ID do contexto, endpoint, número do turno e se é multiturn. +- **A2AStreamingChunkEvent**: Emitido quando um chunk de streaming é recebido. Contém o texto do chunk, índice do chunk, se é o chunk final, ID da tarefa, ID do contexto e número do turno. + +#### Eventos de Polling e Push Notification + +- **A2APollingStartedEvent**: Emitido quando o modo polling é iniciado para delegação A2A. Contém o ID da tarefa, ID do contexto, intervalo de polling em segundos e endpoint. +- **A2APollingStatusEvent**: Emitido em cada iteração de polling. Contém o ID da tarefa, ID do contexto, estado atual da tarefa, segundos decorridos e contagem de polls. +- **A2APushNotificationRegisteredEvent**: Emitido quando um callback de push notification é registrado. Contém o ID da tarefa, ID do contexto, URL do callback e endpoint. +- **A2APushNotificationReceivedEvent**: Emitido quando uma push notification é recebida do agente A2A remoto. Contém o ID da tarefa, ID do contexto e estado atual. +- **A2APushNotificationSentEvent**: Emitido quando uma push notification é enviada para uma URL de callback. Contém o ID da tarefa, ID do contexto, URL do callback, estado, se a entrega foi bem-sucedida e mensagem de erro opcional. +- **A2APushNotificationTimeoutEvent**: Emitido quando a espera por push notification expira. Contém o ID da tarefa, ID do contexto e duração do timeout em segundos. + +#### Eventos de Conexão e Autenticação + +- **A2AAgentCardFetchedEvent**: Emitido quando um agent card é obtido com sucesso. Contém o endpoint, nome do agente, metadados do agent card, versão do protocolo, informações do provedor, se foi do cache e tempo de busca em milissegundos. +- **A2AAuthenticationFailedEvent**: Emitido quando a autenticação com um agente A2A falha. Contém o endpoint, tipo de autenticação tentada (ex.: `bearer`, `oauth2`, `api_key`), mensagem de erro e código de status HTTP. +- **A2AConnectionErrorEvent**: Emitido quando ocorre um erro de conexão durante a comunicação A2A. Contém o endpoint, mensagem de erro, tipo de erro (ex.: `timeout`, `connection_refused`, `dns_error`), código de status HTTP e a operação sendo tentada. +- **A2ATransportNegotiatedEvent**: Emitido quando o protocolo de transporte é negociado com um agente A2A. Contém o transporte negociado, URL negociada, fonte de seleção (`client_preferred`, `server_preferred`, `fallback`) e transportes suportados pelo cliente/servidor. +- **A2AContentTypeNegotiatedEvent**: Emitido quando os tipos de conteúdo são negociados com um agente A2A. Contém os modos de entrada/saída do cliente/servidor, modos de entrada/saída negociados e se a negociação foi bem-sucedida. + +#### Eventos de Artefatos + +- **A2AArtifactReceivedEvent**: Emitido quando um artefato é recebido de um agente A2A remoto. Contém o ID da tarefa, ID do artefato, nome do artefato, descrição, tipo MIME, tamanho em bytes e se o conteúdo deve ser concatenado. + +#### Eventos de Tarefa do Servidor + +- **A2AServerTaskStartedEvent**: Emitido quando a execução de uma tarefa do servidor A2A é iniciada. Contém o ID da tarefa e ID do contexto. +- **A2AServerTaskCompletedEvent**: Emitido quando a execução de uma tarefa do servidor A2A é concluída. Contém o ID da tarefa, ID do contexto e resultado. +- **A2AServerTaskCanceledEvent**: Emitido quando a execução de uma tarefa do servidor A2A é cancelada. Contém o ID da tarefa e ID do contexto. +- **A2AServerTaskFailedEvent**: Emitido quando a execução de uma tarefa do servidor A2A falha. Contém o ID da tarefa, ID do contexto e mensagem de erro. + +#### Eventos de Ciclo de Vida do Contexto + +- **A2AContextCreatedEvent**: Emitido quando um contexto A2A é criado. Contextos agrupam tarefas relacionadas em uma conversação ou workflow. Contém o ID do contexto e timestamp de criação. +- **A2AContextExpiredEvent**: Emitido quando um contexto A2A expira devido ao TTL. Contém o ID do contexto, timestamp de criação, idade em segundos e contagem de tarefas. +- **A2AContextIdleEvent**: Emitido quando um contexto A2A fica inativo (sem atividade pelo threshold configurado). Contém o ID do contexto, tempo de inatividade em segundos e contagem de tarefas. +- **A2AContextCompletedEvent**: Emitido quando todas as tarefas em um contexto A2A são concluídas. Contém o ID do contexto, total de tarefas e duração em segundos. +- **A2AContextPrunedEvent**: Emitido quando um contexto A2A é podado (deletado). Contém o ID do contexto, contagem de tarefas e idade em segundos. + +## Estrutura dos Handlers de Evento + +Cada handler de evento recebe dois parâmetros: + +1. **source**: O objeto que emitiu o evento +2. **event**: A instância do evento, contendo dados específicos do evento + +A estrutura do objeto de evento depende do tipo do evento, mas todos herdam de `BaseEvent` e incluem: + +- **timestamp**: O horário em que o evento foi emitido +- **type**: Identificador do tipo do evento + +Campos adicionais variam pelo tipo de evento. Por exemplo, `CrewKickoffCompletedEvent` inclui os campos `crew_name` e `output`. + +## Uso Avançado: Handlers Escopados + +Para lidar temporariamente com eventos (útil para testes ou operações específicas), você pode usar o context manager `scoped_handlers`: + +```python +from crewai.events import crewai_event_bus, CrewKickoffStartedEvent + +with crewai_event_bus.scoped_handlers(): + @crewai_event_bus.on(CrewKickoffStartedEvent) + def temp_handler(source, event): + print("Este handler só existe neste contexto") + + # Faça algo que emita eventos + +# Fora do contexto, o handler temporário é removido +``` + +## Casos de Uso + +Listeners de evento podem ser usados para várias finalidades: + +1. **Log e Monitoramento**: Monitore a execução do seu Crew e registre eventos importantes +2. **Analytics**: Colete dados sobre o desempenho e comportamento do seu Crew +3. **Depuração**: Configure listeners temporários para debugar problemas específicos +4. **Integração**: Conecte o CrewAI a sistemas externos como plataformas de monitoramento, bancos de dados ou serviços de notificação +5. **Comportamento Personalizado**: Dispare ações personalizadas com base em eventos específicos + +## Boas Práticas + +1. **Mantenha Handlers Leves**: Handlers de eventos devem ser leves e evitar operações bloqueantes +2. **Tratamento de Erros**: Implemente tratamento de erros adequado nos event handlers para evitar que exceções afetem a execução principal +3. **Limpeza**: Se seu listener alocar recursos, garanta o devido fechamento/liberação +4. **Escuta Seletiva**: Escute apenas eventos que realmente precisa tratar +5. **Testes**: Teste seus listeners de evento isoladamente para garantir que se comportam conforme esperado + +Aproveitando o sistema de eventos do CrewAI, é possível estender a funcionalidade e integrá-lo facilmente à sua infraestrutura existente. diff --git a/docs/v1.15.13/pt-BR/concepts/files.mdx b/docs/v1.15.13/pt-BR/concepts/files.mdx new file mode 100644 index 0000000000..cc2f4f3cac --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/files.mdx @@ -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. + + +O suporte a arquivos requer o pacote opcional `crewai-files`. Instale com: + +```bash +uv add 'crewai[file-processing]' +``` + + + +A API de processamento de arquivos está atualmente em acesso antecipado. + + +## 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) | ✓ | | ✓ | | | + + +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. + + + +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. + + +## 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** | ✓ | | ✓ | + + +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. + + +## 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"), + } +) +``` diff --git a/docs/v1.15.13/pt-BR/concepts/flows.mdx b/docs/v1.15.13/pt-BR/concepts/flows.mdx new file mode 100644 index 0000000000..d70bb9774b --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/flows.mdx @@ -0,0 +1,1073 @@ +--- +title: Flows +description: Saiba como criar e gerenciar fluxos de trabalho de IA usando CrewAI Flows. +icon: arrow-progress +mode: "wide" +--- + +## Visão Geral + +O CrewAI Flows é um recurso poderoso projetado para simplificar a criação e o gerenciamento de fluxos de trabalho de IA. Os flows permitem que desenvolvedores combinem e coordenem tarefas de codificação e crews de forma eficiente, proporcionando uma estrutura robusta para a construção de automações de IA sofisticadas. + +Os flows permitem que você crie fluxos de trabalho estruturados e orientados por eventos. Eles oferecem uma forma integrada de conectar múltiplas tarefas, gerenciar estado e controlar o fluxo de execução nas suas aplicações de IA. Com flows, você pode facilmente projetar e implementar processos de múltiplas etapas que exploram todo o potencial das capacidades do CrewAI. + +1. **Criação Simplificada de Fluxos de Trabalho**: Conecte facilmente múltiplas crews e tarefas para criar workflows de IA complexos. + +2. **Gerenciamento de Estado**: Flows facilitam muito o gerenciamento e o compartilhamento de estados entre diferentes tarefas do seu fluxo de trabalho. + +3. **Arquitetura Orientada a Eventos**: Construído sobre um modelo orientado a eventos, permitindo fluxos dinâmicos e responsivos. + +4. **Controle de Fluxo Flexível**: Implemente lógica condicional, loops e ramificações dentro dos seus fluxos. + +## Primeiros Passos + +Vamos criar um Flow simples no qual você usará a OpenAI para gerar uma cidade aleatória em uma tarefa e, em seguida, usará essa cidade para gerar uma curiosidade em outra tarefa. + +```python Code + +from crewai.flow.flow import Flow, listen, start +from dotenv import load_dotenv +from litellm import completion + +load_dotenv() + +class ExampleFlow(Flow): + model = "gpt-4o-mini" + + @start() + def generate_city(self): + print("Starting flow") + # Cada estado do flow recebe automaticamente um ID único + print(f"Flow State ID: {self.state['id']}") + + response = completion( + model=self.model, + messages=[ + { + "role": "user", + "content": "Return the name of a random city in the world.", + }, + ], + ) + + random_city = response["choices"][0]["message"]["content"] + # Armazena a cidade no nosso estado + self.state["city"] = random_city + print(f"Random City: {random_city}") + + return random_city + + @listen(generate_city) + def generate_fun_fact(self, random_city): + response = completion( + model=self.model, + messages=[ + { + "role": "user", + "content": f"Tell me a fun fact about {random_city}", + }, + ], + ) + + fun_fact = response["choices"][0]["message"]["content"] + # Armazena a curiosidade no nosso estado + self.state["fun_fact"] = fun_fact + return fun_fact + + + +flow = ExampleFlow() +flow.plot() +result = flow.kickoff() + +print(f"Generated fun fact: {result}") +``` + +Na ilustração acima, criamos um Flow simples que gera uma cidade aleatória usando a OpenAI e depois cria uma curiosidade sobre essa cidade. O Flow consiste em duas tarefas: `generate_city` e `generate_fun_fact`. A tarefa `generate_city` é o ponto de início do Flow, enquanto a tarefa `generate_fun_fact` fica escutando o resultado da tarefa `generate_city`. + +Cada instância de Flow recebe automaticamente um identificador único (UUID) em seu estado, que auxilia no rastreamento e gerenciamento das execuções. O estado também pode armazenar dados adicionais (como a cidade gerada e a curiosidade) que permanecem durante toda a execução do flow. + +Ao executar o Flow, ele irá: +1. Gerar um ID único para o estado do flow +2. Gerar uma cidade aleatória e armazená-la no estado +3. Gerar uma curiosidade sobre essa cidade e armazená-la no estado +4. Imprimir os resultados no console + +O ID único do estado e os dados armazenados podem ser úteis para rastrear execuções do flow e manter contexto entre as tarefas. + +**Nota:** Certifique-se de configurar seu arquivo `.env` para armazenar sua `OPENAI_API_KEY`. Essa chave é necessária para autenticar as requisições à API da OpenAI. + +### @start() + +O decorador `@start()` é utilizado para marcar um método como ponto inicial de um Flow. Quando um Flow é iniciado, todos os métodos decorados com `@start()` são executados em paralelo. É possível ter múltiplos métodos start em um Flow, e todos eles serão executados quando o Flow iniciar. + +### @listen() + +O decorador `@listen()` é utilizado para marcar um método como ouvinte da saída de outra tarefa do Flow. O método decorado com `@listen()` será executado quando a tarefa especificada emitir uma saída. O método pode acessar a saída da tarefa à qual está escutando como argumento. + +#### Utilização + +O decorador `@listen()` pode ser usado de várias formas: + +1. **Escutando um Método pelo Nome**: Você pode passar o nome do método ao qual deseja escutar como string. Quando esse método concluir, o método ouvinte será chamado. + + ```python Code + @listen("generate_city") + def generate_fun_fact(self, random_city): + # Implementação + ``` + +2. **Escutando um Método Diretamente**: Você pode passar o próprio método. Quando esse método concluir, o método ouvinte será chamado. + ```python Code + @listen(generate_city) + def generate_fun_fact(self, random_city): + # Implementação + ``` + +### Saída de um Flow + +Acessar e manipular a saída de um Flow é essencial para integrar seus workflows de IA a aplicações ou sistemas maiores. O CrewAI Flows fornece mecanismos fáceis para recuperar a saída final, acessar resultados intermediários e gerenciar o estado geral do seu Flow. + +#### Recuperando a Saída Final + +Ao executar um Flow, a saída final é determinada pelo último método concluído. O método `kickoff()` retorna a saída desse método final. + +Veja como acessar a saída final: + + +```python Code +from crewai.flow.flow import Flow, listen, start + +class OutputExampleFlow(Flow): + @start() + def first_method(self): + return "Output from first_method" + + @listen(first_method) + def second_method(self, first_output): + return f"Second method received: {first_output}" + + +flow = OutputExampleFlow() +flow.plot("my_flow_plot") +final_output = flow.kickoff() + +print("---- Final Output ----") +print(final_output) +``` + +```text Output +---- Final Output ---- +Second method received: Output from first_method +``` + + +![Flow Visual image](/images/crewai-flow-2.png) + +Neste exemplo, o `second_method` é o último método a ser concluído, logo sua saída será a saída final do Flow. +O método `kickoff()` retorna essa saída, que é impressa no console. O método `plot()` irá gerar o arquivo HTML para visualizar o fluxo. + +#### Acessando e Atualizando o Estado + +Além de recuperar a saída final, você pode acessar e atualizar o estado dentro do seu Flow. O estado pode ser usado para armazenar e compartilhar dados entre diferentes métodos do Flow. Após a execução do Flow, você pode acessar o estado para recuperar informações adicionadas ou alteradas durante o processo. + +Veja um exemplo de como atualizar e acessar o estado: + + + +```python Code +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + counter: int = 0 + message: str = "" + +class StateExampleFlow(Flow[ExampleState]): + + @start() + def first_method(self): + self.state.message = "Hello from first_method" + self.state.counter += 1 + + @listen(first_method) + def second_method(self): + self.state.message += " - updated by second_method" + self.state.counter += 1 + return self.state.message + +flow = StateExampleFlow() +flow.plot("my_flow_plot") +final_output = flow.kickoff() +print(f"Final Output: {final_output}") +print("Final State:") +print(flow.state) +``` + +```text Output +Final Output: Hello from first_method - updated by second_method +Final State: +counter=2 message='Hello from first_method - updated by second_method' +``` + + +![Flow Visual image](/images/crewai-flow-2.png) + +Neste exemplo, o estado é atualizado tanto por `first_method` quanto por `second_method`. +Após o término da execução, é possível acessar o estado final e observar as atualizações realizadas por esses métodos. + +Ao garantir que a saída do método final seja retornada e oferecer acesso ao estado, o CrewAI Flows facilita a integração dos resultados dos seus workflows de IA em aplicações maiores, +além de permitir o gerenciamento e o acesso ao estado durante toda a execução do Flow. + +## Métricas de Uso do Flow + +Após a execução de um Flow, você pode acessar a propriedade `usage_metrics` para visualizar o consumo agregado de tokens em **todas as chamadas de LLM** realizadas durante a execução — incluindo chamadas das Crews orquestradas pelo Flow, chamadas dentro de tools de Agents, e invocações diretas de `LLM.call(...)` feitas a partir de métodos do Flow. Esse é o equivalente, do lado do SDK, ao total exibido na interface do CrewAI Enterprise. + +```python Code +from crewai import LLM +from crewai.flow.flow import Flow, listen, start + +class UsageMetricsFlow(Flow): + @start() + def run_first_crew(self): + self.state.first_result = FirstCrew().crew().kickoff() + + @listen(run_first_crew) + def call_llm_directly(self): + # Chamada direta de LLM — também contabilizada por flow.usage_metrics + llm = LLM(model="openai/gpt-4o-mini") + self.state.summary = llm.call("Resuma os principais pontos.") + + @listen(call_llm_directly) + def run_second_crew(self): + self.state.second_result = SecondCrew().crew().kickoff() + +flow = UsageMetricsFlow() +flow.kickoff() + +print(flow.usage_metrics) +# UsageMetrics(total_tokens=8579, prompt_tokens=6210, completion_tokens=2369, +# cached_prompt_tokens=0, reasoning_tokens=0, +# cache_creation_tokens=0, successful_requests=5) +``` + + + `flow.usage_metrics` **não** é o mesmo que `flow.kickoff().token_usage`. Este + último retorna apenas o `CrewOutput.token_usage` do **último** método + `@listen` que retornou um `CrewOutput`, ou seja, reflete somente a Crew + final e ignora completamente as Crews anteriores e quaisquer chamadas + diretas de `LLM.call(...)`. Use `flow.usage_metrics` sempre que precisar do + rollup **completo** de tokens da execução do Flow. + + +### Semântica dos campos UsageMetrics + +O objeto [`UsageMetrics`](https://github.com/crewAIInc/crewAI/blob/main/lib/crewai/src/crewai/types/usage_metrics.py) retornado usa um contrato neutro em relação ao provedor: + +| Campo | Significado | +| --- | --- | +| `total_tokens` | Total faturado: `prompt_tokens + completion_tokens` | +| `prompt_tokens` | Total de tokens de entrada/prompt faturados para a requisição | +| `completion_tokens` | Tokens de saída/conclusão faturados para a requisição | +| `cached_prompt_tokens` | Subconjunto de leitura de cache dos tokens de prompt (apenas breakdown) | +| `cache_creation_tokens` | Subconjunto de escrita de cache dos tokens de prompt (apenas breakdown, Anthropic) | +| `reasoning_tokens` | Subconjunto de raciocínio/pensamento quando o provedor reporta separadamente (apenas breakdown) | +| `successful_requests` | Número de chamadas LLM agregadas | + +Campos de breakdown como `cached_prompt_tokens`, `cache_creation_tokens` e `reasoning_tokens` **não** são somados sobre `total_tokens` — eles descrevem porções já incluídas em `prompt_tokens` ou `completion_tokens`. + +Para Anthropic, os contadores de leitura e escrita de cache são incorporados em `prompt_tokens`, de modo que workloads em cache são totalmente refletidos em `total_tokens`. Provedores no estilo OpenAI já incluem a entrada em cache dentro de `prompt_tokens`; o CrewAI expõe a porção em cache separadamente para visibilidade. + +Cada campo do [`UsageMetrics`](https://github.com/crewAIInc/crewAI/blob/main/lib/crewai/src/crewai/types/usage_metrics.py) retornado representa a soma de todas as chamadas de LLM feitas em uma única invocação de `flow.kickoff()`. Os contadores são resetados a cada novo `kickoff()` (e em cada iteração de `kickoff_for_each`), de modo que execuções sucessivas não duplicam o total. A propriedade é segura para ser lida em qualquer momento após o `kickoff()`; lê-la durante a execução retorna o total parcial acumulado até aquele instante. + +## Gerenciamento de Estado em Flows + +Gerenciar o estado de forma eficaz é fundamental para construir fluxos de trabalho de IA confiáveis e de fácil manutenção. O CrewAI Flows oferece mecanismos robustos para o gerenciamento de estado tanto não estruturado quanto estruturado, +permitindo que o desenvolvedor escolha a abordagem que melhor se adapta à sua aplicação. + +### Gerenciamento de Estado Não Estruturado + +No gerenciamento de estado não estruturado, todo o estado é armazenado no atributo `state` da classe `Flow`. +Essa abordagem oferece flexibilidade, permitindo que o desenvolvedor adicione ou modifique atributos do estado conforme necessário sem precisar definir um esquema rígido. +Mesmo com estados não estruturados, os flows do CrewAI geram e mantêm automaticamente um identificador único (UUID) para cada instância de estado. + +```python Code +from crewai.flow.flow import Flow, listen, start + +class UnstructuredExampleFlow(Flow): + + @start() + def first_method(self): + # O estado inclui automaticamente um campo 'id' + print(f"State ID: {self.state['id']}") + self.state['counter'] = 0 + self.state['message'] = "Hello from structured flow" + + @listen(first_method) + def second_method(self): + self.state['counter'] += 1 + self.state['message'] += " - updated" + + @listen(second_method) + def third_method(self): + self.state['counter'] += 1 + self.state['message'] += " - updated again" + + print(f"State after third_method: {self.state}") + + +flow = UnstructuredExampleFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +![Flow Visual image](/images/crewai-flow-3.png) + +**Nota:** O campo `id` é gerado e preservado automaticamente durante toda a execução do flow. Não é necessário gerenciá-lo ou defini-lo manualmente, e ele permanecerá mesmo ao atualizar o estado com novos dados. + +**Pontos-Chave:** + +- **Flexibilidade:** É possível adicionar atributos dinamicamente ao `self.state` sem restrições pré-definidas. +- **Simplicidade:** Ideal para fluxos de trabalho diretos em que a estrutura do estado é mínima ou varia bastante. + +### Gerenciamento de Estado Estruturado + +No gerenciamento de estado estruturado, utilizam-se esquemas pré-definidos para garantir consistência e segurança de tipos em todo o workflow. +Ao usar modelos como o `BaseModel` da Pydantic, os desenvolvedores podem definir a forma exata do estado, melhorando a validação e fornecendo auto-complete nos ambientes de desenvolvimento. + +Cada estado nos flows do CrewAI recebe automaticamente um identificador único (UUID) para ajudar no rastreamento e gerenciamento. Esse ID é gerado e mantido automaticamente pelo sistema de flows. + +```python Code +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + + +class ExampleState(BaseModel): + # Nota: o campo 'id' é adicionado automaticamente a todos os estados + counter: int = 0 + message: str = "" + + +class StructuredExampleFlow(Flow[ExampleState]): + + @start() + def first_method(self): + # Acesse o ID gerado automaticamente, se necessário + print(f"State ID: {self.state.id}") + self.state.message = "Hello from structured flow" + + @listen(first_method) + def second_method(self): + self.state.counter += 1 + self.state.message += " - updated" + + @listen(second_method) + def third_method(self): + self.state.counter += 1 + self.state.message += " - updated again" + + print(f"State after third_method: {self.state}") + + +flow = StructuredExampleFlow() +flow.kickoff() +``` + +![Flow Visual image](/images/crewai-flow-3.png) + +**Pontos-Chave:** + +- **Esquema Definido:** `ExampleState` deixa claro a estrutura do estado, aumentando a legibilidade e a manutenção do código. +- **Segurança de Tipos:** O uso da Pydantic garante que os atributos do estado tenham os tipos certos, reduzindo os erros em tempo de execução. +- **Auto-Completar:** IDEs conseguem oferecer auto-completar e checagem de erros, graças ao modelo definido do estado. + +### Escolhendo entre Estado Não Estruturado e Estruturado + +- **Use Estado Não Estruturado quando:** + - O estado do fluxo é simples ou altamente dinâmico. + - Flexibilidade é mais importante do que uma definição rígida do estado. + - Prototipagem rápida é necessária sem a sobrecarga de definição de esquemas. + +- **Use Estado Estruturado quando:** + - O flow exige uma estrutura de estado bem definida e consistente. + - Segurança de tipos e validação são importantes para a confiabilidade da aplicação. + - É desejado usar recursos da IDE como auto-completar e checagem de tipos para uma melhor experiência de desenvolvimento. + +Ao oferecer as duas opções de gerenciamento de estado, o CrewAI Flows permite que desenvolvedores criem fluxos de IA que sejam ao mesmo tempo flexíveis e robustos, atendendo a uma ampla variedade de requisitos de aplicação. + +## Persistência de Flow + +O decorador @persist permite a persistência automática do estado nos flows do CrewAI, garantindo que você mantenha o estado do flow entre reinicializações ou execuções diferentes do workflow. Esse decorador pode ser aplicado tanto ao nível de classe, quanto ao nível de método, oferecendo flexibilidade sobre como gerenciar a persistência do estado. + +### Persistência no Nível de Classe + +Quando aplicado no nível da classe, o decorador @persist garante a persistência automática de todos os estados dos métodos do flow: + +```python +@persist # Usa SQLiteFlowPersistence por padrão +class MyFlow(Flow[MyState]): + @start() + def initialize_flow(self): + # Este método terá seu estado persistido automaticamente + self.state.counter = 1 + print("Initialized flow. State ID:", self.state.id) + + @listen(initialize_flow) + def next_step(self): + # O estado (incluindo self.state.id) é recarregado automaticamente + self.state.counter += 1 + print("Flow state is persisted. Counter:", self.state.counter) +``` + +### Persistência no Nível de Método + +Para um controle mais granular, você pode aplicar @persist em métodos específicos: + +```python +class AnotherFlow(Flow[dict]): + @persist # Persiste apenas o estado deste método + @start() + def begin(self): + if "runs" not in self.state: + self.state["runs"] = 0 + self.state["runs"] += 1 + print("Method-level persisted runs:", self.state["runs"]) +``` + +### Forking de Estado Persistido + +`@persist` suporta dois modos distintos de hidratação em `kickoff` / `kickoff_async`: + +- `kickoff(inputs={"id": })` — **resume**: carrega o snapshot mais recente do UUID informado e continua escrevendo sob o mesmo `flow_uuid`. O histórico se estende. +- `kickoff(restore_from_state_id=)` — **fork**: carrega o snapshot mais recente do UUID informado, hidrata o estado da nova execução a partir dele, e atribui um novo `state.id` (auto-gerado, ou `inputs["id"]` se fixado). As escritas do `@persist` da nova execução vão para o novo `state.id`; o histórico do flow de origem é preservado. + +```python +from crewai.flow.flow import Flow, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + id: str = "" + counter: int = 0 + +@persist +class CounterFlow(Flow[CounterState]): + @start() + def step(self): + self.state.counter += 1 + print(f"[id={self.state.id}] counter={self.state.counter}") + +# Execução 1: estado novo, counter 0 -> 1, persistido sob flow_1.state.id +flow_1 = CounterFlow() +flow_1.kickoff() + +# Fork: hidrata do snapshot mais recente de flow_1, mas usa um state.id NOVO +flow_2 = CounterFlow() +flow_2.kickoff(restore_from_state_id=flow_1.state.id) +# flow_2.state.counter começa em 1 (hidratado), e step() incrementa para 2. +# flow_2.state.id != flow_1.state.id; o histórico de flow_1 não é alterado. +``` + +Se o `restore_from_state_id` informado não corresponder a nenhum estado persistido, o kickoff retorna silenciosamente ao comportamento padrão — o mesmo comportamento do `inputs["id"]` quando não encontrado. Combinar `restore_from_state_id` com `from_checkpoint` lança um `ValueError`; escolha uma única fonte de hidratação. Fixar `inputs["id"]` durante o fork compartilha uma chave de persistência com outro flow — geralmente você quer apenas `restore_from_state_id`. + +### Como Funciona + +1. **Identificação Única do Estado** + - Cada estado do flow recebe automaticamente um UUID único + - O ID é preservado entre atualizações do estado e chamadas de métodos + - Suporta tanto estados estruturados (Pydantic BaseModel) quanto não estruturados (dicionário) + +2. **Backend SQLite Padrão** + - O SQLiteFlowPersistence é o backend de armazenamento padrão + - Os estados são salvos automaticamente em um banco de dados SQLite local + - O tratamento de erros é robusto, oferecendo mensagens claras caso ocorram falhas nas operações de banco de dados + +3. **Tratamento de Erros** + - Mensagens de erro abrangentes para operações de banco de dados + - Validação automática do estado ao salvar e carregar + - Feedback claro quando houver problemas de persistência + +### Considerações Importantes + +- **Tipos de Estado**: São suportados tanto estados estruturados (Pydantic BaseModel) quanto não estruturados (dicionário) +- **ID Automático**: O campo `id` é adicionado automaticamente se não estiver presente +- **Recuperação de Estado**: Flows que falharem ou forem reiniciados podem recarregar automaticamente seu estado anterior +- **Implementação Personalizada**: Você pode fornecer sua própria implementação de FlowPersistence para necessidades de armazenamento especializadas + +### Vantagens Técnicas + +1. **Controle Preciso Através de Acesso de Baixo Nível** + - Acesso direto às operações de persistência para casos avançados + - Controle detalhado via decoradores de persistência no nível do método + - Inspeção de estado e recursos de depuração embutidos + - Visibilidade total das mudanças e operações de persistência do estado + +2. **Maior Confiabilidade** + - Recuperação automática do estado após falhas no sistema ou reinicializações + - Atualizações de estado baseadas em transações para garantir integridade dos dados + - Mensagens de erro abrangentes e claras + - Validação robusta durante operações de salvar e carregar estado + +3. **Arquitetura Extensível** + - Backend de persistência personalizável através da interface FlowPersistence + - Suporte para soluções de armazenamento especializadas além do SQLite + - Compatibilidade tanto com estados estruturados (Pydantic) quanto não estruturados (dict) + - Integração perfeita com os padrões de flow existentes no CrewAI + +A arquitetura de persistência enfatiza precisão técnica e opções de personalização, permitindo que desenvolvedores mantenham controle total sobre o gerenciamento de estado enquanto se beneficiam dos recursos de confiabilidade integrados. + +## Controle de Flow + +### Lógica Condicional: `or` + +A função `or_` nos flows permite escutar múltiplos métodos e acionar o método ouvinte quando qualquer um dos métodos especificados gerar uma saída. + + + +```python Code +from crewai.flow.flow import Flow, listen, or_, start + +class OrExampleFlow(Flow): + + @start() + def start_method(self): + return "Hello from the start method" + + @listen(start_method) + def second_method(self): + return "Hello from the second method" + + @listen(or_(start_method, second_method)) + def logger(self, result): + print(f"Logger: {result}") + + + +flow = OrExampleFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +```text Output +Logger: Hello from the start method +Logger: Hello from the second method +``` + + +![Flow Visual image](/images/crewai-flow-4.png) + +Ao executar esse Flow, o método `logger` será acionado pela saída tanto do `start_method` quanto do `second_method`. +A função `or_` serve para escutar vários métodos e disparar o método ouvinte quando qualquer um emitir um resultado. + +### Lógica Condicional: `and` + +A função `and_` nos flows permite escutar múltiplos métodos e acionar o método ouvinte apenas quando todos os métodos especificados emitirem uma saída. + + + +```python Code +from crewai.flow.flow import Flow, and_, listen, start + +class AndExampleFlow(Flow): + + @start() + def start_method(self): + self.state["greeting"] = "Hello from the start method" + + @listen(start_method) + def second_method(self): + self.state["joke"] = "What do computers eat? Microchips." + + @listen(and_(start_method, second_method)) + def logger(self): + print("---- Logger ----") + print(self.state) + +flow = AndExampleFlow() +flow.plot() +flow.kickoff() +``` + +```text Output +---- Logger ---- +{'greeting': 'Hello from the start method', 'joke': 'What do computers eat? Microchips.'} +``` + + +![Flow Visual image](/images/crewai-flow-5.png) + +Ao executar esse Flow, o método `logger` só será disparado quando ambos `start_method` e `second_method` emitirem uma saída. +A função `and_` é usada para escutar vários métodos e acionar o método ouvinte apenas quando todas as condições forem atendidas. + +### Router + +O decorador `@router()` nos flows permite definir lógica de roteamento condicional baseada na saída de um método. +Você pode especificar diferentes rotas conforme a saída do método, permitindo controlar o fluxo de execução de forma dinâmica. + + + +```python Code +import random +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + success_flag: bool = False + +class RouterFlow(Flow[ExampleState]): + + @start() + def start_method(self): + print("Starting the structured flow") + random_boolean = random.choice([True, False]) + self.state.success_flag = random_boolean + + @router(start_method) + def second_method(self): + if self.state.success_flag: + return "success" + else: + return "failed" + + @listen("success") + def third_method(self): + print("Third method running") + + @listen("failed") + def fourth_method(self): + print("Fourth method running") + + +flow = RouterFlow() +flow.plot("my_flow_plot") +flow.kickoff() +``` + +```text Output +Starting the structured flow +Third method running +Fourth method running +``` + + +![Flow Visual image](/images/crewai-flow-6.png) + +No exemplo, o `start_method` gera um valor booleano aleatório e armazena no estado. +O `second_method` usa o decorador `@router()` para decidir o roteamento conforme o valor booleano. +Se o valor for `True`, retorna `"success"`, senão retorna `"failed"`. +Os métodos `third_method` e `fourth_method` escutam a saída do `second_method` e executam com base no valor retornado. + +Ao executar esse Flow, a saída será diferente dependendo do valor booleano aleatório gerado pelo `start_method`. + +### Human in the Loop (feedback humano) + + +O decorador `@human_feedback` requer **CrewAI versão 1.8.0 ou superior**. + + +O decorador `@human_feedback` permite fluxos de trabalho human-in-the-loop, pausando a execução do flow para coletar feedback de um humano. Isso é útil para portões de aprovação, revisão de qualidade e pontos de decisão que requerem julgamento humano. + +```python Code +from crewai.flow.flow import Flow, start, listen +from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult + +class ReviewFlow(Flow): + @start() + @human_feedback( + message="Você aprova este conteúdo?", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + def generate_content(self): + return "Conteúdo para revisão..." + + @listen("approved") + def on_approval(self, result: HumanFeedbackResult): + print(f"Aprovado! Feedback: {result.feedback}") + + @listen("rejected") + def on_rejection(self, result: HumanFeedbackResult): + print(f"Rejeitado. Motivo: {result.feedback}") +``` + +Quando `emit` é especificado, o feedback livre do humano é interpretado por um LLM e mapeado para um dos outcomes especificados, que então dispara o decorador `@listen` correspondente. + +Você também pode usar `@human_feedback` sem roteamento para simplesmente coletar feedback: + +```python Code +@start() +@human_feedback(message="Algum comentário sobre esta saída?") +def my_method(self): + return "Saída para revisão" + +@listen(my_method) +def next_step(self, result: HumanFeedbackResult): + # Acesse o feedback via result.feedback + # Acesse a saída original via result.output + pass +``` + +Acesse todo o feedback coletado durante um flow via `self.last_human_feedback` (mais recente) ou `self.human_feedback_history` (todo o feedback em uma lista). + +Para um guia completo sobre feedback humano em flows, incluindo feedback assíncrono/não-bloqueante com providers customizados (Slack, webhooks, etc.), veja [Feedback Humano em Flows](/pt-BR/learn/human-feedback-in-flows). + +## Adicionando Agentes aos Flows + +Os agentes podem ser integrados facilmente aos seus flows, oferecendo uma alternativa leve às crews completas quando você precisar executar tarefas simples e focadas. Veja um exemplo de como utilizar um agente em um flow para realizar uma pesquisa de mercado: + +```python +import asyncio +from typing import Any, Dict, List + +from crewai_tools import SerperDevTool +from pydantic import BaseModel, Field + +from crewai.agent import Agent +from crewai.flow.flow import Flow, listen, start + + +# Define um formato de saída estruturado +class MarketAnalysis(BaseModel): + key_trends: List[str] = Field(description="List of identified market trends") + market_size: str = Field(description="Estimated market size") + competitors: List[str] = Field(description="Major competitors in the space") + + +# Define o estado do flow +class MarketResearchState(BaseModel): + product: str = "" + analysis: MarketAnalysis | None = None + + +# Cria uma classe de flow +class MarketResearchFlow(Flow[MarketResearchState]): + @start() + def initialize_research(self) -> Dict[str, Any]: + print(f"Starting market research for {self.state.product}") + return {"product": self.state.product} + + @listen(initialize_research) + async def analyze_market(self) -> Dict[str, Any]: + # Cria um agente para pesquisa de mercado + analyst = Agent( + role="Market Research Analyst", + goal=f"Analyze the market for {self.state.product}", + backstory="You are an experienced market analyst with expertise in " + "identifying market trends and opportunities.", + tools=[SerperDevTool()], + verbose=True, + ) + + # Define a consulta de pesquisa + query = f""" + Research the market for {self.state.product}. Include: + 1. Key market trends + 2. Market size + 3. Major competitors + + Format your response according to the specified structure. + """ + + # Executa a análise com formato de saída estruturado + result = await analyst.kickoff_async(query, response_format=MarketAnalysis) + if result.pydantic: + print("result", result.pydantic) + else: + print("result", result) + + # Retorna a análise para atualizar o estado + return {"analysis": result.pydantic} + + @listen(analyze_market) + def present_results(self, analysis) -> None: + print("\nMarket Analysis Results") + print("=====================") + + if isinstance(analysis, dict): + # Se recebemos um dict com a chave 'analysis', extrai o objeto de análise real + market_analysis = analysis.get("analysis") + else: + market_analysis = analysis + + if market_analysis and isinstance(market_analysis, MarketAnalysis): + print("\nKey Market Trends:") + for trend in market_analysis.key_trends: + print(f"- {trend}") + + print(f"\nMarket Size: {market_analysis.market_size}") + + print("\nMajor Competitors:") + for competitor in market_analysis.competitors: + print(f"- {competitor}") + else: + print("No structured analysis data available.") + print("Raw analysis:", analysis) + + +# Exemplo de uso +async def run_flow(): + flow = MarketResearchFlow() + flow.plot("MarketResearchFlowPlot") + result = await flow.kickoff_async(inputs={"product": "AI-powered chatbots"}) + return result + + +# Executa o flow +if __name__ == "__main__": + asyncio.run(run_flow()) +``` + +![Flow Visual image](/images/crewai-flow-7.png) + +Esse exemplo demonstra diversos recursos fundamentais do uso de agentes em flows: + +1. **Saída Estruturada**: O uso de modelos Pydantic para definir o formato esperado da saída (`MarketAnalysis`) garante segurança de tipos e dados estruturados em todo o flow. + +2. **Gerenciamento de Estado**: O estado do flow (`MarketResearchState`) mantém o contexto entre as etapas e armazena entradas e saídas. + +3. **Integração de Ferramentas**: Os agentes podem usar ferramentas (como `WebsiteSearchTool`) para potencializar suas habilidades. + +## Adicionando Crews aos Flows + +Criar um flow com múltiplas crews no CrewAI é simples. + +Você pode gerar um novo projeto CrewAI que já inclui toda a estrutura para criar um flow com várias crews executando o seguinte comando: + +```bash +crewai create flow name_of_flow +``` + +Esse comando irá gerar um novo projeto CrewAI com a estrutura de pastas necessária. O projeto gerado inclui uma crew pré-criada chamada `poem_crew`, já funcional. A crew embutida inicial usa a estrutura clássica Python/YAML; novas crews independentes criadas com `crewai create crew` usam a estrutura JSON-first. + +### Estrutura de Pastas + +Após rodar o comando `crewai create flow name_of_flow`, você verá uma estrutura parecida com: + +| Diretório/Arquivo | Descrição | +| :------------------------ | :------------------------------------------------------------------- | +| `name_of_flow/` | Diretório raiz do flow. | +| ├── `crews/` | Contém diretórios para crews específicas. | +| │ └── `poem_crew/` | Diretório da "poem_crew" com configurações e scripts. | +| │ ├── `config/` | Arquivos de configuração da "poem_crew". | +| │ │ ├── `agents.yaml` | YAML que define os agentes da "poem_crew". | +| │ │ └── `tasks.yaml` | YAML que define as tarefas da "poem_crew". | +| │ ├── `poem_crew.py` | Script da funcionalidade da "poem_crew". | +| ├── `tools/` | Ferramentas adicionais usadas no flow. | +| │ └── `custom_tool.py` | Implementação de ferramenta customizada. | +| ├── `main.py` | Script principal do flow. | +| ├── `README.md` | Descrição do projeto e instruções. | +| ├── `pyproject.toml` | Arquivo de configurações e dependências do projeto. | +| └── `.gitignore` | Arquivos e pastas a serem ignorados no controle de versão. | + +### Construindo suas Crews + +Na pasta `crews`, você pode definir múltiplas crews. Cada crew tem sua própria pasta, com arquivos de configuração e o arquivo de definição da crew. Por exemplo, a pasta `poem_crew` contém: + +- `config/agents.yaml`: Define os agentes da crew. +- `config/tasks.yaml`: Define as tarefas da crew. +- `poem_crew.py`: Contém a definição da crew, incluindo agentes, tarefas, etc. + +Você pode copiar, colar e editar a `poem_crew` para criar outras crews clássicas embutidas. + +Para crews embutidas JSON-first, use uma pasta com `crew.jsonc` e `agents/*.jsonc`: + +```text +crews/ +└── research_crew/ + ├── agents/ + │ └── researcher.jsonc + └── crew.jsonc +``` + +Depois carregue a crew em uma etapa do Flow: + +```python +from pathlib import Path +from crewai.project import load_crew + +crew, default_inputs = load_crew( + Path(__file__).parent / "crews" / "research_crew" / "crew.jsonc" +) +result = crew.kickoff(inputs={**default_inputs, "topic": "AI Agents"}) +``` + +### Conectando Crews no `main.py` + +No arquivo `main.py`, você cria seu flow e conecta as crews. É possível definir o fluxo usando a classe `Flow` e os decoradores `@start` e `@listen` para definir a ordem de execução. + +Veja um exemplo de como conectar a `poem_crew` no arquivo `main.py`: + +```python Code +#!/usr/bin/env python +from random import randint + +from pydantic import BaseModel +from crewai.flow.flow import Flow, listen, start +from .crews.poem_crew.poem_crew import PoemCrew + +class PoemState(BaseModel): + sentence_count: int = 1 + poem: str = "" + +class PoemFlow(Flow[PoemState]): + + @start() + def generate_sentence_count(self): + print("Generating sentence count") + self.state.sentence_count = randint(1, 5) + + @listen(generate_sentence_count) + def generate_poem(self): + print("Generating poem") + result = PoemCrew().crew().kickoff(inputs={"sentence_count": self.state.sentence_count}) + + print("Poem generated", result.raw) + self.state.poem = result.raw + + @listen(generate_poem) + def save_poem(self): + print("Saving poem") + with open("poem.txt", "w") as f: + f.write(self.state.poem) + +def kickoff(): + poem_flow = PoemFlow() + poem_flow.kickoff() + + +def plot(): + poem_flow = PoemFlow() + poem_flow.plot("PoemFlowPlot") + +if __name__ == "__main__": + kickoff() + plot() +``` + +Neste exemplo, a classe `PoemFlow` define um fluxo que gera a quantidade de frases, usa a `PoemCrew` para gerar um poema e, depois, salva o poema em um arquivo. O flow inicia com o método `kickoff()`, e o gráfico é gerado pelo método `plot()`. + +![Flow Visual image](/images/crewai-flow-8.png) + +### Executando o Flow + +(Opcional) Antes de rodar o flow, instale as dependências executando: + +```bash +crewai install +``` + +Após instalar as dependências, ative o ambiente virtual com: + +```bash +source .venv/bin/activate +``` + +Com o ambiente ativado, execute o flow usando um dos comandos: + +```bash +crewai run +``` + +ou + +```bash +uv run kickoff +``` + +O flow será executado, e você verá a saída no console. + +## Plotando Flows + +Visualizar seus fluxos de trabalho de IA proporciona insights valiosos sobre a estrutura e os caminhos de execução dos flows. O CrewAI oferece uma ferramenta de visualização poderosa que permite gerar plots interativos dos flows, facilitando o entendimento e a otimização dos workflows de IA. + +### O que são Plots? + +No CrewAI, plots são representações gráficas dos fluxos de trabalho de IA. Eles mostram as tarefas, suas conexões e o fluxo de dados entre elas. Essa visualização ajuda a compreender a sequência de operações, identificar gargalos e garantir que a lógica do workflow está alinhada com o esperado. + +### Como Gerar um Plot + +O CrewAI oferece duas formas práticas de gerar plots dos seus flows: + +#### Opção 1: Usando o método `plot()` + +Se estiver trabalhando diretamente com uma instância do flow, basta chamar o método `plot()` do objeto. Isso criará um arquivo HTML com o plot interativo do seu flow. + +```python Code +# Considerando que você já tem uma instância do flow +flow.plot("my_flow_plot") +``` + +Esse comando gera um arquivo chamado `my_flow_plot.html` no diretório atual. Abra esse arquivo em um navegador para visualizar o plot interativo. + +#### Opção 2: Usando a Linha de Comando + +Em projetos CrewAI estruturados, é possível gerar um plot pela linha de comando. Isso é útil para projetos maiores, onde você deseja visualizar toda a configuração do flow. + +```bash +crewai flow plot +``` + +O comando gera um arquivo HTML com o plot do flow, semelhante ao método `plot()`. Basta abrir o arquivo no navegador para explorar o workflow. + +### Entendendo o Plot + +O plot gerado mostra nós representando as tarefas do seu flow, com setas indicando o fluxo de execução. A visualização é interativa, permitindo zoom, navegação e detalhes ao passar o mouse nos nós. + +Ao visualizar seus flows, você tem clareza do formato do workflow, facilitando debug, otimização e comunicação dos seus processos de IA para outras pessoas. + +### Conclusão + +A plotagem dos flows é um recurso poderoso do CrewAI para aprimorar o design e o gerenciamento de fluxos de IA complexos. Usando o método `plot()` ou a linha de comando, você obtém uma visão visual dos workflows, benefício tanto para desenvolvimento quanto para apresentação. + +## Próximos Passos + +Se você deseja explorar exemplos adicionais de flows, acompanhe alguns exemplos em nosso repositório de exemplos. Aqui estão quatro sugestões específicas de flows, cada uma demonstrando casos de uso distintos para você escolher conforme seu problema: + +1. **Email Auto Responder Flow**: Este exemplo demonstra um loop infinito, onde um job de background roda continuamente automatizando respostas de email. É ideal para tarefas rotineiras sem intervenção manual. [Ver Exemplo](https://github.com/crewAIInc/crewAI-examples/tree/main/email_auto_responder_flow) + +2. **Lead Score Flow**: Destaca como adicionar feedback humano e manipular diferentes ramos condicionais usando router. Um ótimo aprendizado para workflows com decisão dinâmica e supervisão humana. [Ver Exemplo](https://github.com/crewAIInc/crewAI-examples/tree/main/lead-score-flow) + +3. **Write a Book Flow**: Exemplo ideal para encadear múltiplas crews, onde a saída de uma é usada por outra. Uma crew faz um sumário do livro inteiro, outra gera capítulos... Tudo conectado para entregar um livro completo. Perfeito para processos longos e coordenados. [Ver Exemplo](https://github.com/crewAIInc/crewAI-examples/tree/main/write_a_book_with_flows) + +4. **Meeting Assistant Flow**: Demonstra como transmitir um evento para desencadear múltiplas ações posteriores. Exemplo: ao finalizar uma reunião, atualizar um Trello, enviar mensagem no Slack e salvar resultados ao mesmo tempo. Indicado para gerenciamento completo de tarefas e notificações. [Ver Exemplo](https://github.com/crewAIInc/crewAI-examples/tree/main/meeting_assistant_flow) + +Explore esses exemplos para descobrir como aproveitar CrewAI Flows em diferentes contextos – desde automação de tarefas repetitivas até o gerenciamento de processos dinâmicos com decisões e feedback humano. + +Além disso, confira nosso vídeo no YouTube sobre como utilizar flows no CrewAI abaixo! + + + +## Executando Flows + +Existem duas formas de executar um flow: + +### Usando a API do Flow + +Você pode executar um flow programaticamente criando uma instância da sua classe de flow e chamando o método `kickoff()`: + +```python +# Exemplo de execução de flow em português +flow = ExemploFlow() +resultado = flow.kickoff() +``` + +### Usando a CLI + +A partir da versão 0.103.0, é possível executar flows usando o comando `crewai run`: + +```shell +crewai run +``` + +O comando detecta automaticamente se seu projeto é um flow (com base na configuração `type = "flow"` no pyproject.toml) e executa conforme o esperado. Esse é o método recomendado para executar flows pelo terminal. + +O comando legado `crewai flow kickoff` está deprecated. Use `crewai run` para crews e flows. diff --git a/docs/v1.15.13/pt-BR/concepts/knowledge.mdx b/docs/v1.15.13/pt-BR/concepts/knowledge.mdx new file mode 100644 index 0000000000..eabe22fabd --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/knowledge.mdx @@ -0,0 +1,1060 @@ +--- +title: Knowledge +description: O que é knowledge em CrewAI e como usá-lo. +icon: book +mode: "wide" +--- + +## Visão Geral + +Knowledge no CrewAI é um sistema poderoso que permite que agentes de IA acessem e utilizem fontes de informação externas durante suas tarefas. +Pense nisso como dar aos seus agentes uma biblioteca de referência que eles podem consultar enquanto trabalham. + + + Principais benefícios de usar Knowledge: + - Aprimorar agentes com informações específicas do domínio + - Apoiar decisões com dados do mundo real + - Manter contexto entre conversas + - Fundamentar respostas em informações factuais + + +## Exemplos de Início Rápido + + +Para Fontes de Knowledge baseadas em arquivos, certifique-se de colocar seus arquivos em um diretório `knowledge` na raiz do seu projeto. +Além disso, use caminhos relativos do diretório `knowledge` ao criar a fonte. + + +### Exemplo Básico de Knowledge com String + +```python Code +from crewai import Agent, Task, Crew, Process, LLM +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create a knowledge source +content = "Users name is John. He is 30 years old and lives in San Francisco." +string_source = StringKnowledgeSource(content=content) + +# Create an LLM with a temperature of 0 to ensure deterministic outputs +llm = LLM(model="gpt-4o-mini", temperature=0) + +# Create an agent with the knowledge store +agent = Agent( + role="Sobre o Usuário", + goal="Você sabe tudo sobre o usuário.", + backstory="Você é mestre em entender pessoas e suas preferências.", + verbose=True, + allow_delegation=False, + llm=llm, +) + +task = Task( + description="Responda às seguintes perguntas sobre o usuário: {question}", + expected_output="Uma resposta para a pergunta.", + agent=agent, +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True, + process=Process.sequential, + knowledge_sources=[string_source], # Enable knowledge by adding the sources here +) + +result = crew.kickoff(inputs={"question": "What city does John live in and how old is he?"}) +``` + +### Exemplo de Knowledge com Conteúdo Web + + + Você precisa instalar `docling` para o seguinte exemplo funcionar: `uv add docling` + + +```python Code +from crewai import LLM, Agent, Crew, Process, Task +from crewai.knowledge.source.crew_docling_source import CrewDoclingSource + +# Create a knowledge source from web content +content_source = CrewDoclingSource( + file_paths=[ + "https://lilianweng.github.io/posts/2024-11-28-reward-hacking", + "https://lilianweng.github.io/posts/2024-07-07-hallucination", + ], +) + +# Create an LLM with a temperature of 0 to ensure deterministic outputs +llm = LLM(model="gpt-4o-mini", temperature=0) + +# Create an agent with the knowledge store +agent = Agent( + role="Sobre artigos", + goal="Você sabe tudo sobre os artigos.", + backstory="Você é mestre em entender artigos e seus conteúdos.", + verbose=True, + allow_delegation=False, + llm=llm, +) + +task = Task( + description="Responda às seguintes perguntas sobre os artigos: {question}", + expected_output="Uma resposta para a pergunta.", + agent=agent, +) + +crew = Crew( + agents=[agent], + tasks=[task], + verbose=True, + process=Process.sequential, + knowledge_sources=[content_source], +) + +result = crew.kickoff( + inputs={"question": "What is the reward hacking paper about? Be sure to provide sources."} +) +``` + +## Fontes de Knowledge Suportadas + +O CrewAI suporta vários tipos de fontes de knowledge prontas para uso: + + + + - Strings brutas + - Arquivos de texto (.txt) + - Documentos PDF + + + - Arquivos CSV + - Planilhas Excel + - Documentos JSON + + + +### Fonte de Knowledge de Arquivo de Texto +```python +from crewai.knowledge.source.text_file_knowledge_source import TextFileKnowledgeSource + +text_source = TextFileKnowledgeSource( + file_paths=["document.txt", "another.txt"] +) +``` + +### Fonte de Knowledge PDF +```python +from crewai.knowledge.source.pdf_knowledge_source import PDFKnowledgeSource + +pdf_source = PDFKnowledgeSource( + file_paths=["document.pdf", "another.pdf"] +) +``` + +### Fonte de Knowledge CSV +```python +from crewai.knowledge.source.csv_knowledge_source import CSVKnowledgeSource + +csv_source = CSVKnowledgeSource( + file_paths=["data.csv"] +) +``` + +### Fonte de Knowledge Excel +```python +from crewai.knowledge.source.excel_knowledge_source import ExcelKnowledgeSource + +excel_source = ExcelKnowledgeSource( + file_paths=["spreadsheet.xlsx"] +) +``` + +### Fonte de Knowledge JSON +```python +from crewai.knowledge.source.json_knowledge_source import JSONKnowledgeSource + +json_source = JSONKnowledgeSource( + file_paths=["data.json"] +) +``` + + + Certifique-se de criar a pasta ./knowledge. Todos os arquivos de origem (ex: .txt, .pdf, .xlsx, .json) devem ser colocados nesta pasta para gerenciamento centralizado. + + +## Knowledge de Agente vs Crew: Guia Completo + + +**Entendendo os Níveis de Knowledge**: O CrewAI suporta knowledge tanto no nível de agente quanto de crew. Esta seção esclarece exatamente como cada um funciona, quando são inicializados, e aborda equívocos comuns sobre dependências. + + +### Como a Inicialização de Knowledge Realmente Funciona + +Aqui está exatamente o que acontece quando você usa knowledge: + +#### Knowledge no Nível do Agente (Independente) +```python +from crewai import Agent, Task, Crew +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Agent with its own knowledge - NO crew knowledge needed +specialist_knowledge = StringKnowledgeSource( + content="Specialized technical information for this agent only" +) + +specialist_agent = Agent( + role="Especialista Técnico", + goal="Fornecer expertise técnica", + backstory="Especialista em domínios técnicos especializados", + knowledge_sources=[specialist_knowledge] # Conhecimento específico do agente +) + +task = Task( + description="Responda perguntas técnicas", + agent=specialist_agent, + expected_output="Resposta técnica" +) + +# No crew-level knowledge required +crew = Crew( + agents=[specialist_agent], + tasks=[task] +) + +result = crew.kickoff() # Agent knowledge works independently +``` + +#### O Que Acontece Durante `crew.kickoff()` + +Quando você chama `crew.kickoff()`, aqui está a sequência exata: + +```python +# During kickoff +for agent in self.agents: + agent.crew = self # Agent gets reference to crew + agent.set_knowledge(crew_embedder=self.embedder) # Agent knowledge initialized + agent.create_agent_executor() +``` + +#### Independência de Armazenamento + +Cada nível de knowledge usa coleções de armazenamento independentes: + +```python +# Agent knowledge storage +agent_collection_name = agent.role # e.g., "Especialista Técnico" + +# Crew knowledge storage +crew_collection_name = "crew" + +# Both stored in same ChromaDB instance but different collections +# Path: ~/.local/share/CrewAI/{project}/knowledge/ +# ├── crew/ # Crew knowledge collection +# ├── Especialista Técnico/ # Agent knowledge collection +# └── Another Agent Role/ # Another agent's collection +``` + +### Exemplos Completos Funcionais + +#### Exemplo 1: Knowledge Apenas do Agente +```python +from crewai import Agent, Task, Crew +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Agent-specific knowledge +agent_knowledge = StringKnowledgeSource( + content="Agent-specific information that only this agent needs" +) + +agent = Agent( + role="Especialista", + goal="Use specialized knowledge", + backstory="Expert with specific knowledge", + knowledge_sources=[agent_knowledge], + embedder={ # Agent can have its own embedder + "provider": "openai", + "config": {"model": "text-embedding-3-small"} + } +) + +task = Task( + description="Answer using your specialized knowledge", + agent=agent, + expected_output="Answer based on agent knowledge" +) + +# No crew knowledge needed +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() # Works perfectly +``` + +#### Exemplo 2: Knowledge Tanto do Agente Quanto da Crew +```python +# Crew-wide knowledge (shared by all agents) +crew_knowledge = StringKnowledgeSource( + content="Company policies and general information for all agents" +) + +# Agent-specific knowledge +specialist_knowledge = StringKnowledgeSource( + content="Technical specifications only the specialist needs" +) + +specialist = Agent( + role="Especialista Técnico", + goal="Fornecer expertise técnica", + backstory="Especialista em domínios técnicos especializados", + knowledge_sources=[specialist_knowledge] # Conhecimento específico do agente +) + +generalist = Agent( + role="General Assistant", + goal="Provide general assistance", + backstory="General helper" + # No agent-specific knowledge +) + +crew = Crew( + agents=[specialist, generalist], + tasks=[...], + knowledge_sources=[crew_knowledge] # Crew-wide knowledge +) + +# Result: +# - specialist gets: crew_knowledge + specialist_knowledge +# - generalist gets: crew_knowledge only +``` + +#### Exemplo 3: Múltiplos Agentes com Knowledge Diferente +```python +# Different knowledge for different agents +sales_knowledge = StringKnowledgeSource(content="Sales procedures and pricing") +tech_knowledge = StringKnowledgeSource(content="Technical documentation") +support_knowledge = StringKnowledgeSource(content="Support procedures") + +sales_agent = Agent( + role="Sales Representative", + knowledge_sources=[sales_knowledge], + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}} +) + +tech_agent = Agent( + role="Technical Expert", + knowledge_sources=[tech_knowledge], + embedder={"provider": "ollama", "config": {"model": "mxbai-embed-large"}} +) + +support_agent = Agent( + role="Support Specialist", + knowledge_sources=[support_knowledge] + # Will use crew embedder as fallback +) + +crew = Crew( + agents=[sales_agent, tech_agent, support_agent], + tasks=[...], + embedder={ # Fallback embedder for agents without their own + "provider": "google", + "config": {"model": "text-embedding-004"} + } +) + +# Each agent gets only their specific knowledge +# Each can use different embedding providers +``` + + +Diferente da recuperação de um banco de dados vetorial usando uma ferramenta, agentes pré-carregados com knowledge não precisarão de uma persona de recuperação ou tarefa. +Simplesmente adicione as fontes de knowledge relevantes que seu agente ou crew precisa para funcionar. + +As fontes de knowledge podem ser adicionadas no nível do agente ou da crew. +As fontes de knowledge no nível da crew serão usadas por **todos os agentes** na crew. +As fontes de knowledge no nível do agente serão usadas pelo **agente específico** que é pré-carregado com o knowledge. + + +## Configuração de Knowledge + +Você pode configurar a configuração de knowledge para a crew ou agente. + +```python Code +from crewai.knowledge.knowledge_config import KnowledgeConfig + +knowledge_config = KnowledgeConfig(results_limit=10, score_threshold=0.5) + +agent = Agent( + ... + knowledge_config=knowledge_config +) +``` + + + `results_limit`: é o número de documentos relevantes a retornar. Padrão é 3. + `score_threshold`: é a pontuação mínima para um documento ser considerado relevante. Padrão é 0.35. + + +## Parâmetros de Knowledge Suportados + + + Lista de fontes de knowledge que fornecem conteúdo para ser armazenado e consultado. Pode incluir PDF, CSV, Excel, JSON, arquivos de texto ou conteúdo de string. + + + Nome da coleção onde o knowledge será armazenado. Usado para identificar diferentes conjuntos de knowledge. Padrão é "knowledge" se não fornecido. + + +Configuração de armazenamento personalizada para gerenciar como o knowledge é armazenado e recuperado. Se não fornecido, um armazenamento padrão será criado. + + +## Transparência do Armazenamento de Knowledge + + +**Entendendo o Armazenamento de Knowledge**: O CrewAI armazena automaticamente as fontes de knowledge em diretórios específicos da plataforma usando ChromaDB para armazenamento vetorial. Entender essas localizações e padrões ajuda com implantações de produção, depuração e gerenciamento de armazenamento. + + +### Onde o CrewAI Armazena Arquivos de Knowledge + +Por padrão, o CrewAI usa o mesmo sistema de armazenamento que a memória, armazenando knowledge em diretórios específicos da plataforma: + +#### Localizações de Armazenamento Padrão por Plataforma + +**macOS:** +``` +~/Library/Application Support/CrewAI/{project_name}/ +└── knowledge/ # Knowledge ChromaDB files + ├── chroma.sqlite3 # ChromaDB metadata + ├── {collection_id}/ # Vector embeddings + └── knowledge_{collection}/ # Named collections +``` + +**Linux:** +``` +~/.local/share/CrewAI/{project_name}/ +└── knowledge/ + ├── chroma.sqlite3 + ├── {collection_id}/ + └── knowledge_{collection}/ +``` + +**Windows:** +``` +C:\Users\{username}\AppData\Local\CrewAI\{project_name}\ +└── knowledge\ + ├── chroma.sqlite3 + ├── {collection_id}\ + └── knowledge_{collection}\ +``` + +### Encontrando Sua Localização de Armazenamento de Knowledge + +Para ver exatamente onde o CrewAI está armazenando seus arquivos de knowledge: + +```python +from crewai.utilities.paths import db_storage_path +import os + +# Get the knowledge storage path +knowledge_path = os.path.join(db_storage_path(), "knowledge") +print(f"Knowledge storage location: {knowledge_path}") + +# List knowledge collections and files +if os.path.exists(knowledge_path): + print("\nKnowledge storage contents:") + for item in os.listdir(knowledge_path): + item_path = os.path.join(knowledge_path, item) + if os.path.isdir(item_path): + print(f"📁 Collection: {item}/") + # Show collection contents + try: + for subitem in os.listdir(item_path): + print(f" └── {subitem}") + except PermissionError: + print(f" └── (permission denied)") + else: + print(f"📄 {item}") +else: + print("No knowledge storage found yet.") +``` + +### Controlando Localizações de Armazenamento de Knowledge + +#### Opção 1: Variável de Ambiente (Recomendado) +```python +import os +from crewai import Crew + +# Set custom storage location for all CrewAI data +os.environ["CREWAI_STORAGE_DIR"] = "./my_project_storage" + +# All knowledge will now be stored in ./my_project_storage/knowledge/ +crew = Crew( + agents=[...], + tasks=[...], + knowledge_sources=[...] +) +``` + +#### Opção 2: Armazenamento de Knowledge Personalizado +```python +from crewai.knowledge.storage.knowledge_storage import KnowledgeStorage +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create custom storage with specific embedder +custom_storage = KnowledgeStorage( + embedder={ + "provider": "ollama", + "config": {"model": "mxbai-embed-large"} + }, + collection_name="my_custom_knowledge" +) + +# Use with knowledge sources +knowledge_source = StringKnowledgeSource( + content="Your knowledge content here" +) +knowledge_source.storage = custom_storage +``` + +#### Opção 3: Armazenamento de Knowledge Específico do Projeto +```python +import os +from pathlib import Path + +# Store knowledge in project directory +project_root = Path(__file__).parent +knowledge_dir = project_root / "knowledge_storage" + +os.environ["CREWAI_STORAGE_DIR"] = str(knowledge_dir) + +# Now all knowledge will be stored in your project directory +``` + +### Comportamento Padrão do Provedor de Embedding + + +**Provedor de Embedding Padrão**: O CrewAI usa por padrão embeddings da OpenAI (`text-embedding-3-small`) para armazenamento de knowledge, mesmo quando usa diferentes provedores de LLM. Você pode facilmente personalizar isso para corresponder à sua configuração. + + +#### Entendendo o Comportamento Padrão +```python +from crewai import Agent, Crew, LLM +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# When using Claude as your LLM... +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + llm=LLM(provider="anthropic", model="claude-3-sonnet") # Using Claude +) + +# CrewAI will still use OpenAI embeddings by default for knowledge +# This ensures consistency but may not match your LLM provider preference +knowledge_source = StringKnowledgeSource(content="Research data...") + +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source] + # Default: Uses OpenAI embeddings even with Claude LLM +) +``` + +#### Personalizando Provedores de Embedding de Knowledge +```python +# Option 1: Use Voyage AI (recommended by Anthropic for Claude users) +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source], + embedder={ + "provider": "voyageai", # Recommended for Claude users + "config": { + "api_key": "your-voyage-api-key", + "model": "voyage-3" # or "voyage-3-large" for best quality + } + } +) + +# Option 2: Use local embeddings (no external API calls) +crew = Crew( + agents=[agent], + tasks=[...], + knowledge_sources=[knowledge_source], + embedder={ + "provider": "ollama", + "config": { + "model": "mxbai-embed-large", + "url": "http://localhost:11434/api/embeddings" + } + } +) + +# Option 3: Agent-level embedding customization +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + knowledge_sources=[knowledge_source], + embedder={ + "provider": "google", + "config": { + "model": "models/text-embedding-004", + "api_key": "your-google-key" + } + } +) +``` + +#### Configurando Embeddings do Azure OpenAI + +Ao usar embeddings do Azure OpenAI: +1. Certifique-se de implantar o modelo de embedding na plataforma Azure primeiro +2. Então você precisa usar a seguinte configuração: + +```python +agent = Agent( + role="Researcher", + goal="Research topics", + backstory="Expert researcher", + knowledge_sources=[knowledge_source], + embedder={ + "provider": "azure", + "config": { + "api_key": "your-azure-api-key", + "model": "text-embedding-ada-002", # change to the model you are using and is deployed in Azure + "api_base": "https://your-azure-endpoint.openai.azure.com/", + "api_version": "2024-02-01" + } + } +) +``` + +## Recursos Avançados + +### Reescrita de Consulta + +O CrewAI implementa um mecanismo inteligente de reescrita de consulta para otimizar a recuperação de knowledge. Quando um agente precisa pesquisar nas fontes de knowledge, o prompt da tarefa bruto é automaticamente transformado em uma consulta de pesquisa mais eficaz. + +#### Como a Reescrita de Consulta Funciona + +1. Quando um agente executa uma tarefa com fontes de knowledge disponíveis, o método `_get_knowledge_search_query` é acionado +2. O LLM do agente é usado para transformar o prompt original da tarefa em uma consulta de pesquisa otimizada +3. Esta consulta otimizada é então usada para recuperar informações relevantes das fontes de knowledge + +#### Benefícios da Reescrita de Consulta + + + + Ao focar em conceitos-chave e remover conteúdo irrelevante, a reescrita de consulta ajuda a recuperar informações mais relevantes. + + + As consultas reescritas são projetadas para ser mais específicas e conscientes do contexto para recuperação de banco de dados vetorial. + + + +#### Exemplo + +```python +# Original task prompt +task_prompt = "Answer the following questions about the user's favorite movies: What movie did John watch last week? Format your answer in JSON." + +# Behind the scenes, this might be rewritten as: +rewritten_query = "What movies did John watch last week?" +``` + +A consulta reescrita é mais focada na necessidade de informação principal e remove instruções irrelevantes sobre formatação de saída. + + + Este mecanismo é totalmente automático e não requer configuração dos usuários. O LLM do agente é usado para realizar a reescrita da consulta, então usar um LLM mais capaz pode melhorar a qualidade das consultas reescritas. + + +### Eventos de Knowledge + +O CrewAI emite eventos durante o processo de recuperação de knowledge que você pode escutar usando o sistema de eventos. Esses eventos permitem que você monitore, depure e analise como o knowledge está sendo recuperado e usado pelos seus agentes. + +#### Eventos de Knowledge Disponíveis + +- **KnowledgeRetrievalStartedEvent**: Emitido quando um agente começa a recuperar knowledge das fontes +- **KnowledgeRetrievalCompletedEvent**: Emitido quando a recuperação de knowledge é concluída, incluindo a consulta usada e o conteúdo recuperado +- **KnowledgeQueryStartedEvent**: Emitido quando uma consulta às fontes de knowledge começa +- **KnowledgeQueryCompletedEvent**: Emitido quando uma consulta é concluída com sucesso +- **KnowledgeQueryFailedEvent**: Emitido quando uma consulta às fontes de knowledge falha +- **KnowledgeSearchQueryFailedEvent**: Emitido quando uma consulta de pesquisa falha + +#### Exemplo: Monitorando Recuperação de Knowledge + +```python +from crewai.events import ( + KnowledgeRetrievalStartedEvent, + KnowledgeRetrievalCompletedEvent, + BaseEventListener, +) + +class KnowledgeMonitorListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(KnowledgeRetrievalStartedEvent) + def on_knowledge_retrieval_started(source, event): + print(f"Agent '{event.agent.role}' started retrieving knowledge") + + @crewai_event_bus.on(KnowledgeRetrievalCompletedEvent) + def on_knowledge_retrieval_completed(source, event): + print(f"Agent '{event.agent.role}' completed knowledge retrieval") + print(f"Query: {event.query}") + print(f"Retrieved {len(event.retrieved_knowledge)} knowledge chunks") + +# Create an instance of your listener +knowledge_monitor = KnowledgeMonitorListener() +``` + +Para mais informações sobre como usar eventos, consulte a documentação [Event Listeners](/pt-BR/concepts/event-listener). + +### Fontes de Knowledge Personalizadas + +O CrewAI permite que você crie fontes de knowledge personalizadas para qualquer tipo de dados estendendo a classe `BaseKnowledgeSource`. Vamos criar um exemplo prático que busca e processa artigos de notícias espaciais. + +#### Exemplo de Fonte de Knowledge de Notícias Espaciais + + + +```python Code +from crewai import Agent, Task, Crew, Process, LLM +from crewai.knowledge.source.base_knowledge_source import BaseKnowledgeSource +import requests +from datetime import datetime +from typing import Dict, Any +from pydantic import BaseModel, Field + +class SpaceNewsKnowledgeSource(BaseKnowledgeSource): + """Knowledge source that fetches data from Space News API.""" + + api_endpoint: str = Field(description="API endpoint URL") + limit: int = Field(default=10, description="Number of articles to fetch") + + def load_content(self) -> Dict[Any, str]: + """Fetch and format space news articles.""" + try: + response = requests.get( + f"{self.api_endpoint}?limit={self.limit}" + ) + response.raise_for_status() + + data = response.json() + articles = data.get('results', []) + + formatted_data = self.validate_content(articles) + return {self.api_endpoint: formatted_data} + except Exception as e: + raise ValueError(f"Failed to fetch space news: {str(e)}") + + def validate_content(self, articles: list) -> str: + """Format articles into readable text.""" + formatted = "Space News Articles:\n\n" + for article in articles: + formatted += f""" + Title: {article['title']} + Published: {article['published_at']} + Summary: {article['summary']} + News Site: {article['news_site']} + URL: {article['url']} + -------------------""" + return formatted + + def add(self) -> None: + """Process and store the articles.""" + content = self.load_content() + for _, text in content.items(): + chunks = self._chunk_text(text) + self.chunks.extend(chunks) + + self._save_documents() + +# Create knowledge source +recent_news = SpaceNewsKnowledgeSource( + api_endpoint="https://api.spaceflightnewsapi.net/v4/articles", + limit=10, +) + +# Create specialized agent +space_analyst = Agent( + role="Space News Analyst", + goal="Answer questions about space news accurately and comprehensively", + backstory="""You are a space industry analyst with expertise in space exploration, + satellite technology, and space industry trends. You excel at answering questions + about space news and providing detailed, accurate information.""", + knowledge_sources=[recent_news], + llm=LLM(model="gpt-4", temperature=0.0) +) + +# Create task that handles user questions +analysis_task = Task( + description="Answer this question about space news: {user_question}", + expected_output="A detailed answer based on the recent space news articles", + agent=space_analyst +) + +# Create and run the crew +crew = Crew( + agents=[space_analyst], + tasks=[analysis_task], + verbose=True, + process=Process.sequential +) + +# Example usage +result = crew.kickoff( + inputs={"user_question": "What are the latest developments in space exploration?"} +) +``` + +```output Output +# Agent: Space News Analyst +## Task: Answer this question about space news: What are the latest developments in space exploration? + + +# Agent: Space News Analyst +## Final Answer: +The latest developments in space exploration, based on recent space news articles, include the following: + +1. SpaceX has received the final regulatory approvals to proceed with the second integrated Starship/Super Heavy launch, scheduled for as soon as the morning of Nov. 17, 2023. This is a significant step in SpaceX's ambitious plans for space exploration and colonization. [Source: SpaceNews](https://spacenews.com/starship-cleared-for-nov-17-launch/) + +2. SpaceX has also informed the US Federal Communications Commission (FCC) that it plans to begin launching its first next-generation Starlink Gen2 satellites. This represents a major upgrade to the Starlink satellite internet service, which aims to provide high-speed internet access worldwide. [Source: Teslarati](https://www.teslarati.com/spacex-first-starlink-gen2-satellite-launch-2022/) + +3. AI startup Synthetaic has raised $15 million in Series B funding. The company uses artificial intelligence to analyze data from space and air sensors, which could have significant applications in space exploration and satellite technology. [Source: SpaceNews](https://spacenews.com/ai-startup-synthetaic-raises-15-million-in-series-b-funding/) + +4. The Space Force has formally established a unit within the U.S. Indo-Pacific Command, marking a permanent presence in the Indo-Pacific region. This could have significant implications for space security and geopolitics. [Source: SpaceNews](https://spacenews.com/space-force-establishes-permanent-presence-in-indo-pacific-region/) + +5. Slingshot Aerospace, a space tracking and data analytics company, is expanding its network of ground-based optical telescopes to increase coverage of low Earth orbit. This could improve our ability to track and analyze objects in low Earth orbit, including satellites and space debris. [Source: SpaceNews](https://spacenews.com/slingshots-space-tracking-network-to-extend-coverage-of-low-earth-orbit/) + +6. The National Natural Science Foundation of China has outlined a five-year project for researchers to study the assembly of ultra-large spacecraft. This could lead to significant advancements in spacecraft technology and space exploration capabilities. [Source: SpaceNews](https://spacenews.com/china-researching-challenges-of-kilometer-scale-ultra-large-spacecraft/) + +7. The Center for AEroSpace Autonomy Research (CAESAR) at Stanford University is focusing on spacecraft autonomy. The center held a kickoff event on May 22, 2024, to highlight the industry, academia, and government collaboration it seeks to foster. This could lead to significant advancements in autonomous spacecraft technology. [Source: SpaceNews](https://spacenews.com/stanford-center-focuses-on-spacecraft-autonomy/) +``` + + + +## Depuração e Solução de Problemas + +### Depurando Problemas de Knowledge + +#### Verificar Inicialização de Knowledge do Agente +```python +from crewai import Agent, Crew, Task +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +knowledge_source = StringKnowledgeSource(content="Test knowledge") + +agent = Agent( + role="Test Agent", + goal="Test knowledge", + backstory="Testing", + knowledge_sources=[knowledge_source] +) + +crew = Crew(agents=[agent], tasks=[Task(...)]) + +# Before kickoff - knowledge not initialized +print(f"Before kickoff - Agent knowledge: {getattr(agent, 'knowledge', None)}") + +crew.kickoff() + +# After kickoff - knowledge initialized +print(f"After kickoff - Agent knowledge: {agent.knowledge}") +print(f"Agent knowledge collection: {agent.knowledge.storage.collection_name}") +print(f"Number of sources: {len(agent.knowledge.sources)}") +``` + +#### Verificar Localizações de Armazenamento de Knowledge +```python +import os +from crewai.utilities.paths import db_storage_path + +# Check storage structure +storage_path = db_storage_path() +knowledge_path = os.path.join(storage_path, "knowledge") + +if os.path.exists(knowledge_path): + print("Knowledge collections found:") + for collection in os.listdir(knowledge_path): + collection_path = os.path.join(knowledge_path, collection) + if os.path.isdir(collection_path): + print(f" - {collection}/") + # Show collection contents + for item in os.listdir(collection_path): + print(f" └── {item}") +``` + +#### Testar Recuperação de Knowledge +```python +# Test agent knowledge retrieval +if hasattr(agent, 'knowledge') and agent.knowledge: + test_query = ["test query"] + results = agent.knowledge.query(test_query) + print(f"Agent knowledge results: {len(results)} documents found") + + # Test crew knowledge retrieval (if exists) + if hasattr(crew, 'knowledge') and crew.knowledge: + crew_results = crew.query_knowledge(test_query) + print(f"Crew knowledge results: {len(crew_results)} documents found") +``` + +#### Inspecionar Coleções de Knowledge +```python +import chromadb +from crewai.utilities.paths import db_storage_path +import os + +# Connect to CrewAI's knowledge ChromaDB +knowledge_path = os.path.join(db_storage_path(), "knowledge") + +if os.path.exists(knowledge_path): + client = chromadb.PersistentClient(path=knowledge_path) + collections = client.list_collections() + + print("Knowledge Collections:") + for collection in collections: + print(f" - {collection.name}: {collection.count()} documents") + + # Sample a few documents to verify content + if collection.count() > 0: + sample = collection.peek(limit=2) + print(f" Sample content: {sample['documents'][0][:100]}...") +else: + print("No knowledge storage found") +``` + +#### Verificar Processamento de Knowledge +```python +from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + +# Create a test knowledge source +test_source = StringKnowledgeSource( + content="Test knowledge content for debugging", + chunk_size=100, # Small chunks for testing + chunk_overlap=20 +) + +# Check chunking behavior +print(f"Original content length: {len(test_source.content)}") +print(f"Chunk size: {test_source.chunk_size}") +print(f"Chunk overlap: {test_source.chunk_overlap}") + +# Process and inspect chunks +test_source.add() +print(f"Number of chunks created: {len(test_source.chunks)}") +for i, chunk in enumerate(test_source.chunks[:3]): # Show first 3 chunks + print(f"Chunk {i+1}: {chunk[:50]}...") +``` + +### Problemas Comuns de Armazenamento de Knowledge + +**Erros "Arquivo não encontrado":** +```python +# Ensure files are in the correct location +from crewai.utilities.constants import KNOWLEDGE_DIRECTORY +import os + +knowledge_dir = KNOWLEDGE_DIRECTORY # Usually "knowledge" +file_path = os.path.join(knowledge_dir, "your_file.pdf") + +if not os.path.exists(file_path): + print(f"File not found: {file_path}") + print(f"Current working directory: {os.getcwd()}") + print(f"Expected knowledge directory: {os.path.abspath(knowledge_dir)}") +``` + +**Erros "Incompatibilidade de dimensão de embedding":** +```python +# This happens when switching embedding providers +# Reset knowledge storage to clear old embeddings +crew.reset_memories(command_type='knowledge') + +# Or use consistent embedding providers +crew = Crew( + agents=[...], + tasks=[...], + knowledge_sources=[...], + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}} +) +``` + +**Erros "ChromaDB permissão negada":** +```bash +# Fix storage permissions +chmod -R 755 ~/.local/share/CrewAI/ +``` + +**Knowledge não persistindo entre execuções:** +```python +# Verify storage location consistency +import os +from crewai.utilities.paths import db_storage_path + +print("CREWAI_STORAGE_DIR:", os.getenv("CREWAI_STORAGE_DIR")) +print("Computed storage path:", db_storage_path()) +print("Knowledge path:", os.path.join(db_storage_path(), "knowledge")) +``` + +### Comandos de Reset de Knowledge + +```python +# Reset only agent-specific knowledge +crew.reset_memories(command_type='agent_knowledge') + +# Reset both crew and agent knowledge +crew.reset_memories(command_type='knowledge') + +# CLI commands +# crewai reset-memories --agent-knowledge # Agent knowledge only +# crewai reset-memories --knowledge # All knowledge +``` + +### Limpando Knowledge + +Se você precisar limpar o knowledge armazenado no CrewAI, você pode usar o comando `crewai reset-memories` com a opção `--knowledge`. + +```bash Command +crewai reset-memories --knowledge +``` + +Isso é útil quando você atualizou suas fontes de knowledge e quer garantir que os agentes estejam usando as informações mais recentes. + +## Melhores Práticas + + + + - Mantenha tamanhos de chunk apropriados para seu tipo de conteúdo + - Considere sobreposição de conteúdo para preservação de contexto + - Organize informações relacionadas em fontes de knowledge separadas + + + + - Ajuste tamanhos de chunk baseado na complexidade do conteúdo + - Configure modelos de embedding apropriados + - Considere usar provedores de embedding locais para processamento mais rápido + + + + - Com a estrutura de arquivo típica fornecida pelo CrewAI, as fontes de knowledge são incorporadas toda vez que o kickoff é acionado. + - Se as fontes de knowledge são grandes, isso leva à ineficiência e latência aumentada, pois os mesmos dados são incorporados cada vez. + - Para resolver isso, inicialize diretamente o parâmetro knowledge em vez do parâmetro knowledge_sources. + - Link para a issue para ter a ideia completa [Github Issue](https://github.com/crewAIInc/crewAI/issues/2755) + + + + - Use knowledge no nível do agente para informações específicas do papel + - Use knowledge no nível da crew para informações compartilhadas que todos os agentes precisam + - Configure embedders no nível do agente se você precisar de estratégias de embedding diferentes + - Use nomenclatura consistente de coleção mantendo papéis de agente descritivos + - Teste a inicialização de knowledge verificando agent.knowledge após o kickoff + - Monitore localizações de armazenamento para entender onde o knowledge está armazenado + - Reset knowledge apropriadamente usando os tipos de comando corretos + + + + - Configure `CREWAI_STORAGE_DIR` para uma localização conhecida em produção + - Escolha provedores de embedding explícitos para corresponder à sua configuração de LLM e evitar conflitos de chave de API + - Monitore o tamanho do armazenamento de knowledge conforme ele cresce com adições de documentos + - Organize fontes de knowledge por domínio ou propósito usando nomes de coleção + - Inclua diretórios de knowledge em suas estratégias de backup e implantação + - Configure permissões de arquivo apropriadas para arquivos de knowledge e diretórios de armazenamento + - Use variáveis de ambiente para chaves de API e configuração sensível + + diff --git a/docs/v1.15.13/pt-BR/concepts/llms.mdx b/docs/v1.15.13/pt-BR/concepts/llms.mdx new file mode 100644 index 0000000000..c4cf18ecf5 --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/llms.mdx @@ -0,0 +1,932 @@ +--- +title: 'LLMs' +description: 'Um guia abrangente para configurar e usar Modelos de Linguagem de Grande Escala (LLMs) em seus projetos CrewAI' +icon: 'microchip-ai' +mode: "wide" +--- + +## Visão Geral + +O CrewAI integra-se com múltiplos provedores de LLM através do LiteLLM, oferecendo flexibilidade para você escolher o modelo certo para o seu caso de uso específico. Este guia irá ajudá-lo a entender como configurar e usar diferentes provedores de LLM em seus projetos CrewAI. + +## O que são LLMs? + +Modelos de Linguagem de Grande Escala (LLMs) são a inteligência central por trás dos agentes CrewAI. Eles permitem que os agentes compreendam o contexto, tomem decisões e gerem respostas semelhantes às humanas. Veja o que você precisa saber: + + + + Modelos de Linguagem de Grande Escala são sistemas de IA treinados em grandes volumes de dados textuais. Eles potencializam a inteligência dos agentes CrewAI, permitindo compreender e gerar textos de voz humana. + + + A janela de contexto determina quanto texto um LLM pode processar de uma só vez. Janelas maiores (por exemplo, 128K tokens) permitem mais contexto, porém podem ser mais caras e lentas. + + + A temperatura é um controle de amostragem compatível com alguns modelos. Valores mais baixos geralmente tornam a amostragem mais focada, enquanto valores mais altos aumentam a variabilidade. Alguns modelos de raciocínio mais recentes ignoram, desaconselham ou rejeitam esse parâmetro; consulte a documentação do modelo escolhido antes de defini-lo. + + + Cada provedor de LLM (ex.: OpenAI, Anthropic, Google) oferece modelos diferentes, com capacidades, preços e recursos variados. Escolha conforme suas necessidades de precisão, velocidade e custo. + + + +## Configurando seu LLM + +Existem diferentes locais no código do CrewAI onde você pode especificar o modelo a ser utilizado. Após definir o modelo usado, será necessário fornecer a configuração (como uma chave de API) para cada provedor de modelo. Veja a seção de [exemplos de configuração de provedores](#provider-configuration-examples) para seu provedor. + + + + A maneira mais simples de começar. Defina o modelo diretamente em seu ambiente, usando um arquivo `.env` ou no código do seu aplicativo. Se você utilizou `crewai create` para iniciar seu projeto, já estará configurado. + + ```bash .env + MODEL=provider/model-id # e.g. openai/gpt-5.6-terra + + # Lembre-se de definir suas chaves de API aqui também. Veja a seção + # do Provedor abaixo. + ``` + + + Nunca envie chaves de API para controle de versão. Use arquivos de ambiente (.env) ou o gerenciamento de segredos do seu sistema. + + + + Crie um arquivo YAML para definir as configurações dos seus agentes. Este método é ótimo para controle de versão e colaboração em equipe: + + ```yaml agents.yaml {6} + researcher: + role: Research Specialist + goal: Conduct comprehensive research and analysis + backstory: A dedicated research professional with years of experience + verbose: true + llm: provider/model-id # e.g. anthropic/claude-sonnet-4-6 + # (veja exemplos de configuração de provedores abaixo para mais) + ``` + + + A configuração YAML permite: + - Controlar versões das configurações dos agentes + - Trocar facilmente entre diferentes modelos + - Compartilhar configurações entre membros da equipe + - Documentar escolhas de modelos e seus propósitos + + + + Para máxima flexibilidade, configure os LLMs diretamente no seu código Python: + + ```python {4,8} + from crewai import LLM + + # Configuração básica + llm = LLM(model="provider/model-id") # e.g. gemini/gemini-3.6-flash + + # Configuração avançada com parâmetros detalhados + llm = LLM( + model="provider/model-id", + timeout=120, + max_tokens=4000, + response_format={"type": "json"}, # Para saídas estruturadas + ) + ``` + + + Explicações dos parâmetros: + - `timeout`: Tempo máximo de espera pela resposta + - `max_tokens`: Limita o comprimento da resposta + - `response_format`: Especifica formato de saída + + Controles de amostragem como `temperature` e `top_p`, parâmetros de penalidade, nomes de limites de tokens e controles de raciocínio são específicos de cada modelo. Adicione-os somente quando o provedor e o modelo escolhidos oferecerem suporte. Consulte os exemplos de provedores abaixo e a documentação do modelo do provedor. + + + + + + O CrewAI oferece integrações nativas via SDK para OpenAI, Anthropic, Google (Gemini API), Azure, AWS Bedrock e Snowflake Cortex — sem necessidade de instalação extra além dos extras específicos do provedor (ex.: `uv add "crewai[openai]"`). + + Todos os outros provedores são alimentados pelo **LiteLLM**. Se você planeja usar algum deles, adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + +## Exemplos de Configuração de Provedores + +O CrewAI suporta uma grande variedade de provedores de LLM, cada um com recursos, métodos de autenticação e capacidades de modelo únicos. +Nesta seção, você encontrará exemplos detalhados que ajudam a selecionar, configurar e otimizar o LLM que melhor atende às necessidades do seu projeto. + + + A disponibilidade dos modelos muda com frequência e pode variar por conta, região e plataforma de nuvem. Os exemplos abaixo usam modelos atuais no momento da redação, mas não são listas completas de suporte. Antes de implantar, confirme o ID e o estado do ciclo de vida do modelo no catálogo vinculado do provedor. + + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + + ```toml Code + # Obrigatório + OPENAI_API_KEY=sk-... + + # Opcional + OPENAI_API_BASE= + OPENAI_ORGANIZATION= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + from crewai import LLM + + llm = LLM( + model="openai/gpt-5.6-terra", + reasoning_effort="medium", + max_completion_tokens=4000 + ) + ``` + + A OpenAI adiciona modelos e desativa snapshots antigos regularmente. Consulte o [catálogo de modelos da OpenAI](https://developers.openai.com/api/docs/models) para obter IDs atuais, janelas de contexto, compatibilidade com endpoints e informações de ciclo de vida. + + **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) + + + 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). + + + + + A API Llama da Meta fornece acesso à família de modelos de linguagem de grande escala da Meta. + A API está disponível através da [Meta Llama API](https://llama.developer.meta.com?utm_source=partner-crewai&utm_medium=website). + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + + ```toml Code + # Configuração chave da API Meta Llama + LLAMA_API_KEY=LLM|your_api_key_here + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + from crewai import LLM + + # Inicializar Meta Llama LLM + llm = LLM( + model="meta_llama/Llama-4-Scout-17B-16E-Instruct-FP8", + temperature=0.8, + stop=["FIM"], + seed=42 + ) + ``` + + Consulte a [visão geral dos modelos Meta Llama](https://ai.meta.com/llama/get-started/) para conhecer as famílias de modelos, modalidades e orientações de contexto atuais. + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + O CrewAI oferece integração nativa com a API REST do Snowflake Cortex pelo endpoint Chat Completions compatível com OpenAI. Isso evita fallback para LiteLLM em modelos `snowflake/...`. Atualmente, o Snowflake Cortex no CrewAI oferece suporte apenas a Chat Completions, então use o modo `api` padrão e não defina `api="responses"`. + + ```toml Code + # Obrigatório + SNOWFLAKE_PAT= + SNOWFLAKE_ACCOUNT_URL=https://.snowflakecomputing.com + + # Configuração alternativa da conta + SNOWFLAKE_ACCOUNT= + ``` + + **Uso básico:** + ```python Code + from crewai import LLM + + llm = LLM( + model="snowflake/openai-gpt-4.1", + temperature=0.7, + max_completion_tokens=1024, + ) + ``` + + **Modelos Claude no Cortex:** + ```python Code + from crewai import LLM + + llm = LLM( + model="snowflake/claude-sonnet-4-5", + max_completion_tokens=1024, + stream=True, + ) + ``` + + **Variáveis de ambiente suportadas:** + - `SNOWFLAKE_PAT`, `SNOWFLAKE_TOKEN` ou `SNOWFLAKE_JWT`: token usado como credencial Bearer + - `SNOWFLAKE_ACCOUNT_URL`: URL completa da conta Snowflake + - `SNOWFLAKE_ACCOUNT`, `SNOWFLAKE_ACCOUNT_ID` ou `SNOWFLAKE_ACCOUNT_IDENTIFIER`: identificador da conta usado para montar a URL + + As requisições REST do Snowflake usam a role padrão do usuário. Garanta que essa role tenha `SNOWFLAKE.CORTEX_USER` ou `SNOWFLAKE.CORTEX_REST_API_USER`. Parâmetros de banco de dados, schema, warehouse e role explícita não são exigidos pelo endpoint Cortex REST Chat Completions. + + **Recursos:** + - Seleção nativa com `model="snowflake/"` + - Chat Completions com e sem streaming apenas; `api="responses"` não é compatível + - Rastreamento de uso de tokens + - Chamadas de função para modelos OpenAI e Claude hospedados no Snowflake + - Remoção automática de prefill final de assistant inválido para modelos Claude no Snowflake + + + + ```toml Code + # Obrigatório + ANTHROPIC_API_KEY=sk-ant-... + + # Opcional + ANTHROPIC_API_BASE= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="anthropic/claude-sonnet-4-6", + max_tokens=4096 + ) + ``` + + **Uso de tokens e prompt caching:** + + A Anthropic reporta a entrada faturada em contadores separados — `input_tokens` (não em cache), `cache_read_input_tokens` e `cache_creation_input_tokens`. O CrewAI incorpora os três em `prompt_tokens` (e no `input_tokens` nativo nas respostas do provedor) para que `total_tokens` reflita o uso faturado completo em workloads em cache. + + `cached_prompt_tokens` registra a porção de leitura de cache apenas como breakdown; ela já está incluída em `prompt_tokens` e não deve ser somada novamente a `total_tokens`. `cache_creation_tokens` registra escritas de cache da mesma forma. + + ```python Code + usage = llm.get_token_usage_summary() + # total_tokens == prompt_tokens + completion_tokens + # prompt_tokens includes cache read + cache write for Anthropic + ``` + + Consulte a seção **UsageMetrics field semantics** na documentação do + conceito Flows para o contrato neutro em relação ao provedor usado por + `crew.usage_metrics` e `flow.usage_metrics`. + + Consulte a [visão geral dos modelos](https://platform.claude.com/docs/en/about-claude/models/overview) da Anthropic para obter IDs e capacidades atuais e revise a [tabela de descontinuação](https://platform.claude.com/docs/en/about-claude/model-deprecations) antes de fixar um modelo em produção. + + + + 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 + # Para API Gemini (uma das seguintes) + GOOGLE_API_KEY= + GEMINI_API_KEY= + + # Para Vertex AI Express mode (autenticação por chave de API) + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_API_KEY= + + # Para Vertex AI com conta de serviço + GOOGLE_CLOUD_PROJECT= + GOOGLE_CLOUD_LOCATION= # Padrão: us-central1 + ``` + + **Uso Básico:** + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash", + ) + ``` + + **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= + ``` + + Em seguida, use o LLM normalmente: + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash" + ) + ``` + + + 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). + + + O Google publica IDs atuais, capacidades e estágios do ciclo de vida no [catálogo de modelos Gemini](https://ai.google.dev/gemini-api/docs/models). Consulte o [cronograma de descontinuação](https://ai.google.dev/gemini-api/docs/deprecations) antes de escolher um modelo estável ou preview. A API Gemini também hospeda [modelos Gemma](https://ai.google.dev/gemma/docs). + + + + Autentique-se com as [Credenciais Padrão do Aplicativo](https://cloud.google.com/docs/authentication/provide-credentials-adc) e configure o provedor Gemini nativo para usar o Vertex AI: + ```toml .env + GOOGLE_GENAI_USE_VERTEXAI=true + GOOGLE_CLOUD_PROJECT= + GOOGLE_CLOUD_LOCATION= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + from crewai import LLM + + llm = LLM( + model="gemini/gemini-3.6-flash" + ) + ``` + + Consulte as [informações de modelos do Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models) para verificar modelos e regiões disponíveis. + + **Nota:** Esta configuração usa a integração Gemini nativa do CrewAI. Adicione-a como dependência ao seu projeto: + ```bash + uv add "crewai[google-genai]" + ``` + + + + ```toml Code + # Obrigatório + AZURE_API_KEY= + AZURE_API_BASE= + AZURE_API_VERSION= + + # Opcional + AZURE_AD_TOKEN= + AZURE_API_TYPE= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="azure/gpt-4", + api_version="2023-05-15" + ) + ``` + + + + ```toml Code + AWS_ACCESS_KEY_ID= + AWS_SECRET_ACCESS_KEY= + AWS_DEFAULT_REGION= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="bedrock/us.anthropic.claude-sonnet-4-6" + ) + ``` + + Antes de usar o Amazon Bedrock, certifique-se de ter o boto3 instalado em seu ambiente + + [Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html) é um serviço gerenciado que fornece acesso a múltiplos modelos fundamentais dos principais provedores de IA através de uma API unificada, permitindo o desenvolvimento seguro e responsável de aplicações de IA. + + + + + ```toml Code + AWS_ACCESS_KEY_ID= + AWS_SECRET_ACCESS_KEY= + AWS_DEFAULT_REGION= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="sagemaker/" + ) + ``` + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + ```toml Code + MISTRAL_API_KEY= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="mistral/mistral-large-latest", + temperature=0.7 + ) + ``` + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + ```toml Code + NVIDIA_API_KEY= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="nvidia_nim/nvidia/nvidia-nemotron-3-ultra-550b-a55b", + temperature=0.7 + ) + ``` + + O catálogo hospedado do NVIDIA NIM muda com frequência. Use o [catálogo de modelos NVIDIA NIM](https://build.nvidia.com/models) para escolher um endpoint atual e confirmar o ID, as modalidades e os limites de contexto. + + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + + O NVIDIA NIM permite rodar LLMs potentes localmente em máquinas Windows usando WSL2 (Windows Subsystem for Linux). + Este método aproveita o GPU NVIDIA para inferência privativa, segura e econômica, sem depender de serviços em nuvem. + Perfeito para desenvolvimento, testes ou produção onde privacidade ou funcionalidades offline são necessárias. + + Aqui está um guia passo a passo para configurar um modelo local NVIDIA NIM: + + 1. Siga as instruções de instalação no [site da NVIDIA](https://docs.nvidia.com/nim/wsl2/latest/getting-started.html) + + 2. Instale o modelo local. Para Llama 3.1-8b siga as [instruções](https://build.nvidia.com/meta/llama-3_1-8b-instruct/deploy) + + 3. Configure seus modelos locais crewai: + + ```python Code + from crewai.llm import LLM + + local_nvidia_nim_llm = LLM( + model="openai/meta/llama-3.1-8b-instruct", # é compatível com openai-api + base_url="http://localhost:8000/v1", + api_key="", # api_key obrigatório, pode usar qualquer texto + ) + + # Então pode usá-lo no seu crew: + + @CrewBase + class MyCrew(): + # ... + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], # type: ignore[index] + llm=local_nvidia_nim_llm + ) + + # ... + ``` + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + + ```toml Code + GROQ_API_KEY= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="groq/qwen/qwen3.6-27b", + temperature=0.7 + ) + ``` + + A Groq diferencia modelos production e preview e desativa IDs regularmente. Consulte o [catálogo de modelos da Groq](https://console.groq.com/docs/models) e a [página de descontinuações](https://console.groq.com/docs/deprecations) antes de escolher um modelo para produção. + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + ```toml Code + # Obrigatório + WATSONX_URL= + WATSONX_APIKEY= + WATSONX_PROJECT_ID= + + # Opcional + WATSONX_TOKEN= + WATSONX_DEPLOYMENT_SPACE_ID= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="watsonx/meta-llama/llama-3-1-70b-instruct", + base_url="https://api.watsonx.ai/v1" + ) + ``` + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + 1. Instale o Ollama: [ollama.ai](https://ollama.ai/) + 2. Rode um modelo: `ollama run llama3` + 3. Configure: + + ```python Code + llm = LLM( + model="ollama/llama3:70b", + base_url="http://localhost:11434" + ) + ``` + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + ```toml Code + FIREWORKS_API_KEY= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="fireworks_ai/accounts/fireworks/models/llama-v3-70b-instruct", + temperature=0.7 + ) + ``` + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + ```toml Code + PERPLEXITY_API_KEY= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="perplexity/sonar-pro" + ) + ``` + + Consulte o [catálogo de modelos da Perplexity](https://docs.perplexity.ai/getting-started/models) e o [changelog](https://docs.perplexity.ai/docs/resources/changelog) para obter IDs atuais e avisos de descontinuação. + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + ```toml Code + HF_TOKEN= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="huggingface/meta-llama/Meta-Llama-3.1-8B-Instruct" + ) + ``` + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + + ```toml Code + SAMBANOVA_API_KEY= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="sambanova/Meta-Llama-3.3-70B-Instruct", + temperature=0.7 + ) + ``` + + Os modelos hospedados no SambaNova Cloud podem mudar independentemente do CrewAI. Consulte o [endpoint de modelos](https://docs.sambanova.ai/docs/api-reference/models/get-environments-available-model-list-metadata) e o [guia de descontinuação](https://docs.sambanova.ai/docs/en/models/deprecations) antes de implantar. + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + ```toml Code + # Obrigatório + CEREBRAS_API_KEY= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="cerebras/gpt-oss-120b", + temperature=0.7, + max_tokens=8192 + ) + ``` + + + Recursos do Cerebras: + - Altas velocidades de inferência + - Preços competitivos + - Equilíbrio entre velocidade e qualidade + - Suporte a longas janelas de contexto + + + Consulte o [catálogo de modelos Cerebras](https://inference-docs.cerebras.ai/models/overview) e os [avisos de descontinuação](https://inference-docs.cerebras.ai/support/deprecation) para obter os IDs atuais dos endpoints públicos. + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + + Defina as seguintes variáveis de ambiente no seu arquivo `.env`: + ```toml Code + OPENROUTER_API_KEY= + ``` + + Exemplo de uso em seu projeto CrewAI: + ```python Code + llm = LLM( + model="openrouter/deepseek/deepseek-r1", + base_url="https://openrouter.ai/api/v1", + api_key=OPENROUTER_API_KEY + ) + ``` + + + Modelos do Open Router: + - openrouter/deepseek/deepseek-r1 + - openrouter/deepseek/deepseek-chat + + + **Nota:** Este provedor usa o LiteLLM. Adicione-o como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + + + +## Respostas em streaming + +O CrewAI suporta respostas em streaming de LLMs, permitindo que sua aplicação receba e processe saídas em tempo real assim que são geradas. + + + + Ative o streaming definindo o parâmetro `stream` como `True` ao inicializar seu LLM: + + ```python + from crewai import LLM + + # Crie um LLM com streaming ativado + llm = LLM( + model="openai/gpt-5.6-terra", + stream=True # Ativar streaming + ) + ``` + + Quando o streaming está ativado, as respostas são entregues em partes à medida que vão sendo geradas, criando uma experiência mais responsiva para o usuário. + + + + O CrewAI emite eventos para cada chunk recebido durante o streaming: + + ```python + from crewai.events import ( + LLMStreamChunkEvent + ) + from crewai.events import BaseEventListener + + class MyCustomListener(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(LLMStreamChunkEvent) + def on_llm_stream_chunk(self, event: LLMStreamChunkEvent): + # Clique para cada chunk assim que chegar + print(f"Received chunk: {event.chunk}") + + my_listener = MyCustomListener() + ``` + + + [Clique aqui](/pt-BR/concepts/event-listener#event-listeners) para mais detalhes + + + + +## Chamada Estruturada de LLM + +O CrewAI suporta respostas estruturadas de LLMs permitindo que você defina um `response_format` usando um modelo Pydantic. Isso permite que o framework automaticamente faça o parsing e valide a saída, facilitando a integração da resposta em sua aplicação sem pós-processamento manual. + +O suporte a saídas estruturadas varia de acordo com o provedor e o modelo. Teste o modelo escolhido antes de depender de respostas estruturadas em produção. + +Por exemplo, é possível definir um modelo Pydantic para representar a resposta esperada e passá-lo como `response_format` ao instanciar o LLM. O modelo será utilizado para converter a resposta do LLM em um objeto Python estruturado. + +```python Code +from crewai import LLM + +class Dog(BaseModel): + name: str + age: int + breed: str + + +llm = LLM(model="openai/gpt-5.6-terra", response_format=Dog) + +response = llm.call( + "Analyze the following messages and return the name, age, and breed. " + "Meet Kona! She is 3 years old and is a black german shepherd." +) +print(response) + +# Output: +# Dog(name='Kona', age=3, breed='black german shepherd') +``` + +## Recursos Avançados e Otimização + +Saiba como obter o máximo da configuração do seu LLM: + + + + O CrewAI inclui recursos inteligentes para gerenciamento de contexto: + + ```python + from crewai import LLM + + # O CrewAI automaticamente gerencia: + # 1. Contagem e acompanhamento de tokens + # 2. Resumo de conteúdo quando necessário + # 3. Divisão de tarefas para grandes contextos + + llm = LLM( + model="openai/gpt-5.6-terra", + max_completion_tokens=4000, # Limitar tamanho da resposta + ) + ``` + + + Boas práticas para o gerenciamento de contexto: + 1. Prefira modelos com janelas apropriadas + 2. Pré-processe entradas muito longas + 3. Utilize divisão para documentos grandes + 4. Monitore tokens para otimizar custos + + + + + + + Escolha a janela de contexto certa para sua tarefa: + - Tarefas pequenas (até 4K tokens): Modelos padrão + - Tarefas médias (entre 4K-32K): Modelos aprimorados + - Tarefas grandes (acima de 32K): Modelos com contexto expandido + + ```python + # Configure o modelo com as opções certas + llm = LLM( + model="openai/gpt-5.6-terra", + reasoning_effort="medium", + max_completion_tokens=4096, + timeout=300 + ) + ``` + + Use os controles compatíveis com o modelo escolhido. Dependendo do provedor, isso pode ser `temperature`, um nível de reasoning ou thinking, ou instruções no prompt que definam o estilo e a variabilidade desejados. + + + + + 1. Monitore o uso de tokens + 2. Implemente limites de taxa (rate limiting) + 3. Use cache quando possível + 4. Defina limites apropriados para max_tokens + + + + + Lembre-se de monitorar regularmente o uso de tokens e ajustar suas configurações para otimizar custos e desempenho. + + + + + 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 stop, basta omiti-lo na chamada do LLM: + + ```python + from crewai import LLM + import os + + os.environ["OPENAI_API_KEY"] = "" + + o3_llm = LLM( + model="o3", + drop_params=True, + additional_drop_params=["stop"] + ) + ``` + + + +## Problemas Comuns e Soluções + + + + + A maioria dos problemas de autenticação pode ser resolvida verificando o formato da chave da API e os nomes das variáveis de ambiente. + + + ```bash + # OpenAI + OPENAI_API_KEY=sk-... + + # Anthropic + ANTHROPIC_API_KEY=sk-ant-... + ``` + + + + Sempre inclua o prefixo do provedor nos nomes dos modelos + + + ```python + # Correto + llm = LLM(model="openai/gpt-4") + + # Incorreto + llm = LLM(model="gpt-4") + ``` + + + + Use modelos de contexto expandido para tarefas extensas + + + ```python + # Modelo com contexto expandido + llm = LLM(model="openai/gpt-4o") # 128K tokens + ``` + + diff --git a/docs/v1.15.13/pt-BR/concepts/memory.mdx b/docs/v1.15.13/pt-BR/concepts/memory.mdx new file mode 100644 index 0000000000..3931ed6ab5 --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/memory.mdx @@ -0,0 +1,878 @@ +--- +title: Memória +description: Aproveitando o sistema de memória unificado no CrewAI para aprimorar as capacidades dos agentes. +icon: database +mode: "wide" +--- + +## Visão Geral + +O CrewAI oferece um **sistema de memória unificado** -- uma única classe `Memory` que substitui memórias de curto prazo, longo prazo, entidades e externa por uma API inteligente. A memória usa um LLM para analisar o conteúdo ao salvar (inferindo escopo, categorias e importância) e suporta recall com profundidade adaptativa e pontuação composta que combina similaridade semântica, recência e importância. + +Você pode usar a memória de quatro formas: **standalone** (scripts, notebooks), **com Crews**, **com Agentes** ou **dentro de Flows**. + +## Início Rápido + +```python +from crewai import Memory + +memory = Memory() + +# Armazenar -- o LLM infere escopo, categorias e importância +memory.remember("Decidimos usar PostgreSQL para o banco de dados de usuários.") + +# Recuperar -- resultados ranqueados por pontuação composta (semântica + recência + importância) +matches = memory.recall("Qual banco de dados escolhemos?") +for m in matches: + print(f"[{m.score:.2f}] {m.record.content}") + +# Ajustar pontuação para um projeto dinâmico +memory = Memory(recency_weight=0.5, recency_half_life_days=7) + +# Esquecer +memory.forget(scope="/project/old") + +# Explorar a árvore de escopos auto-organizada +print(memory.tree()) +print(memory.info("/")) +``` + +## Quatro Formas de Usar Memória + +### Standalone + +Use memória em scripts, notebooks, ferramentas CLI ou como base de conhecimento independente -- sem agentes ou crews necessários. + +```python +from crewai import Memory + +memory = Memory() + +# Construir conhecimento +memory.remember("O limite da API é 1000 requisições por minuto.") +memory.remember("Nosso ambiente de staging usa a porta 8080.") +memory.remember("A equipe concordou em usar feature flags para todos os novos lançamentos.") + +# Depois, recupere o que precisar +matches = memory.recall("Quais são nossos limites de API?", limit=5) +for m in matches: + print(f"[{m.score:.2f}] {m.record.content}") + +# Extrair fatos atômicos de um texto mais longo +raw = """Notas da reunião: Decidimos migrar do MySQL para PostgreSQL +no próximo trimestre. O orçamento é de $50k. Sarah liderará a migração.""" + +facts = memory.extract_memories(raw) +# ["Migração de MySQL para PostgreSQL planejada para o próximo trimestre", +# "Orçamento da migração de banco de dados é $50k", +# "Sarah liderará a migração do banco de dados"] + +for fact in facts: + memory.remember(fact) +``` + +### Com Crews + +Passe `memory=True` para configurações padrão, ou passe uma instância `Memory` configurada para comportamento customizado. + +```python +from crewai import Crew, Agent, Task, Process, Memory + +# Opção 1: Memória padrão +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + memory=True, + verbose=True, +) + +# Opção 2: Memória customizada com pontuação ajustada +memory = Memory( + recency_weight=0.4, + semantic_weight=0.4, + importance_weight=0.2, + recency_half_life_days=14, +) +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + memory=memory, +) +``` + +Quando `memory=True`, a crew cria um `Memory()` padrão e repassa a configuração de `embedder` da crew automaticamente. Todos os agentes compartilham a memória da crew, a menos que um agente tenha sua própria. + +Após cada tarefa, a crew extrai automaticamente fatos discretos da saída da tarefa e os armazena. Antes de cada tarefa, o agente recupera contexto relevante da memória e o injeta no prompt da tarefa. + +### Com Agentes + +Agentes podem usar a memória compartilhada da crew (padrão) ou receber uma visão com escopo para contexto privado. + +```python +from crewai import Agent, Memory + +memory = Memory() + +# Pesquisador recebe um escopo privado -- só vê /agent/researcher +researcher = Agent( + role="Researcher", + goal="Encontrar e analisar informações", + backstory="Pesquisador experiente com atenção aos detalhes", + memory=memory.scope("/agent/researcher"), +) + +# Escritor usa memória compartilhada da crew (sem memória própria) +writer = Agent( + role="Writer", + goal="Produzir conteúdo claro e bem estruturado", + backstory="Escritor técnico experiente", + # memory não definido -- usa crew._memory quando a crew tem memória habilitada +) +``` + +Esse padrão dá ao pesquisador descobertas privadas enquanto o escritor lê da memória compartilhada da crew. + +### Com Flows + +Todo Flow possui memória integrada. Use `self.remember()`, `self.recall()` e `self.extract_memories()` dentro de qualquer método do flow. + +```python +from crewai.flow.flow import Flow, listen, start + +class ResearchFlow(Flow): + @start() + def gather_data(self): + findings = "PostgreSQL suporta 10k conexões simultâneas. MySQL limita a 5k." + self.remember(findings, scope="/research/databases") + return findings + + @listen(gather_data) + def write_report(self, findings): + # Recuperar pesquisas anteriores para fornecer contexto + past = self.recall("benchmarks de performance de banco de dados") + context = "\n".join(f"- {m.record.content}" for m in past) + return f"Relatório:\nNovas descobertas: {findings}\nContexto anterior:\n{context}" +``` + +Veja a [documentação de Flows](/concepts/flows) para mais informações sobre memória em Flows. + + +## Escopos Hierárquicos + +### O Que São Escopos + +As memórias são organizadas em uma árvore hierárquica de escopos, similar a um sistema de arquivos. Cada escopo é um caminho como `/`, `/project/alpha` ou `/agent/researcher/findings`. + +``` +/ + /company + /company/engineering + /company/product + /project + /project/alpha + /project/beta + /agent + /agent/researcher + /agent/writer +``` + +Escopos fornecem **memória dependente de contexto** -- quando você faz recall dentro de um escopo, busca apenas naquela ramificação da árvore, melhorando tanto a precisão quanto o desempenho. + +### Como a Inferência de Escopo Funciona + +Quando você chama `remember()` sem especificar um escopo, o LLM analisa o conteúdo e a árvore de escopos existente, e sugere o melhor posicionamento. Se nenhum escopo existente é adequado, ele cria um novo. Com o tempo, a árvore de escopos cresce organicamente a partir do conteúdo -- você não precisa projetar um esquema antecipadamente. + +```python +memory = Memory() + +# LLM infere escopo a partir do conteúdo +memory.remember("Escolhemos PostgreSQL para o banco de dados de usuários.") +# -> pode ser colocado em /project/decisions ou /engineering/database + +# Você também pode especificar o escopo explicitamente +memory.remember("Velocidade do sprint é 42 pontos", scope="/team/metrics") +``` + +### Visualizando a Árvore de Escopos + +```python +print(memory.tree()) +# / (15 records) +# /project (8 records) +# /project/alpha (5 records) +# /project/beta (3 records) +# /agent (7 records) +# /agent/researcher (4 records) +# /agent/writer (3 records) + +print(memory.info("/project/alpha")) +# ScopeInfo(path='/project/alpha', record_count=5, +# categories=['architecture', 'database'], +# oldest_record=datetime(...), newest_record=datetime(...), +# child_scopes=[]) +``` + +### MemoryScope: Visões de Subárvore + +Um `MemoryScope` restringe todas as operações a uma ramificação da árvore. O agente ou código que o utiliza só pode ver e escrever dentro daquela subárvore. + +```python +memory = Memory() + +# Criar um escopo para um agente específico +agent_memory = memory.scope("/agent/researcher") + +# Tudo é relativo a /agent/researcher +agent_memory.remember("Encontrados três papers relevantes sobre memória de LLM.") +# -> armazenado em /agent/researcher + +agent_memory.recall("papers relevantes") +# -> busca apenas em /agent/researcher + +# Restringir ainda mais com subscope +project_memory = agent_memory.subscope("project-alpha") +# -> /agent/researcher/project-alpha +``` + +### Boas Práticas para Design de Escopos + +- **Comece plano, deixe o LLM organizar.** Não projete demais sua hierarquia de escopos antecipadamente. Comece com `memory.remember(content)` e deixe a inferência de escopo do LLM criar estrutura conforme o conteúdo se acumula. + +- **Use padrões `/{tipo_entidade}/{identificador}`.** Hierarquias naturais emergem de padrões como `/project/alpha`, `/agent/researcher`, `/company/engineering`, `/customer/acme-corp`. + +- **Escopo por preocupação, não por tipo de dado.** Use `/project/alpha/decisions` em vez de `/decisions/project/alpha`. Isso mantém conteúdo relacionado junto. + +- **Mantenha profundidade rasa (2-3 níveis).** Escopos profundamente aninhados ficam muito esparsos. `/project/alpha/architecture` é bom; `/project/alpha/architecture/decisions/databases/postgresql` é demais. + +- **Use escopos explícitos quando souber, deixe o LLM inferir quando não souber.** Se está armazenando uma decisão de projeto conhecida, passe `scope="/project/alpha/decisions"`. Se está armazenando saída livre de um agente, omita o escopo e deixe o LLM decidir. + +### Exemplos de Casos de Uso + +**Equipe multi-projeto:** +```python +memory = Memory() +# Cada projeto recebe sua própria ramificação +memory.remember("Usando arquitetura de microsserviços", scope="/project/alpha/architecture") +memory.remember("API GraphQL para apps cliente", scope="/project/beta/api") + +# Recall em todos os projetos +memory.recall("decisões de design de API") + +# Ou dentro de um projeto específico +memory.recall("design de API", scope="/project/beta") +``` + +**Contexto privado por agente com conhecimento compartilhado:** +```python +memory = Memory() + +# Pesquisador tem descobertas privadas +researcher_memory = memory.scope("/agent/researcher") + +# Escritor pode ler de seu próprio escopo e do conhecimento compartilhado da empresa +writer_view = memory.slice( + scopes=["/agent/writer", "/company/knowledge"], + read_only=True, +) +``` + +**Suporte ao cliente (contexto por cliente):** +```python +memory = Memory() + +# Cada cliente recebe contexto isolado +memory.remember("Prefere comunicação por email", scope="/customer/acme-corp") +memory.remember("Plano enterprise, 50 licenças", scope="/customer/acme-corp") + +# Docs de produto compartilhados são acessíveis a todos os agentes +memory.remember("Limite de taxa é 1000 req/min no plano enterprise", scope="/product/docs") +``` + + +## Fatias de Memória (Memory Slices) + +### O Que São Fatias + +Um `MemorySlice` é uma visão sobre múltiplos escopos, possivelmente disjuntos. Diferente de um escopo (que restringe a uma subárvore), uma fatia permite recall de várias ramificações simultaneamente. + +### Quando Usar Fatias vs Escopos + +- **Escopo**: Use quando um agente ou bloco de código deve ser restrito a uma única subárvore. Exemplo: um agente que só vê `/agent/researcher`. +- **Fatia**: Use quando precisar combinar contexto de múltiplas ramificações. Exemplo: um agente que lê de seu próprio escopo mais conhecimento compartilhado da empresa. + +### Fatias Somente Leitura + +O padrão mais comum: dar a um agente acesso de leitura a múltiplas ramificações sem permitir que ele escreva em áreas compartilhadas. + +```python +memory = Memory() + +# Agente pode fazer recall de seu próprio escopo E do conhecimento da empresa, +# mas não pode escrever no conhecimento da empresa +agent_view = memory.slice( + scopes=["/agent/researcher", "/company/knowledge"], + read_only=True, +) + +matches = agent_view.recall("políticas de segurança da empresa", limit=5) +# Busca em /agent/researcher e /company/knowledge, mescla e ranqueia resultados + +agent_view.remember("nova descoberta") # Levanta PermissionError (somente leitura) +``` + +### Fatias de Leitura e Escrita + +Quando somente leitura está desabilitado, você pode escrever em qualquer um dos escopos incluídos, mas deve especificar qual escopo explicitamente. + +```python +view = memory.slice(scopes=["/team/alpha", "/team/beta"], read_only=False) + +# Deve especificar escopo ao escrever +view.remember("Decisão entre equipes", scope="/team/alpha", categories=["decisions"]) +``` + + +## Pontuação Composta + +Os resultados do recall são ranqueados por uma combinação ponderada de três sinais: + +``` +composite = semantic_weight * similarity + recency_weight * decay + importance_weight * importance +``` + +Onde: +- **similarity** = `1 / (1 + distance)` do índice vetorial (0 a 1) +- **decay** = `0.5^(age_days / half_life_days)` -- decaimento exponencial (1.0 para hoje, 0.5 na meia-vida) +- **importance** = pontuação de importância do registro (0 a 1), definida no momento da codificação + +Configure diretamente no construtor do `Memory`: + +```python +# Retrospectiva de sprint: favorecer memórias recentes, meia-vida curta +memory = Memory( + recency_weight=0.5, + semantic_weight=0.3, + importance_weight=0.2, + recency_half_life_days=7, +) + +# Base de conhecimento de arquitetura: favorecer memórias importantes, meia-vida longa +memory = Memory( + recency_weight=0.1, + semantic_weight=0.5, + importance_weight=0.4, + recency_half_life_days=180, +) +``` + +Cada `MemoryMatch` inclui uma lista `match_reasons` para que você possa ver por que um resultado ficou na posição que ficou (ex.: `["semantic", "recency", "importance"]`). + + +## Camada de Análise LLM + +A memória usa o LLM de três formas: + +1. **Ao salvar** -- Quando você omite escopo, categorias ou importância, o LLM analisa o conteúdo e sugere escopo, categorias, importância e metadados (entidades, datas, tópicos). +2. **Ao fazer recall** -- Para recall profundo/automático, o LLM analisa a consulta (palavras-chave, dicas temporais, escopos sugeridos, complexidade) para guiar a recuperação. +3. **Extrair memórias** -- `extract_memories(content)` quebra texto bruto (ex.: saída de tarefa) em afirmações de memória discretas. Os agentes usam isso antes de chamar `remember()` em cada afirmação para que fatos atômicos sejam armazenados em vez de um bloco grande. + +Toda análise degrada graciosamente em caso de falha do LLM -- veja [Comportamento em Caso de Falha](#comportamento-em-caso-de-falha). + + +## Consolidação de Memória + +Ao salvar novo conteúdo, o pipeline de codificação verifica automaticamente registros similares existentes no armazenamento. Se a similaridade estiver acima de `consolidation_threshold` (padrão 0.85), o LLM decide o que fazer: + +- **keep** -- O registro existente ainda é preciso e não é redundante. +- **update** -- O registro existente deve ser atualizado com novas informações (o LLM fornece o conteúdo mesclado). +- **delete** -- O registro existente está desatualizado, substituído ou contradito. +- **insert_new** -- Se o novo conteúdo também deve ser inserido como um registro separado. + +Isso evita o acúmulo de duplicatas. Por exemplo, se você salvar "CrewAI garante operação confiável" três vezes, a consolidação reconhece as duplicatas e mantém apenas um registro. + +### Dedup Intra-batch + +Ao usar `remember_many()`, os itens dentro do mesmo batch são comparados entre si antes de atingir o armazenamento. Se dois itens tiverem similaridade de cosseno >= `batch_dedup_threshold` (padrão 0.98), o posterior é silenciosamente descartado. Isso captura duplicatas exatas ou quase exatas dentro de um único batch sem chamadas ao LLM (pura matemática vetorial). + +```python +# Apenas 2 registros são armazenados (o terceiro é quase duplicata do primeiro) +memory.remember_many([ + "CrewAI supports complex workflows.", + "Python is a great language.", + "CrewAI supports complex workflows.", # descartado pelo dedup intra-batch +]) +``` + + +## Saves Não-Bloqueantes + +`remember_many()` é **não-bloqueante** -- ele envia o pipeline de codificação para uma thread em background e retorna imediatamente. Isso significa que o agente pode continuar para a próxima tarefa enquanto as memórias estão sendo salvas. + +```python +# Retorna imediatamente -- save acontece em background +memory.remember_many(["Fato A.", "Fato B.", "Fato C."]) + +# recall() espera automaticamente saves pendentes antes de buscar +matches = memory.recall("fatos") # vê todos os 3 registros +``` + +### Barreira de Leitura + +Cada chamada `recall()` executa automaticamente `drain_writes()` antes de buscar, garantindo que a consulta sempre veja os registros mais recentes persistidos. Isso é transparente -- você nunca precisa pensar nisso. + +### Encerramento da Crew + +Quando uma crew termina, `kickoff()` drena todos os saves de memória pendentes em seu bloco `finally`, então nenhum save é perdido mesmo que a crew complete enquanto saves em background estão em andamento. + +### Uso Standalone + +Para scripts ou notebooks onde não há ciclo de vida de crew, chame `drain_writes()` ou `close()` explicitamente: + +```python +memory = Memory() +memory.remember_many(["Fato A.", "Fato B."]) + +# Opção 1: Esperar saves pendentes +memory.drain_writes() + +# Opção 2: Drenar e encerrar o pool de background +memory.close() +``` + + +## Origem e Privacidade + +Cada registro de memória pode carregar uma tag `source` para rastreamento de procedência e uma flag `private` para controle de acesso. + +### Rastreamento de Origem + +O parâmetro `source` identifica de onde uma memória veio: + +```python +# Marcar memórias com sua origem +memory.remember("Usuário prefere modo escuro", source="user:alice") +memory.remember("Configuração do sistema atualizada", source="admin") +memory.remember("Agente encontrou um bug", source="agent:debugger") + +# Recuperar apenas memórias de uma origem específica +matches = memory.recall("preferências do usuário", source="user:alice") +``` + +### Memórias Privadas + +Memórias privadas só são visíveis no recall quando o `source` corresponde: + +```python +# Armazenar uma memória privada +memory.remember("A chave de API da Alice é sk-...", source="user:alice", private=True) + +# Este recall vê a memória privada (source corresponde) +matches = memory.recall("chave de API", source="user:alice") + +# Este recall NÃO a vê (source diferente) +matches = memory.recall("chave de API", source="user:bob") + +# Acesso admin: ver todos os registros privados independente do source +matches = memory.recall("chave de API", include_private=True) +``` + +Isso é particularmente útil em implantações multi-usuário ou corporativas onde memórias de diferentes usuários devem ser isoladas. + + +## RecallFlow (Recall Profundo) + +`recall()` suporta duas profundidades: + +- **`depth="shallow"`** -- Busca vetorial direta com pontuação composta. Rápido (~200ms), sem chamadas ao LLM. +- **`depth="deep"` (padrão)** -- Executa um RecallFlow em múltiplas etapas: análise da consulta, seleção de escopo, busca vetorial paralela, roteamento baseado em confiança e exploração recursiva opcional quando a confiança é baixa. + +**Pulo inteligente do LLM**: Consultas com menos de `query_analysis_threshold` (padrão 200 caracteres) pulam a análise de consulta do LLM inteiramente, mesmo no modo deep. Consultas curtas como "Qual banco de dados usamos?" já são boas frases de busca -- a análise do LLM agrega pouco valor. Isso economiza ~1-3s por recall para consultas curtas típicas. Apenas consultas mais longas (ex.: descrições completas de tarefas) passam pela destilação do LLM em sub-consultas direcionadas. + +```python +# Shallow: busca vetorial pura, sem LLM +matches = memory.recall("O que decidimos?", limit=10, depth="shallow") + +# Deep (padrão): recuperação inteligente com análise LLM para consultas longas +matches = memory.recall( + "Resuma todas as decisões de arquitetura deste trimestre", + limit=10, + depth="deep", +) +``` + +Os limiares de confiança que controlam o roteador do RecallFlow são configuráveis: + +```python +memory = Memory( + confidence_threshold_high=0.9, # Só sintetizar quando muito confiante + confidence_threshold_low=0.4, # Explorar mais profundamente de forma mais agressiva + exploration_budget=2, # Permitir até 2 rodadas de exploração + query_analysis_threshold=200, # Pular LLM para consultas menores que isso +) +``` + + +## Configuração de Embedder + +A memória precisa de um modelo de embedding para converter texto em vetores para busca semântica. Você pode configurar de três formas. + +### Passando Diretamente para o Memory + +```python +from crewai import Memory + +# Como um dict de configuração +memory = Memory(embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-small"}}) + +# Como um callable pré-construído +from crewai.rag.embeddings.factory import build_embedder +embedder = build_embedder({"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}) +memory = Memory(embedder=embedder) +``` + +### Via Configuração de Embedder da Crew + +Quando usar `memory=True`, a configuração de `embedder` da crew é repassada: + +```python +from crewai import Crew + +crew = Crew( + agents=[...], + tasks=[...], + memory=True, + embedder={"provider": "openai", "config": {"model_name": "text-embedding-3-small"}}, +) +``` + +### Exemplos por Provedor + + + +```python +memory = Memory(embedder={ + "provider": "openai", + "config": { + "model_name": "text-embedding-3-small", + # "api_key": "sk-...", # ou defina OPENAI_API_KEY + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "ollama", + "config": { + "model_name": "mxbai-embed-large", + "url": "http://localhost:11434/api/embeddings", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "azure", + "config": { + "deployment_id": "your-embedding-deployment", + "api_key": "your-azure-api-key", + "api_base": "https://your-resource.openai.azure.com", + "api_version": "2024-02-01", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "google-generativeai", + "config": { + "model_name": "gemini-embedding-001", + # "api_key": "...", # ou defina GOOGLE_API_KEY + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "google-vertex", + "config": { + "model_name": "gemini-embedding-001", + "project_id": "your-gcp-project-id", + "location": "us-central1", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "cohere", + "config": { + "model_name": "embed-english-v3.0", + # "api_key": "...", # ou defina COHERE_API_KEY + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "voyageai", + "config": { + "model": "voyage-3", + # "api_key": "...", # ou defina VOYAGE_API_KEY + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "amazon-bedrock", + "config": { + "model_name": "amazon.titan-embed-text-v1", + # Usa credenciais AWS padrão (sessão boto3) + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "huggingface", + "config": { + "model_name": "sentence-transformers/all-MiniLM-L6-v2", + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "jina", + "config": { + "model_name": "jina-embeddings-v2-base-en", + # "api_key": "...", # ou defina JINA_API_KEY + }, +}) +``` + + + +```python +memory = Memory(embedder={ + "provider": "watsonx", + "config": { + "model_id": "ibm/slate-30m-english-rtrvr", + "api_key": "your-watsonx-api-key", + "project_id": "your-project-id", + "url": "https://us-south.ml.cloud.ibm.com", + }, +}) +``` + + + +```python +# Passe qualquer callable que receba uma lista de strings e retorne uma lista de vetores +def my_embedder(texts: list[str]) -> list[list[float]]: + # Sua lógica de embedding aqui + return [[0.1, 0.2, ...] for _ in texts] + +memory = Memory(embedder=my_embedder) +``` + + + +### Referência de Provedores + +| Provedor | Chave | Modelo Típico | Notas | +| :--- | :--- | :--- | :--- | +| OpenAI | `openai` | `text-embedding-3-small` | Padrão. Defina `OPENAI_API_KEY`. | +| Ollama | `ollama` | `mxbai-embed-large` | Local, sem API key. | +| Azure OpenAI | `azure` | `text-embedding-ada-002` | Requer `deployment_id`. | +| Google AI | `google-generativeai` | `gemini-embedding-001` | Defina `GOOGLE_API_KEY`. | +| Google Vertex | `google-vertex` | `gemini-embedding-001` | Requer `project_id`. | +| Cohere | `cohere` | `embed-english-v3.0` | Forte suporte multilíngue. | +| VoyageAI | `voyageai` | `voyage-3` | Otimizado para retrieval. | +| AWS Bedrock | `amazon-bedrock` | `amazon.titan-embed-text-v1` | Usa credenciais boto3. | +| Hugging Face | `huggingface` | `all-MiniLM-L6-v2` | Sentence-transformers local. | +| Jina | `jina` | `jina-embeddings-v2-base-en` | Defina `JINA_API_KEY`. | +| IBM WatsonX | `watsonx` | `ibm/slate-30m-english-rtrvr` | Requer `project_id`. | +| Sentence Transformer | `sentence-transformer` | `all-MiniLM-L6-v2` | Local, sem API key. | +| Custom | `custom` | -- | Requer `embedding_callable`. | + + +## Configuração de LLM + +A memória usa um LLM para análise de save (inferência de escopo, categorias e importância), decisões de consolidação e análise de consulta no recall profundo. Você pode configurar qual modelo usar. + +```python +from crewai import Memory, LLM + +# Padrão: gpt-4o-mini +memory = Memory() + +# Usar um modelo OpenAI diferente +memory = Memory(llm="gpt-4o") + +# Usar Anthropic +memory = Memory(llm="anthropic/claude-3-haiku-20240307") + +# Usar Ollama para análise totalmente local/privada +memory = Memory(llm="ollama/llama3.2") + +# Usar Google Gemini +memory = Memory(llm="gemini/gemini-2.0-flash") + +# Passar uma instância LLM pré-configurada com configurações customizadas +llm = LLM(model="gpt-4o", temperature=0) +memory = Memory(llm=llm) +``` + +O LLM é inicializado **lazily** -- ele só é criado quando necessário pela primeira vez. Isso significa que `Memory()` nunca falha no momento da construção, mesmo que chaves de API não estejam definidas. Erros só aparecem quando o LLM é realmente chamado (ex.: ao salvar sem escopo/categorias explícitos, ou durante recall profundo). + +Para operação totalmente offline/privada, use um modelo local tanto para o LLM quanto para o embedder: + +```python +memory = Memory( + llm="ollama/llama3.2", + embedder={"provider": "ollama", "config": {"model_name": "mxbai-embed-large"}}, +) +``` + + +## Backend de Armazenamento + +- **Padrão**: LanceDB, armazenado em `./.crewai/memory` (ou `$CREWAI_STORAGE_DIR/memory` se a variável de ambiente estiver definida, ou o caminho que você passar como `storage="path/to/dir"`). +- **Backend customizado**: Implemente o protocolo `StorageBackend` (veja `crewai.memory.storage.backend`) e passe uma instância para `Memory(storage=your_backend)`. + + +## Descoberta + +Inspecione a hierarquia de escopos, categorias e registros: + +```python +memory.tree() # Árvore formatada de escopos e contagem de registros +memory.tree("/project", max_depth=2) # Visão de subárvore +memory.info("/project") # ScopeInfo: record_count, categories, oldest/newest +memory.list_scopes("/") # Escopos filhos imediatos +memory.list_categories() # Nomes e contagens de categorias +memory.list_records(scope="/project/alpha", limit=20) # Registros em um escopo, mais recentes primeiro +``` + + +## Comportamento em Caso de Falha + +Se o LLM falhar durante a análise (erro de rede, limite de taxa, resposta inválida), a memória degrada graciosamente: + +- **Análise de save** -- Um aviso é registrado e a memória ainda é armazenada com escopo padrão `/`, categorias vazias e importância `0.5`. +- **Extrair memórias** -- O conteúdo completo é armazenado como uma única memória para que nada seja descartado. +- **Análise de consulta** -- O recall usa fallback para seleção simples de escopo e busca vetorial, então você ainda obtém resultados. + +Nenhuma exceção é levantada para essas falhas de análise; apenas falhas de armazenamento ou do embedder irão levantar. + + +## Nota sobre Privacidade + +O conteúdo da memória é enviado ao LLM configurado para análise (escopo/categorias/importância no save, análise de consulta e recall profundo opcional). Para dados sensíveis, use um LLM local (ex.: Ollama) ou garanta que seu provedor atenda aos requisitos de conformidade. + + +## Eventos de Memória + +Todas as operações de memória emitem eventos com `source_type="unified_memory"`. Você pode escutar para timing, erros e conteúdo. + +| Evento | Descrição | Propriedades Principais | +| :---- | :---------- | :------------- | +| **MemoryQueryStartedEvent** | Consulta inicia | `query`, `limit` | +| **MemoryQueryCompletedEvent** | Consulta bem-sucedida | `query`, `results`, `query_time_ms` | +| **MemoryQueryFailedEvent** | Consulta falha | `query`, `error` | +| **MemorySaveStartedEvent** | Save inicia | `value`, `metadata` | +| **MemorySaveCompletedEvent** | Save bem-sucedido | `value`, `save_time_ms` | +| **MemorySaveFailedEvent** | Save falha | `value`, `error` | +| **MemoryRetrievalStartedEvent** | Retrieval do agente inicia | `task_id` | +| **MemoryRetrievalCompletedEvent** | Retrieval do agente completo | `task_id`, `memory_content`, `retrieval_time_ms` | + +Exemplo: monitorar tempo de consulta: + +```python +from crewai.events import BaseEventListener, MemoryQueryCompletedEvent + +class MemoryMonitor(BaseEventListener): + def setup_listeners(self, crewai_event_bus): + @crewai_event_bus.on(MemoryQueryCompletedEvent) + def on_done(source, event): + if getattr(event, "source_type", None) == "unified_memory": + print(f"Query '{event.query}' completou em {event.query_time_ms:.0f}ms") +``` + + +## Solução de Problemas + +**Memória não persiste?** +- Garanta que o caminho de armazenamento seja gravável (padrão `./.crewai/memory`). Passe `storage="./your_path"` para usar outro diretório, ou defina a variável de ambiente `CREWAI_STORAGE_DIR`. +- Ao usar uma crew, confirme que `memory=True` ou `memory=Memory(...)` está definido. + +**Recall lento?** +- Use `depth="shallow"` para contexto rotineiro do agente. Reserve `depth="deep"` para consultas complexas. +- Aumente `query_analysis_threshold` para pular a análise do LLM em mais consultas. + +**Erros de análise LLM nos logs?** +- A memória ainda salva/recupera com padrões seguros. Verifique chaves de API, limites de taxa e disponibilidade do modelo se quiser análise LLM completa. + +**Erros de save em background nos logs?** +- Os saves de memória rodam em uma thread em background. Erros são emitidos como `MemorySaveFailedEvent` mas não derrubam o agente. Verifique os logs para a causa raiz (geralmente problemas de conexão com LLM ou embedder). + +**Conflitos de escrita concorrente?** +- As operações do LanceDB são serializadas com um lock compartilhado e reexecutadas automaticamente em caso de conflito. Isso lida com múltiplas instâncias `Memory` apontando para o mesmo banco de dados (ex.: memória do agente + memória da crew). Nenhuma ação necessária. + +**Navegar na memória pelo terminal:** +```bash +crewai memory # Abre o navegador TUI +crewai memory --storage-path ./my_memory # Apontar para um diretório específico +``` + +**Resetar memória (ex.: para testes):** +```python +crew.reset_memories(command_type="memory") # Reseta memória unificada +# Ou em uma instância Memory: +memory.reset() # Todos os escopos +memory.reset(scope="/project/old") # Apenas essa subárvore +``` + + +## Referência de Configuração + +Toda a configuração é passada como argumentos nomeados para `Memory(...)`. Cada parâmetro tem um padrão sensato. + +| Parâmetro | Padrão | Descrição | +| :--- | :--- | :--- | +| `llm` | `"gpt-4o-mini"` | LLM para análise (nome do modelo ou instância `BaseLLM`). | +| `storage` | `"lancedb"` | Backend de armazenamento (`"lancedb"`, string de caminho ou instância `StorageBackend`). | +| `embedder` | `None` (OpenAI padrão) | Embedder (dict de config, callable ou `None` para OpenAI padrão). | +| `recency_weight` | `0.3` | Peso da recência na pontuação composta. | +| `semantic_weight` | `0.5` | Peso da similaridade semântica na pontuação composta. | +| `importance_weight` | `0.2` | Peso da importância na pontuação composta. | +| `recency_half_life_days` | `30` | Dias para a pontuação de recência cair pela metade (decaimento exponencial). | +| `consolidation_threshold` | `0.85` | Similaridade acima da qual a consolidação é ativada no save. Defina `1.0` para desativar. | +| `consolidation_limit` | `5` | Máx. de registros existentes para comparar durante consolidação. | +| `default_importance` | `0.5` | Importância atribuída quando não fornecida e a análise LLM é pulada. | +| `batch_dedup_threshold` | `0.98` | Similaridade de cosseno para descartar quase-duplicatas dentro de um batch `remember_many()`. | +| `confidence_threshold_high` | `0.8` | Confiança de recall acima da qual resultados são retornados diretamente. | +| `confidence_threshold_low` | `0.5` | Confiança de recall abaixo da qual exploração mais profunda é ativada. | +| `complex_query_threshold` | `0.7` | Para consultas complexas, explorar mais profundamente abaixo desta confiança. | +| `exploration_budget` | `1` | Número de rodadas de exploração por LLM durante recall profundo. | +| `query_analysis_threshold` | `200` | Consultas menores que isso (em caracteres) pulam análise LLM durante recall profundo. | diff --git a/docs/v1.15.13/pt-BR/concepts/planning.mdx b/docs/v1.15.13/pt-BR/concepts/planning.mdx new file mode 100644 index 0000000000..c4e511da7c --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/planning.mdx @@ -0,0 +1,153 @@ +--- +title: Planejamento +description: Aprenda como adicionar planejamento à sua CrewAI Crew e melhorar sua performance. +icon: ruler-combined +mode: "wide" +--- + +## Visão geral + +O recurso de planejamento no CrewAI permite que você adicione capacidade de planejamento à sua crew. Quando ativado, antes de cada iteração da Crew, todas as informações da Crew são enviadas para um AgentPlanner que irá planejar as tarefas passo a passo, e este plano será adicionado à descrição de cada tarefa. + +### Usando o recurso de Planejamento + +Começar a usar o recurso de planejamento é muito simples, o único passo necessário é adicionar `planning=True` à sua Crew: + + +```python Code +from crewai import Crew, Agent, Task, Process + +# Monte sua crew com capacidades de planejamento +minha_crew = Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + planning=True, +) +``` + + +A partir deste ponto, sua crew terá o planejamento ativado, e as tarefas serão planejadas antes de cada iteração. + + +Quando o planejamento está ativado, o crewAI irá usar `gpt-4o-mini` como o LLM padrão para planejamento, o que requer uma chave de API válida da OpenAI. Como seus agentes podem estar usando LLMs diferentes, isso pode causar confusão se você não tiver uma chave de API da OpenAI configurada ou se estiver experimentando um comportamento inesperado relacionado a chamadas de API de LLM. + + +#### LLM de Planejamento + +Agora você pode definir qual LLM será usado para planejar as tarefas. + +Ao executar o exemplo básico, você verá algo semelhante ao resultado abaixo, que representa a saída do `AgentPlanner` responsável por criar a lógica passo a passo a ser adicionada às tarefas dos Agents. + + +```python Code +from crewai import Crew, Agent, Task, Process + +# Monte sua crew com capacidades de planejamento e LLM personalizado +my_crew = Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + planning=True, + planning_llm="gpt-4o" +) + +# Execute a crew +my_crew.kickoff() +``` + +```markdown Result +[2024-07-15 16:49:11][INFO]: Planejando a execução da crew +**Plano Passo a Passo para Execução das Tarefas** + +**Tarefa Número 1: Realizar uma pesquisa aprofundada sobre LLMs de IA** + +**Agente:** Pesquisador Sênior de Dados de LLMs de IA + +**Objetivo do Agente:** Descobrir avanços de ponta em LLMs de IA + +**Resultado Esperado da Tarefa:** Uma lista com 10 tópicos dos dados mais relevantes sobre LLMs de IA + +**Ferramentas da Tarefa:** Nenhuma especificada + +**Ferramentas do Agente:** Nenhuma especificada + +**Plano Passo a Passo:** + +1. **Definir o Escopo da Pesquisa:** + + - Determine as áreas específicas de LLMs de IA a focar, como avanços em arquitetura, casos de uso, considerações éticas e métricas de performance. + +2. **Identificar Fontes Confiáveis:** + + - Liste fontes confiáveis para pesquisa em IA, incluindo periódicos acadêmicos, relatórios da indústria, conferências (ex: NeurIPS, ACL), laboratórios de pesquisa em IA (ex: OpenAI, Google AI) e bancos de dados online (ex: IEEE Xplore, arXiv). + +3. **Coletar Dados:** + + - Procure pelos artigos, publicações e relatórios mais recentes publicados em 2024 e início de 2025. + - Use palavras-chave como "Large Language Models 2025", "Avanços em LLM de IA", "Ética em IA 2025", etc. + +4. **Analisar Resultados:** + + - Leia e resuma os principais pontos de cada fonte. + - Destaque novas técnicas, modelos e aplicações introduzidos no último ano. + +5. **Organizar as Informações:** + + - Categorize as informações em tópicos relevantes (ex: novas arquiteturas, implicações éticas, aplicações no mundo real). + - Garanta que cada tópico seja conciso, mas informativo. + +6. **Criar a Lista:** + + - Compile os 10 dados mais relevantes em itens de uma lista. + - Revise a lista para garantir clareza e relevância. + +**Saída Esperada:** + +Uma lista com 10 tópicos dos dados mais relevantes sobre LLMs de IA. + +--- + +**Tarefa Número 2: Revise o contexto obtido e expanda cada tópico em uma seção completa para um relatório** + +**Agente:** Analista de Relatórios de LLMs de IA + +**Objetivo do Agente:** Criar relatórios detalhados baseados na análise de dados e pesquisa sobre LLMs de IA + +**Resultado Esperado da Tarefa:** Um relatório completo com os principais tópicos, cada um com uma seção completa de informações. Formatado em markdown sem '```' + +**Ferramentas da Tarefa:** Nenhuma especificada + +**Ferramentas do Agente:** Nenhuma especificada + +**Plano Passo a Passo:** + +1. **Revisar os Tópicos:** + - Leia atentamente a lista dos 10 tópicos fornecida pelo Pesquisador Sênior de Dados de LLMs de IA. + +2. **Esboçar o Relatório:** + - Crie um esboço com cada tópico como título principal da seção. + - Planeje subseções sob cada título para abordar diferentes aspectos do tema. + +3. **Pesquisar Detalhes Adicionais:** + - Para cada tópico, conduza pesquisa adicional, se necessário, para reunir informações mais detalhadas. + - Busque estudos de caso, exemplos e dados estatísticos para embasar cada seção. + +4. **Redigir Seções Detalhadas:** + - Expanda cada tópico em uma seção abrangente. + - Certifique-se de que cada seção inclua introdução, explicação detalhada, exemplos e conclusão. + - Utilize formatação markdown para títulos, subtítulos, listas e ênfase. + +5. **Revisar e Editar:** + - Revise o relatório para garantir clareza, coerência e correção. + - Garanta uma sequência lógica de uma seção para a outra. + - Formate o relatório conforme os padrões markdown. + +6. **Finalizar o Relatório:** + - Certifique-se de que o relatório está completo, com todas as seções expandidas e detalhadas. + - Faça uma última verificação de formatação e ajustes necessários. + +**Saída Esperada:** +Um relatório completo com os principais tópicos, cada um com uma seção cheia de informações. Formatado em markdown sem '```'. +``` + \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/concepts/processes.mdx b/docs/v1.15.13/pt-BR/concepts/processes.mdx new file mode 100644 index 0000000000..c92f34c8fb --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/processes.mdx @@ -0,0 +1,66 @@ +--- +title: Processos +description: Guia detalhado sobre o gerenciamento de fluxos de trabalho através de processos no CrewAI, com detalhes de implementação atualizados. +icon: bars-staggered +mode: "wide" +--- + +## Visão Geral + + + Processos orquestram a execução de tarefas por agentes, de maneira semelhante à gestão de projetos em equipes humanas. + Esses processos garantem que as tarefas sejam distribuídas e executadas de forma eficiente, alinhadas a uma estratégia predefinida. + + +## Implementações de Processos + +- **Sequencial**: Executa tarefas de forma sequencial, garantindo que as tarefas sejam concluídas em uma progressão ordenada. +- **Hierárquico**: Organiza tarefas em uma hierarquia gerencial, onde as tarefas são delegadas e executadas com base numa cadeia de comando estruturada. Um modelo de linguagem de gerente (`manager_llm`) ou um agente gerente personalizado (`manager_agent`) deve ser especificado na crew para habilitar o processo hierárquico, facilitando a criação e o gerenciamento de tarefas pelo gerente. + +## O Papel dos Processos no Trabalho em Equipe +Os processos permitem que agentes individuais atuem como uma unidade coesa, otimizando seus esforços para atingir objetivos comuns com eficiência e coerência. + +## Atribuindo Processos a uma Crew +Para atribuir um processo a uma crew, especifique o tipo de processo ao criar a crew para definir a estratégia de execução. Para um processo hierárquico, garanta a definição de `manager_llm` ou `manager_agent` para o agente gerente. + +```python +from crewai import Crew, Process + +# Exemplo: Criando uma crew com processo sequencial +crew = Crew( + agents=meus_agentes, + tasks=minhas_tarefas, + process=Process.sequential +) + +# Exemplo: Criando uma crew com processo hierárquico +# Certifique-se de fornecer um manager_llm ou manager_agent +crew = Crew( + agents=meus_agentes, + tasks=minhas_tarefas, + process=Process.hierarchical, + manager_llm="gpt-4o" + # ou + # manager_agent=meu_agente_gerente +) +``` +**Nota:** Certifique-se de que `meus_agentes` e `minhas_tarefas` estejam definidos antes de criar o objeto `Crew`, e para o processo hierárquico, é necessário também fornecer o `manager_llm` ou `manager_agent`. + +## Processo Sequencial + +Este método reflete fluxos de trabalho dinâmicos de equipes, progredindo nas tarefas de maneira cuidadosa e sistemática. A execução das tarefas segue a ordem preestabelecida na lista de tarefas, com a saída de uma tarefa servindo de contexto para a próxima. + +Para personalizar o contexto das tarefas, utilize o parâmetro `context` na classe `Task` para especificar as saídas que devem ser usadas como contexto para as tarefas subsequentes. + +## Processo Hierárquico + +Emulando uma hierarquia corporativa, o CrewAI permite especificar um agente gerente personalizado ou criar um automaticamente, exigindo a especificação de um modelo de linguagem de gerente (`manager_llm`). Esse agente supervisiona a execução das tarefas, incluindo planejamento, delegação e validação. As tarefas não são pré-atribuídas; o gerente aloca tarefas aos agentes com base em suas capacidades, revisa as saídas e avalia a conclusão das tarefas. + +## Classe Process: Visão Detalhada + +A classe `Process` é implementada como uma enumeração (`Enum`), garantindo segurança de tipo e restringindo os valores de processos aos tipos definidos (`sequential`, `hierarchical`). + +## Conclusão + +A colaboração estruturada possibilitada pelos processos dentro do CrewAI é fundamental para permitir o trabalho em equipe sistemático entre agentes. +Esta documentação foi atualizada para refletir os mais recentes recursos e melhorias, garantindo que os usuários tenham acesso às informações mais atuais e abrangentes. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/concepts/production-architecture.mdx b/docs/v1.15.13/pt-BR/concepts/production-architecture.mdx new file mode 100644 index 0000000000..1cbcb804bc --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/production-architecture.mdx @@ -0,0 +1,162 @@ +--- +title: Arquitetura de Produção +description: Melhores práticas para construir aplicações de IA prontas para produção com CrewAI +icon: server +mode: "wide" +--- + +# A Mentalidade Flow-First + +Ao construir aplicações de IA de produção com CrewAI, **recomendamos começar com um Flow**. + +Embora seja possível executar Crews ou Agentes individuais, envolvê-los em um Flow fornece a estrutura necessária para uma aplicação robusta e escalável. + +## Por que Flows? + +1. **Gerenciamento de Estado**: Flows fornecem uma maneira integrada de gerenciar o estado em diferentes etapas da sua aplicação. Isso é crucial para passar dados entre Crews, manter o contexto e lidar com entradas do usuário. +2. **Controle**: Flows permitem definir caminhos de execução precisos, incluindo loops, condicionais e lógica de ramificação. Isso é essencial para lidar com casos extremos e garantir que sua aplicação se comporte de maneira previsível. +3. **Observabilidade**: Flows fornecem uma estrutura clara que facilita o rastreamento da execução, a depuração de problemas e o monitoramento do desempenho. Recomendamos o uso do [CrewAI Tracing](/pt-BR/observability/tracing) para insights detalhados. Basta executar `crewai login` para habilitar recursos de observabilidade gratuitos. + +## A Arquitetura + +Uma aplicação CrewAI de produção típica se parece com isso: + +```mermaid +graph TD + Start((Início)) --> Flow[Orquestrador de Flow] + Flow --> State{Gerenciamento de Estado} + State --> Step1[Etapa 1: Coleta de Dados] + Step1 --> Crew1[Crew de Pesquisa] + Crew1 --> State + State --> Step2{Verificação de Condição} + Step2 -- "Válido" --> Step3[Etapa 3: Execução] + Step3 --> Crew2[Crew de Ação] + Step2 -- "Inválido" --> End((Fim)) + Crew2 --> End +``` + +### 1. A Classe Flow +Sua classe `Flow` é o ponto de entrada. Ela define o esquema de estado e os métodos que executam sua lógica. + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class AppState(BaseModel): + user_input: str = "" + research_results: str = "" + final_report: str = "" + +class ProductionFlow(Flow[AppState]): + @start() + def gather_input(self): + # ... lógica para obter entrada ... + pass + + @listen(gather_input) + def run_research_crew(self): + # ... acionar um Crew ... + pass +``` + +### 2. Gerenciamento de Estado +Use modelos Pydantic para definir seu estado. Isso garante a segurança de tipos e deixa claro quais dados estão disponíveis em cada etapa. + +- **Mantenha o mínimo**: Armazene apenas o que você precisa persistir entre as etapas. +- **Use dados estruturados**: Evite dicionários não estruturados quando possível. + +### 3. Crews como Unidades de Trabalho +Delegue tarefas complexas para Crews. Um Crew deve ser focado em um objetivo específico (por exemplo, "Pesquisar um tópico", "Escrever uma postagem no blog"). + +- **Não superengendre Crews**: Mantenha-os focados. +- **Passe o estado explicitamente**: Passe os dados necessários do estado do Flow para as entradas do Crew. + +```python + @listen(gather_input) + def run_research_crew(self): + crew = ResearchCrew() + result = crew.kickoff(inputs={"topic": self.state.user_input}) + self.state.research_results = result.raw +``` + +## Primitivas de Controle + +Aproveite as primitivas de controle do CrewAI para adicionar robustez e controle aos seus Crews. + +### 1. Task Guardrails +Use [Task Guardrails](/pt-BR/concepts/tasks#task-guardrails) para validar as saídas das tarefas antes que sejam aceitas. Isso garante que seus agentes produzam resultados de alta qualidade. + +```python +def validate_content(result: TaskOutput) -> Tuple[bool, Any]: + if len(result.raw) < 100: + return (False, "Content is too short. Please expand.") + return (True, result.raw) + +task = Task( + ..., + guardrail=validate_content +) +``` + +### 2. Saídas Estruturadas +Sempre use saídas estruturadas (`output_pydantic` ou `output_json`) ao passar dados entre tarefas ou para sua aplicação. Isso evita erros de análise e garante a segurança de tipos. + +```python +class ResearchResult(BaseModel): + summary: str + sources: List[str] + +task = Task( + ..., + output_pydantic=ResearchResult +) +``` + +### 3. LLM Hooks +Use [LLM Hooks](/pt-BR/learn/llm-hooks) para inspecionar ou modificar mensagens antes que elas sejam enviadas para o LLM, ou para higienizar respostas. + +```python +@before_llm_call +def log_request(context): + print(f"Agent {context.agent.role} is calling the LLM...") +``` + +## Padrões de Implantação + +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](https://docs-platform.crewai.com/platform/pt-BR/guides/deploy-to-amp) para começar. + +```bash +crewai deploy create +``` + +### Execução Assíncrona +Para tarefas de longa duração, use `kickoff_async` para evitar bloquear sua API. + +### Persistência +Use o decorador `@persist` para salvar o estado do seu Flow em um banco de dados. Isso permite retomar a execução se o processo falhar ou se você precisar esperar pela entrada humana. + +```python +@persist +class ProductionFlow(Flow[AppState]): + # ... +``` + +Por padrão, `@persist` retoma um flow quando `kickoff(inputs={"id": })` é informado, estendendo o mesmo histórico do `flow_uuid`. Para **forkar** um flow persistido em uma nova linhagem — hidratar o estado a partir de uma execução anterior mas escrever sob um novo `state.id` — passe `restore_from_state_id`: + +```python +flow.kickoff(restore_from_state_id="") +``` + +A nova execução recebe um novo `state.id` (auto-gerado, ou `inputs["id"]` se fixado), então suas escritas do `@persist` não estendem o histórico da origem. Combinar com `from_checkpoint` lança um `ValueError`; escolha uma única fonte de hidratação. + +## Resumo + +- **Comece com um Flow.** +- **Defina um Estado claro.** +- **Use Crews para tarefas complexas.** +- **Implante com uma API e persistência.** diff --git a/docs/v1.15.13/pt-BR/concepts/reasoning.mdx b/docs/v1.15.13/pt-BR/concepts/reasoning.mdx new file mode 100644 index 0000000000..e9e2d0f88b --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/reasoning.mdx @@ -0,0 +1,148 @@ +--- +title: Reasoning +description: "Aprenda como habilitar e usar o reasoning do agente para aprimorar a execução de tarefas." +icon: brain +mode: "wide" +--- + +## Visão Geral + +O reasoning do agente é um recurso que permite que agentes reflitam sobre uma tarefa e criem um plano antes da execução. Isso ajuda os agentes a abordarem tarefas de forma mais metódica e garante que estejam preparados para realizar o trabalho atribuído. + +## Uso + +Para habilitar o reasoning para um agente, basta definir `reasoning=True` ao criar o agente: + +```python +from crewai import Agent + +analista = Agent( + role="Analista de Dados", + goal="Analisar dados e fornecer insights", + backstory="Você é um analista de dados especialista.", + reasoning=True, + max_reasoning_attempts=3 # Opcional: Defina um limite de tentativas de reasoning +) +``` + +## Como Funciona + +Quando o reasoning está habilitado, antes de executar uma tarefa, o agente irá: + +1. Refletir sobre a tarefa e criar um plano detalhado +2. Avaliar se está pronto para executar a tarefa +3. Refinar o plano conforme necessário até estar pronto ou até o limite de max_reasoning_attempts ser atingido +4. Inserir o plano de reasoning na descrição da tarefa antes da execução + +Esse processo ajuda o agente a dividir tarefas complexas em etapas gerenciáveis e identificar potenciais desafios antes de começar. + +## Opções de Configuração + + + Ativa ou desativa o reasoning + + + + Número máximo de tentativas para refinar o plano antes de prosseguir com a execução. Se None (padrão), o agente continuará refinando até que esteja pronto. + + +## Exemplo + +Aqui está um exemplo completo: + +```python +from crewai import Agent, Task, Crew + +# Create an agent with reasoning enabled +analista = Agent( + role="Analista de Dados", + goal="Analisar dados e fornecer insights", + backstory="Você é um analista de dados especialista.", + reasoning=True, + max_reasoning_attempts=3 # Opcional: Defina um limite de tentativas de reasoning +) + +# Create a task +analysis_task = Task( + description="Analise os dados de vendas fornecidos e identifique as principais tendências.", + expected_output="Um relatório destacando as 3 principais tendências de vendas.", + agent=analista +) + +# Create a crew and run the task +crew = Crew(agents=[analista], tasks=[analysis_task]) +result = crew.kickoff() + +print(result) +``` + +## Tratamento de Erros + +O processo de reasoning foi projetado para ser robusto, com tratamento de erros integrado. Se ocorrer um erro durante o reasoning, o agente prosseguirá com a execução da tarefa sem o plano de reasoning. Isso garante que as tarefas ainda possam ser executadas mesmo que o processo de reasoning falhe. + +Veja como lidar com possíveis erros no seu código: + +```python +from crewai import Agent, Task +import logging + +# Set up logging to capture any reasoning errors +logging.basicConfig(level=logging.INFO) + +# Create an agent with reasoning enabled +agent = Agent( + role="Analista de Dados", + goal="Analisar dados e fornecer insights", + reasoning=True, + max_reasoning_attempts=3 +) + +# Create a task +task = Task( + description="Analise os dados de vendas fornecidos e identifique as principais tendências.", + expected_output="Um relatório destacando as 3 principais tendências de vendas.", + agent=agent +) + +# Execute the task +# If an error occurs during reasoning, it will be logged and execution will continue +result = agent.execute_task(task) +``` + +## Exemplo de Saída de reasoning + +Veja um exemplo de como pode ser um plano de reasoning para uma tarefa de análise de dados: + +``` +Task: Analise os dados de vendas fornecidos e identifique as principais tendências. + +Reasoning Plan: +I'll analyze the sales data to identify the top 3 trends. + +1. Understanding of the task: + I need to analyze sales data to identify key trends that would be valuable for business decision-making. + +2. Key steps I'll take: + - First, I'll examine the data structure to understand what fields are available + - Then I'll perform exploratory data analysis to identify patterns + - Next, I'll analyze sales by time periods to identify temporal trends + - I'll also analyze sales by product categories and customer segments + - Finally, I'll identify the top 3 most significant trends + +3. Approach to challenges: + - If the data has missing values, I'll decide whether to fill or filter them + - If the data has outliers, I'll investigate whether they're valid data points or errors + - If trends aren't immediately obvious, I'll apply statistical methods to uncover patterns + +4. Use of available tools: + - I'll use data analysis tools to explore and visualize the data + - I'll use statistical tools to identify significant patterns + - I'll use knowledge retrieval to access relevant information about sales analysis + +5. Expected outcome: + A concise report highlighting the top 3 sales trends with supporting evidence from the data. + +READY: I am ready to execute the task. +``` + +Esse plano de reasoning ajuda o agente a organizar sua abordagem para a tarefa, considerar possíveis desafios e garantir que entregará o resultado esperado. diff --git a/docs/v1.15.13/pt-BR/concepts/skills.mdx b/docs/v1.15.13/pt-BR/concepts/skills.mdx new file mode 100644 index 0000000000..09418ae651 --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/skills.mdx @@ -0,0 +1,373 @@ +--- +title: Skills +description: Pacotes de skills baseados em sistema de arquivos que injetam expertise de domínio e instruções nos prompts dos agentes. +icon: bolt +mode: "wide" +--- + +## Visão Geral + +Skills são diretórios autocontidos que fornecem aos agentes **instruções, diretrizes e material de referência específicos de domínio**. Cada skill é definida por um arquivo `SKILL.md` com frontmatter YAML e um corpo em markdown. + +Quando ativada, as instruções de uma skill são injetadas diretamente no prompt da tarefa do agente — dando ao agente expertise sem exigir alterações de código. + + +**Skills NÃO são ferramentas.** Este é o ponto de confusão mais comum. + +- **Skills** injetam *instruções e contexto* no prompt do agente. Elas dizem ao agente *como pensar* sobre um problema. +- **Ferramentas** dão ao agente *funções chamáveis* para tomar ações (buscar, ler arquivos, chamar APIs). + +Frequentemente você precisa de **ambos**: skills para expertise, ferramentas para ação. Eles são configurados independentemente e se complementam. + + +--- + +## Início Rápido + +### 1. Crie uma Skill com a CLI + +A CLI é a forma suportada de criar uma skill — ela gera a estrutura de diretórios e um `SKILL.md` válido para você: + +```shell Terminal +crewai skill create code-review +``` + +Dentro de um projeto de crew (onde o `pyproject.toml` está) isso cria `./skills/code-review/`; fora de um projeto, cria `./code-review/` no diretório atual (você pode forçar esse comportamento com `--no-project`): + +``` +skills/ +└── code-review/ + ├── SKILL.md # Obrigatório — instruções (template pré-preenchido) + ├── references/ # Opcional — documentos de referência + ├── scripts/ # Opcional — scripts executáveis + └── assets/ # Opcional — arquivos estáticos +``` + +### 2. Escreva seu SKILL.md + +```markdown +--- +name: code-review +description: Guidelines for conducting thorough code reviews with focus on security and performance. +metadata: + author: your-team + version: "1.0" +--- + +## Diretrizes de Code Review + +Ao revisar código, siga esta checklist: + +1. **Segurança**: Verifique vulnerabilidades de injeção, bypasses de autenticação e exposição de dados +2. **Performance**: Procure por queries N+1, alocações desnecessárias e chamadas bloqueantes +3. **Legibilidade**: Garanta nomenclatura clara, comentários apropriados e estilo consistente +4. **Testes**: Verifique cobertura adequada de testes para novas funcionalidades + +### Níveis de Severidade +- **Crítico**: Vulnerabilidades de segurança, riscos de perda de dados → bloquear merge +- **Major**: Problemas de performance, erros de lógica → solicitar alterações +- **Minor**: Questões de estilo, sugestões de nomenclatura → aprovar com comentários +``` + +### 3. Anexe a um Agente + +```python +from crewai import Agent +from crewai_tools import GithubSearchTool, FileReadTool + +reviewer = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["./skills"], # Injeta diretrizes de revisão + tools=[GithubSearchTool(), FileReadTool()], # Permite ao agente ler código +) +``` + +O agente agora tem tanto **expertise** (da skill) quanto **capacidades** (das ferramentas). + +--- + +## Skills + Ferramentas: Trabalhando Juntos + +Aqui estão padrões comuns mostrando como skills e ferramentas se complementam: + +### Padrão 1: Apenas Skills (Expertise de Domínio, Sem Ações Necessárias) + +Use quando o agente precisa de instruções específicas mas não precisa chamar serviços externos: + +```python +agent = Agent( + role="Technical Writer", + goal="Write clear API documentation", + backstory="Expert technical writer", + skills=["./skills/api-docs-style"], # Diretrizes e templates de escrita + # Sem ferramentas necessárias — agente escreve baseado no contexto fornecido +) +``` + +### Padrão 2: Apenas Ferramentas (Ações, Sem Expertise Especial) + +Use quando o agente precisa tomar ações mas não precisa de instruções específicas de domínio: + +```python +from crewai_tools import SerperDevTool, ScrapeWebsiteTool + +agent = Agent( + role="Web Researcher", + goal="Find information about a topic", + backstory="Skilled at finding information online", + tools=[SerperDevTool(), ScrapeWebsiteTool()], # Pode buscar e extrair dados + # Sem skills necessárias — pesquisa geral não precisa de diretrizes especiais +) +``` + +### Padrão 3: Skills + Ferramentas (Expertise E Ações) + +O padrão mais comum no mundo real. A skill fornece *como* abordar o trabalho; ferramentas fornecem *o que* o agente pode fazer: + +```python +from crewai_tools import SerperDevTool, FileReadTool, CodeInterpreterTool + +analyst = Agent( + role="Security Analyst", + goal="Audit infrastructure for vulnerabilities", + backstory="Expert in cloud security and compliance", + skills=["./skills/security-audit"], # Metodologia e checklists de auditoria + tools=[ + SerperDevTool(), # Pesquisar vulnerabilidades conhecidas + FileReadTool(), # Ler arquivos de configuração + CodeInterpreterTool(), # Executar scripts de análise + ], +) +``` + +### Padrão 4: Skills + MCPs + +Skills funcionam junto com servidores MCP da mesma forma que com ferramentas: + +```python +agent = Agent( + role="Data Analyst", + goal="Analyze customer data and generate reports", + backstory="Expert data analyst with strong statistical background", + skills=["./skills/data-analysis"], # Metodologia de análise + mcps=["https://data-warehouse.example.com/sse"], # Acesso remoto a dados +) +``` + +### Padrão 5: Skills + Apps + +Skills podem guiar como um agente usa integrações de plataforma: + +```python +agent = Agent( + role="Customer Support Agent", + goal="Respond to customer inquiries professionally", + backstory="Experienced support representative", + skills=["./skills/support-playbook"], # Templates de resposta e regras de escalação + apps=["gmail", "zendesk"], # Pode enviar emails e atualizar tickets +) +``` + +--- + +## Criando, Publicando e Instalando Skills + +Skills têm um ciclo de vida completo gerenciado pela CLI: **crie-as com `crewai skill create`, publique-as com `crewai skill publish`** — criar diretórios à mão funciona para experimentos locais, mas a CLI é o fluxo de trabalho pretendido e mantém a estrutura e o frontmatter da sua skill válidos. + +### Criar + +```shell Terminal +crewai skill create my-skill +``` + +Gera o diretório (em `./skills/` dentro de um projeto de crew) com um `SKILL.md` de template, além dos diretórios vazios `scripts/`, `references/` e `assets/`. Edite o `SKILL.md` para definir as instruções. + +### Publicar + +Execute de dentro do diretório da skill (onde o `SKILL.md` está): + +```shell Terminal +cd skills/my-skill +crewai skill publish +``` + +A publicação lê `name`, `description` e `metadata.version` do frontmatter do `SKILL.md` e envia a skill para o registro da CrewAI. **Skills publicadas são sempre escopadas à sua organização** — assim como ferramentas, apenas membros da organização que publicou podem vê-las e instalá-las; não há visibilidade pública. Flags úteis: + +| Flag | Efeito | +| :--- | :--- | +| `--org ` | Publica sob uma organização específica (sobrepõe as configurações). | +| `--force` | Pula a validação de estado do git (alterações não commitadas, etc.). | + +### Instalar + +Instale uma skill publicada pela sua referência `@org/name`: + +```shell Terminal +crewai skill install @acme/code-review +``` + +Dentro de um projeto de crew, a skill é colocada em `./skills/{name}/`; fora de um projeto, vai para o cache compartilhado em `~/.crewai/skills/{org}/{name}/`. + +Agentes também podem referenciar skills do registro diretamente — elas são resolvidas a partir do cache local (ou do diretório `skills/` do projeto) em tempo de execução: + +```python +agent = Agent( + role="Senior Code Reviewer", + goal="Review pull requests for quality and security issues", + backstory="Staff engineer with expertise in secure coding practices.", + skills=["@acme/code-review"], # registry ref, resolved locally +) +``` + +### Listar + +```shell Terminal +crewai skill list +``` + +Mostra as skills instaladas tanto do diretório `./skills/` do projeto quanto do cache global, com suas versões e caminhos. + +--- + +## Skills no Nível do Crew + +Skills podem ser definidas no crew para aplicar a **todos os agentes**: + +```python +from crewai import Crew + +crew = Crew( + agents=[researcher, writer, reviewer], + tasks=[research_task, write_task, review_task], + skills=["./skills"], # Todos os agentes recebem essas skills +) +``` + +Skills no nível do agente têm prioridade — se a mesma skill é descoberta em ambos os níveis, a versão do agente é usada. + +--- + +## Formato do SKILL.md + +```markdown +--- +name: my-skill +description: Descrição curta do que esta skill faz e quando usá-la. +license: Apache-2.0 # opcional +compatibility: crewai>=0.1.0 # opcional +metadata: # opcional + author: your-name + version: "1.0" +allowed-tools: web-search file-read # opcional, experimental +--- + +Instruções para o agente vão aqui. Este corpo em markdown é injetado +no prompt do agente quando a skill é ativada. +``` + +### Campos do Frontmatter + +| Campo | Obrigatório | Descrição | +| :-------------- | :---------- | :----------------------------------------------------------------------- | +| `name` | Sim | 1–64 chars. Alfanumérico minúsculo e hifens. Deve corresponder ao nome do diretório. | +| `description` | Sim | 1–1024 chars. Descreve o que a skill faz e quando usá-la. | +| `license` | Não | Nome da licença ou referência a um arquivo de licença incluído. | +| `compatibility` | Não | Máx 500 chars. Requisitos de ambiente (produtos, pacotes, rede). | +| `metadata` | Não | Mapeamento arbitrário de chave-valor string. | +| `allowed-tools` | Não | Lista de ferramentas pré-aprovadas delimitada por espaços. Experimental. | + +--- + +## Estrutura de Diretório + +``` +my-skill/ +├── SKILL.md # Obrigatório — frontmatter + instruções +├── scripts/ # Opcional — scripts executáveis +├── references/ # Opcional — documentos de referência +└── assets/ # Opcional — arquivos estáticos (configs, dados) +``` + +O nome do diretório deve corresponder ao campo `name` no `SKILL.md`. Os diretórios `scripts/`, `references/` e `assets/` estão disponíveis no `path` da skill para agentes que precisam referenciar arquivos diretamente. + +--- + +## Skills Pré-carregadas + +Para mais controle, você pode descobrir e ativar skills programaticamente: + +```python +from pathlib import Path +from crewai.skills import discover_skills, activate_skill + +# Descobrir todas as skills em um diretório +skills = discover_skills(Path("./skills")) + +# Ativá-las (carrega o corpo completo do SKILL.md) +activated = [activate_skill(s) for s in skills] + +# Passar para um agente +agent = Agent( + role="Researcher", + goal="Find relevant information", + backstory="An expert researcher.", + skills=activated, +) +``` + +--- + +## Como as Skills São Carregadas + +Skills usam **divulgação progressiva** — carregando apenas o necessário em cada estágio: + +| Estágio | O que é carregado | Quando | +| :--------- | :------------------------------------ | :------------------ | +| Descoberta | Nome, descrição, campos do frontmatter | `discover_skills()` | +| Ativação | Texto completo do corpo do SKILL.md | `activate_skill()` | + +Durante a execução normal do agente (passando caminhos de diretório via `skills=["./skills"]`), skills são automaticamente descobertas e ativadas. O carregamento progressivo só importa quando usando a API programática. + +--- + +## Skills vs Knowledge + +Tanto skills quanto knowledge modificam o prompt do agente, mas servem propósitos diferentes: + +| Aspecto | Skills | Knowledge | +| :--- | :--- | :--- | +| **O que fornece** | Instruções, procedimentos, diretrizes | Fatos, dados, informações | +| **Como é armazenado** | Arquivos Markdown (SKILL.md) | Embarcado em banco vetorial (ChromaDB) | +| **Como é recuperado** | Corpo inteiro injetado no prompt | Busca semântica encontra trechos relevantes | +| **Melhor para** | Metodologia, checklists, guias de estilo | Documentos da empresa, info de produto, dados de referência | +| **Definido via** | `skills=["./skills"]` | `knowledge_sources=[source]` | + +**Regra prática:** Se o agente precisa seguir um *processo*, use uma skill. Se o agente precisa consultar *dados*, use knowledge. + +--- + +## Perguntas Frequentes + + + + Depende do seu caso de uso. Skills e ferramentas são **independentes** — você pode usar qualquer um, ambos ou nenhum. + + - **Apenas skills**: Quando o agente precisa de expertise mas não de ações externas (ex: escrever com diretrizes de estilo) + - **Apenas ferramentas**: Quando o agente precisa de ações mas não de metodologia especial (ex: busca simples na web) + - **Ambos**: Quando o agente precisa de expertise E ações (ex: auditoria de segurança com checklists específicas E capacidade de escanear código) + + + + **Não.** O campo `allowed-tools` no SKILL.md é apenas metadado experimental — ele não provisiona nem injeta nenhuma ferramenta. Você deve sempre definir ferramentas separadamente via `tools=[]`, `mcps=[]` ou `apps=[]`. + + + + A skill no nível do agente tem prioridade. Skills são deduplicadas por nome — as skills do agente são processadas primeiro, então se o mesmo nome de skill aparece em ambos os níveis, a versão do agente é usada. + + + + Há um aviso suave em 50.000 caracteres, mas sem limite rígido. Mantenha skills focadas e concisas para melhores resultados — injeções de prompt muito grandes podem diluir a atenção do agente. + + diff --git a/docs/v1.15.13/pt-BR/concepts/tasks.mdx b/docs/v1.15.13/pt-BR/concepts/tasks.mdx new file mode 100644 index 0000000000..29a0120839 --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/tasks.mdx @@ -0,0 +1,1105 @@ +--- +title: Tarefas +description: Guia detalhado sobre como gerenciar e criar tarefas dentro do framework CrewAI. +icon: list-check +mode: "wide" +--- + +## Visão Geral + +No framework CrewAI, uma `Task` (Tarefa) é uma atribuição específica executada por um `Agent` (Agente). + +As tarefas fornecem todos os detalhes necessários para sua execução, como descrição, agente responsável, ferramentas exigidas e mais, facilitando uma ampla gama de complexidades de ação. + +As tarefas dentro do CrewAI podem ser colaborativas, exigindo que múltiplos agentes trabalhem juntos. Isso é gerenciado por meio das propriedades da tarefa e orquestrado pelo processo do Crew, potencializando o trabalho em equipe e a eficiência. + + +O CrewAI AMP inclui um Construtor Visual de Tarefas no Crew Studio, que simplifica a criação e o encadeamento de tarefas complexas. Projete seus fluxos de tarefas visualmente e teste-os em tempo real sem necessidade de escrever código. + +![Task Builder Screenshot](/images/enterprise/crew-studio-interface.png) + +O Construtor Visual de Tarefas permite: + +- Criação de tarefas via arrastar-e-soltar +- Visualização de dependências e fluxo de tarefas +- Testes e validações em tempo real +- Fácil compartilhamento e colaboração + + +### Fluxo de Execução de Tarefas + +As tarefas podem ser executadas de duas maneiras: + +- **Sequencial**: As tarefas são executadas na ordem em que são definidas +- **Hierárquica**: As tarefas são atribuídas aos agentes com base em seus papéis e especialidades + +O fluxo de execução é definido ao criar o crew: + +```python Code +crew = Crew( + agents=[agent1, agent2], + tasks=[task1, task2], + process=Process.sequential # ou Process.hierarchical +) +``` + +## Atributos da Tarefa + +| Atributo | Parâmetros | Tipo | Descrição | +| :---------------------------------------- | :---------------------- | :-------------------------- | :------------------------------------------------------------------------------------------------------ | +| **Descrição** | `description` | `str` | Uma declaração clara e concisa do que a tarefa envolve. | +| **Saída Esperada** | `expected_output` | `str` | Uma descrição detalhada de como deve ser o resultado da tarefa concluída. | +| **Nome** _(opcional)_ | `name` | `Optional[str]` | Um identificador de nome para a tarefa. | +| **Agente** _(opcional)_ | `agent` | `Optional[BaseAgent]` | O agente responsável por executar a tarefa. | +| **Ferramentas** _(opcional)_ | `tools` | `List[BaseTool]` | As ferramentas/recursos que o agente pode usar para esta tarefa. | +| **Contexto** _(opcional)_ | `context` | `Optional[List["Task"]]` | Outras tarefas cujas saídas serão usadas como contexto para esta tarefa. | +| **Execução Assíncrona** _(opc.)_ | `async_execution` | `Optional[bool]` | Se a tarefa deve ser executada de forma assíncrona. O padrão é False. | +| **Input Humano** _(opcional)_ | `human_input` | `Optional[bool]` | Se a tarefa deve ter uma revisão humana da resposta final do agente. O padrão é False. | +| **Markdown** _(opcional)_ | `markdown` | `Optional[bool]` | Se a tarefa deve instruir o agente a retornar a resposta final formatada em Markdown. O padrão é False. | +| **Config** _(opcional)_ | `config` | `Optional[Dict[str, Any]]` | Parâmetros de configuração específicos da tarefa. | +| **Arquivo de Saída** _(opcional)_ | `output_file` | `Optional[str]` | Caminho do arquivo para armazenar a saída da tarefa. | +| **Criar Diretório** _(opcional)_ | `create_directory` | `Optional[bool]` | Se deve criar o diretório para output_file caso não exista. O padrão é True. | +| **Saída JSON** _(opcional)_ | `output_json` | `Optional[Type[BaseModel]]` | Um modelo Pydantic para estruturar a saída em JSON. | +| **Output Pydantic** _(opcional)_ | `output_pydantic` | `Optional[Type[BaseModel]]` | Um modelo Pydantic para a saída da tarefa. | +| **Callback** _(opcional)_ | `callback` | `Optional[Any]` | Função/objeto a ser executado após a conclusão da tarefa. | +| **Guardrail** _(opcional)_ | `guardrail` | `Optional[Callable]` | Função para validar a saída da tarefa antes de prosseguir para a próxima tarefa. | +| **Max Tentativas Guardrail** _(opcional)_ | `guardrail_max_retries` | `Optional[int]` | Número máximo de tentativas quando a validação do guardrail falha. Padrão é 3. | + +## Criando Tarefas + +Existem duas formas comuns de criar tarefas no CrewAI: usando **configuração JSONC (recomendado para novas crews)** ou definindo-as **diretamente no código**. + +### Configuração JSONC (Recomendado) + +Novos projetos criados com `crewai create crew ` definem tarefas no `crew.jsonc`. + +````jsonc crew.jsonc +{ + "name": "Research Crew", + "agents": ["researcher", "reporting_analyst"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research about {topic}.", + "expected_output": "A list of the most relevant information about {topic}.", + "agent": "researcher" + }, + { + "name": "reporting_task", + "description": "Review the research and expand it into a detailed report.", + "expected_output": "A polished markdown report.", + "agent": "reporting_analyst", + "context": ["research_task"], + "markdown": true, + "output_file": "report.md" + } + ], + "inputs": { + "topic": "AI Agents" + } +} +```` + +Cada tarefa precisa de `description` e `expected_output`. O valor de `agent` deve corresponder a um agente listado em `agents`. `context` referencia nomes de tarefas anteriores; referências futuras são rejeitadas. Campos comuns incluem `name`, `agent`, `context`, `output_file`, `tools`, `human_input`, `async_execution`, `guardrail`, `guardrails`, `markdown`, `output_json`, `output_pydantic` e `response_model`. + +### Configuração YAML Clássica + +Projetos clássicos criados com `crewai create crew --classic` usam `config/tasks.yaml` e uma classe `@CrewBase` em `crew.py`. + +A configuração YAML continua suportada para projetos existentes em Python/YAML e para equipes que preferem definir tarefas a partir de uma classe `@CrewBase`. + +Após criar um projeto clássico, navegue até o arquivo `src//config/tasks.yaml` e modifique o template para refletir os requisitos específicos das tarefas. + + +Variáveis em seus arquivos YAML (como `{topic}`) serão substituídas por valores vindos dos seus inputs ao executar o crew: +```python Code +crew.kickoff(inputs={'topic': 'AI Agents'}) +``` + + +Veja um exemplo de configuração de tarefas usando YAML: + +````yaml tasks.yaml +research_task: + description: > + Realize uma pesquisa detalhada sobre {topic} + Certifique-se de encontrar informações interessantes e relevantes considerando + que o ano atual é 2025. + expected_output: > + Uma lista com 10 tópicos em bullet points das informações mais relevantes sobre {topic} + agent: researcher + +reporting_task: + description: > + Revise o contexto recebido e expanda cada tópico em uma seção completa de um relatório. + Certifique-se de que o relatório seja detalhado e contenha todas as informações relevantes. + expected_output: > + Um relatório completo com os principais tópicos, cada um com uma seção cheia de informações. + Formatado em markdown sem '```' + agent: reporting_analyst + markdown: true + output_file: report.md +```` + +Para usar essa configuração YAML em seu código, crie uma classe crew que herda de `CrewBase`: + +```python crew.py +# src//crew.py + +from crewai import Agent, Crew, Process, Task +from crewai.project import CrewBase, agent, crew, task +from crewai_tools import SerperDevTool + +@CrewBase +class LatestAiDevelopmentCrew(): + """LatestAiDevelopment crew""" + + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], # type: ignore[index] + verbose=True, + tools=[SerperDevTool()] + ) + + @agent + def reporting_analyst(self) -> Agent: + return Agent( + config=self.agents_config['reporting_analyst'], # type: ignore[index] + verbose=True + ) + + @task + def research_task(self) -> Task: + return Task( + config=self.tasks_config['research_task'] # type: ignore[index] + ) + + @task + def reporting_task(self) -> Task: + return Task( + config=self.tasks_config['reporting_task'] # type: ignore[index] + ) + + @crew + def crew(self) -> Crew: + return Crew( + agents=[ + self.researcher(), + self.reporting_analyst() + ], + tasks=[ + self.research_task(), + self.reporting_task() + ], + process=Process.sequential + ) +``` + + + Os nomes usados em seus arquivos YAML (`agents.yaml` e `tasks.yaml`) devem + corresponder aos nomes dos métodos no seu código Python. + + +### Definição Direta no Código (Alternativa) + +Alternativamente, você pode definir tarefas diretamente no seu código sem usar configuração YAML: + +```python task.py +from crewai import Task + +research_task = Task( + description=""" + Realize uma pesquisa detalhada sobre AI Agents. + Certifique-se de encontrar informações interessantes e relevantes considerando + que o ano atual é 2025. + """, + expected_output=""" + Uma lista com 10 tópicos em bullet points das informações mais relevantes sobre AI Agents + """, + agent=researcher +) + +reporting_task = Task( + description=""" + Revise o contexto recebido e expanda cada tópico em uma seção completa de um relatório. + Certifique-se de que o relatório seja detalhado e contenha todas as informações relevantes. + """, + expected_output=""" + Um relatório completo com os principais tópicos, cada um com uma seção cheia de informações. + """, + agent=reporting_analyst, + markdown=True, # Ativa formatação markdown para a saída final + output_file="report.md" +) +``` + + + Especifique diretamente um `agent` para a tarefa ou permita que o processo + `hierarchical` do CrewAI decida com base em papéis, disponibilidade, etc. + + +## Saída da Tarefa + +Compreender as saídas das tarefas é crucial para construir fluxos de trabalho de IA eficazes. O CrewAI oferece uma maneira estruturada de lidar com resultados usando a classe `TaskOutput`, que suporta múltiplos formatos de saída e pode ser facilmente passada entre tarefas. + +A saída de uma tarefa no framework CrewAI é encapsulada na classe `TaskOutput`. Essa classe fornece uma maneira estruturada de acessar os resultados da tarefa, incluindo vários formatos como saída bruta, JSON e modelos Pydantic. + +Por padrão, o `TaskOutput` incluirá apenas a saída `raw`. Um `TaskOutput` só terá as saídas `pydantic` ou `json_dict` se o objeto original da `Task` estiver configurado com `output_pydantic` ou `output_json`, respectivamente. + +### Atributos do Task Output + +| Atributo | Parâmetros | Tipo | Descrição | +| :---------------- | :-------------- | :------------------------- | :---------------------------------------------------------------------------------------- | +| **Description** | `description` | `str` | Descrição da tarefa. | +| **Summary** | `summary` | `Optional[str]` | Resumo da tarefa, gerado automaticamente a partir das primeiras 10 palavras da descrição. | +| **Raw** | `raw` | `str` | Saída bruta da tarefa. Este é o formato padrão da saída. | +| **Pydantic** | `pydantic` | `Optional[BaseModel]` | Objeto modelo Pydantic representando a saída da tarefa de forma estruturada. | +| **JSON Dict** | `json_dict` | `Optional[Dict[str, Any]]` | Dicionário representando a saída da tarefa em JSON. | +| **Agent** | `agent` | `str` | O agente que executou a tarefa. | +| **Output Format** | `output_format` | `OutputFormat` | O formato da saída da tarefa, podendo ser RAW, JSON e Pydantic. O padrão é RAW. | + +### Métodos e Propriedades da Tarefa + +| Método/Propriedade | Descrição | +| :----------------- | :--------------------------------------------------------------------------------------------------- | +| **json** | Retorna a representação da saída da tarefa em JSON como string, se o formato de saída for JSON. | +| **to_dict** | Converte as saídas JSON e Pydantic para um dicionário. | +| **str** | Retorna a representação em string da saída da tarefa, priorizando Pydantic, depois JSON, depois raw. | + +### Acessando Saídas das Tarefas + +Uma vez que a tarefa é executada, sua saída pode ser acessada pelo atributo `output` do objeto `Task`. A classe `TaskOutput` oferece várias formas de interagir e apresentar esse resultado. + +#### Exemplo + +```python Code +# Exemplo de tarefa +task = Task( + description='Encontre e resuma as últimas notícias de IA', + expected_output='Uma lista em bullet points com o resumo das 5 notícias mais importantes de IA', + agent=research_agent, + tools=[search_tool] +) + +# Executando o crew +crew = Crew( + agents=[research_agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() + +# Acessando a saída da tarefa +task_output = task.output + +print(f"Descrição da Tarefa: {task_output.description}") +print(f"Resumo da Tarefa: {task_output.summary}") +print(f"Saída Bruta: {task_output.raw}") +if task_output.json_dict: + print(f"Saída em JSON: {json.dumps(task_output.json_dict, indent=2)}") +if task_output.pydantic: + print(f"Saída Pydantic: {task_output.pydantic}") +``` + +## Formatação Markdown na Saída + +O parâmetro `markdown` ativa a formatação automática em markdown na saída das tarefas. Quando configurado como `True`, a tarefa irá instruir o agente a formatar a resposta final utilizando a sintaxe Markdown correta. + +### Usando Formatação Markdown + +```python Code +# Exemplo de tarefa com formatação markdown ativada +formatted_task = Task( + description="Crie um relatório abrangente sobre tendências em IA", + expected_output="Um relatório bem estruturado com títulos, seções e bullet points", + agent=reporter_agent, + markdown=True # Habilita a formatação automática em markdown +) +``` + +Quando `markdown=True`, o agente recebe instruções extras para formatar a saída usando: + +- `#` para títulos +- `**texto**` para negrito +- `*texto*` para itálico +- `-` ou `*` para bullet points +- `` `código` `` para código inline +- ` `linguagem ``` para blocos de código + +### Configuração YAML com Markdown + +```yaml tasks.yaml +analysis_task: + description: > + Analise os dados de mercado e crie um relatório detalhado + expected_output: > + Uma análise completa com gráficos e descobertas-chave + agent: analyst + markdown: true # Habilita formatação em markdown + output_file: analysis.md +``` + +### Benefícios da Saída Markdown + +- **Formatação Consistente**: Garante que todas as saídas sigam as convenções de markdown +- **Maior Legibilidade**: Conteúdo estruturado com títulos, listas e ênfase +- **Pronto para Documentação**: A saída pode ser usada diretamente em sistemas de documentação +- **Compatibilidade Multi-plataforma**: Markdown é universalmente suportado + + + As instruções de formatação em markdown são adicionadas automaticamente ao + prompt da tarefa quando `markdown=True`, então não é necessário detalhar os + requisitos de formatação na descrição da tarefa. + + +## Dependências de Tarefas e Contexto + +As tarefas podem depender da saída de outras tarefas utilizando o atributo `context`. Por exemplo: + +```python Code +research_task = Task( + description="Pesquise os últimos avanços em IA", + expected_output="Uma lista de avanços recentes em IA", + agent=researcher +) + +analysis_task = Task( + description="Analise os achados da pesquisa e identifique as tendências principais", + expected_output="Relatório de análise das tendências em IA", + agent=analyst, + context=[research_task] # Esta tarefa aguardará a conclusão da research_task +) +``` + +## Guardrails em Tarefas + +Guardrails (trilhas de proteção) de tarefas fornecem uma maneira de validar e transformar as saídas das tarefas antes que elas sejam passadas para a próxima tarefa. Esse recurso assegura a qualidade dos dados e oferece feedback aos agentes quando sua saída não atende a critérios específicos. + +Guardrails são implementados como funções Python que contêm lógica de validação customizada, proporcionando controle total sobre o processo de validação e garantindo resultados confiáveis e determinísticos. + +### Guardrails Baseados em Função + +Para adicionar um guardrail baseado em função a uma tarefa, forneça uma função de validação por meio do parâmetro `guardrail`: + +```python Code +from typing import Tuple, Union, Dict, Any +from crewai import TaskOutput + +def validate_blog_content(result: TaskOutput) -> Tuple[bool, Any]: + """Valida se o conteúdo do blog atende aos requisitos.""" + try: + # Verifica a contagem de palavras + word_count = len(result.split()) + if word_count > 200: + return (False, "O conteúdo do blog excede 200 palavras") + + # Lógica adicional de validação aqui + return (True, result.strip()) + except Exception as e: + return (False, "Erro inesperado durante a validação") + +blog_task = Task( + description="Escreva um post de blog sobre IA", + expected_output="Um post de blog com menos de 200 palavras", + agent=blog_agent, + guardrail=validate_blog_content # Adiciona a função guardrail +) +``` + +### Requisitos da Função Guardrail + +1. **Assinatura da Função**: + + - Deve aceitar exatamente um parâmetro (a saída da tarefa) + - Deve retornar uma tupla `(bool, Any)` + - Type hints são recomendados, mas opcionais + +2. **Valores de Retorno**: + - Em caso de sucesso: retorna uma tupla `(True, resultado_validado)` + - Em caso de falha: retorna uma tupla `(False, "mensagem de erro explicando a falha")` + +### Melhores Práticas de Tratamento de Erros + +1. **Respostas de Erro Estruturadas**: + +```python Code +from crewai import TaskOutput, LLMGuardrail + +def validate_with_context(result: TaskOutput) -> Tuple[bool, Any]: + try: + # Lógica principal de validação + validated_data = perform_validation(result) + return (True, validated_data) + except ValidationError as e: + return (False, f"ERRO_DE_VALIDACAO: {str(e)}") + except Exception as e: + return (False, str(e)) +``` + +2. **Categorias de Erro**: + + - Use códigos de erro específicos + - Inclua contexto relevante + - Forneça feedback acionável + +3. **Cadeia de Validação**: + +```python Code +from typing import Any, Dict, List, Tuple, Union +from crewai import TaskOutput + +def complex_validation(result: TaskOutput) -> Tuple[bool, Any]: + """Encadeia múltiplas etapas de validação.""" + # Passo 1: Validação básica + if not result: + return (False, "Resultado vazio") + + # Passo 2: Validação de conteúdo + try: + validated = validate_content(result) + if not validated: + return (False, "Conteúdo inválido") + + # Passo 3: Validação de formato + formatted = format_output(validated) + return (True, formatted) + except Exception as e: + return (False, str(e)) +``` + +### Tratamento dos Resultados do Guardrail + +Quando um guardrail retorna `(False, erro)`: + +1. O erro é enviado de volta para o agente +2. O agente tenta corrigir o problema +3. O processo se repete até: + - O guardrail retornar `(True, resultado)` + - O número máximo de tentativas ser atingido + +Exemplo com manipulação de tentativas: + +```python Code +from typing import Optional, Tuple, Union +from crewai import TaskOutput, Task + +def validate_json_output(result: TaskOutput) -> Tuple[bool, Any]: + """Valida e faz o parsing da saída como JSON.""" + try: + # Tenta realizar o parsing como JSON + data = json.loads(result) + return (True, data) + except json.JSONDecodeError as e: + return (False, "Formato JSON inválido") + +task = Task( + description="Gere um relatório em JSON", + expected_output="Um objeto JSON válido", + agent=analyst, + guardrail=validate_json_output, + guardrail_max_retries=3 # Limite de tentativas +) +``` + +## Obtendo Saídas Estruturadas e Consistentes das Tarefas + + + É importante também observar que a saída da última tarefa de um crew se torna + a saída final do próprio crew. + + +### Usando `output_pydantic` + +A propriedade `output_pydantic` permite que você defina um modelo Pydantic que a saída da tarefa deve seguir. Isso garante que a saída seja não apenas estruturada, mas também validada de acordo com o modelo. + +Veja um exemplo de uso do output_pydantic: + +```python Code +import json + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + + +class Blog(BaseModel): + title: str + content: str + + +blog_agent = Agent( + role="Blog Content Generator Agent", + goal="Gerar um título e conteúdo para blog", + backstory="""Você é um especialista em criação de conteúdo, habilidoso em escrever posts de blogs engajadores e informativos.""", + verbose=False, + allow_delegation=False, + llm="gpt-4o", +) + +task1 = Task( + description="""Crie um título e conteúdo para blog sobre um tópico. Certifique-se de que o conteúdo tenha menos de 200 palavras.""", + expected_output="Um título atraente e um conteúdo bem escrito para blog.", + agent=blog_agent, + output_pydantic=Blog, +) + +# Instanciando o crew com processo sequencial +crew = Crew( + agents=[blog_agent], + tasks=[task1], + verbose=True, + process=Process.sequential, +) + +result = crew.kickoff() + +# Opção 1: Acessando propriedades via indexação de dicionário +print("Acessando propriedades - Opção 1") +title = result["title"] +content = result["content"] +print("Título:", title) +print("Conteúdo:", content) + +# Opção 2: Acessando diretamente do modelo Pydantic +print("Acessando propriedades - Opção 2") +title = result.pydantic.title +content = result.pydantic.content +print("Título:", title) +print("Conteúdo:", content) + +# Opção 3: Usando o método to_dict() +print("Acessando propriedades - Opção 3") +output_dict = result.to_dict() +title = output_dict["title"] +content = output_dict["content"] +print("Título:", title) +print("Conteúdo:", content) + +# Opção 4: Imprimindo o objeto Blog inteiro +print("Acessando propriedades - Opção 5") +print("Blog:", result) + +``` + +Neste exemplo: + +- Um modelo Pydantic Blog é definido com os campos title e content. +- A tarefa task1 utiliza a propriedade output_pydantic para especificar que sua saída deve seguir o modelo Blog. +- Após executar o crew, você pode acessar a saída estruturada de várias formas, como mostrado. + +#### Explicação sobre o acesso à saída + +1. Indexação estilo dicionário: Acesse os campos diretamente usando result["nome_do_campo"]. Isso funciona porque a classe CrewOutput implementa o método **getitem**. +2. Diretamente do modelo Pydantic: Acesse os atributos diretamente do objeto result.pydantic. +3. Usando o método to_dict(): Converta a saída para um dicionário e acesse os campos. +4. Imprimindo o objeto inteiro: Simplesmente imprima o objeto result para ver a saída estruturada. + +### Usando `output_json` + +A propriedade `output_json` permite definir o formato de saída esperado em JSON. Isso garante que a saída da tarefa seja uma estrutura JSON válida que pode ser facilmente analisada e utilizada na aplicação. + +Veja um exemplo de uso do `output_json`: + +```python Code +import json + +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + + +# Define o modelo Pydantic para o blog +class Blog(BaseModel): + title: str + content: str + + +# Define o agente +blog_agent = Agent( + role="Blog Content Generator Agent", + goal="Gerar um título e conteúdo para blog", + backstory="""Você é um especialista em criação de conteúdo, habilidoso em escrever posts de blogs engajadores e informativos.""", + verbose=False, + allow_delegation=False, + llm="gpt-4o", +) + +# Define a tarefa com output_json configurado para o modelo Blog +task1 = Task( + description="""Crie um título e conteúdo para blog sobre um tópico. Certifique-se de que o conteúdo tenha menos de 200 palavras.""", + expected_output="Um objeto JSON com os campos 'title' e 'content'.", + agent=blog_agent, + output_json=Blog, +) + +# Instancia o crew com processo sequencial +crew = Crew( + agents=[blog_agent], + tasks=[task1], + verbose=True, + process=Process.sequential, +) + +# Executa o crew para realizar a tarefa +result = crew.kickoff() + +# Opção 1: Acessando propriedades via indexação de dicionário +print("Acessando propriedades - Opção 1") +title = result["title"] +content = result["content"] +print("Título:", title) +print("Conteúdo:", content) + +# Opção 2: Imprimindo o objeto Blog inteiro +print("Acessando propriedades - Opção 2") +print("Blog:", result) +``` + +Neste exemplo: + +- Um modelo Pydantic Blog é definido com os campos title e content, usado para especificar a estrutura do JSON de saída. +- A tarefa task1 utiliza a propriedade output_json para indicar que espera uma saída JSON que segue o modelo Blog. +- Após executar o crew, você pode acessar a saída estruturada em JSON conforme demonstrado. + +#### Explicação sobre o acesso à saída + +1. Acessando propriedades via indexação de dicionário: Você pode acessar os campos diretamente usando result["nome_do_campo"]. Isso é possível pois a classe CrewOutput implementa o método **getitem**, permitindo tratar a saída como um dicionário. Nesse caso, estamos acessando title e content do resultado. +2. Imprimindo o objeto Blog inteiro: Ao imprimir result, você obterá a representação em string do objeto CrewOutput. Como o método **str** é implementado para retornar a saída em JSON, isso exibirá toda a saída como uma string formatada representando o objeto Blog. + +--- + +Utilizando `output_pydantic` ou `output_json`, você garante que suas tarefas produzam saídas em um formato estruturado e consistente, facilitando o processamento e uso dos dados na sua aplicação ou entre múltiplas tarefas. + +## Integrando Ferramentas com Tarefas + +Utilize ferramentas do [CrewAI Toolkit](https://github.com/joaomdmoura/crewai-tools) e [LangChain Tools](https://python.langchain.com/docs/integrations/tools) para ampliar o desempenho das tarefas e aprimorar a interação dos agentes. + +## Criando uma Tarefa com Ferramentas + +```python Code +import os +os.environ["OPENAI_API_KEY"] = "Sua Chave" +os.environ["SERPER_API_KEY"] = "Sua Chave" # Chave serper.dev + +from crewai import Agent, Task, Crew +from crewai_tools import SerperDevTool + +research_agent = Agent( + role='Researcher', + goal='Encontrar e resumir as últimas notícias de IA', + backstory="""Você é um pesquisador em uma grande empresa. + Sua responsabilidade é analisar dados e fornecer insights + para o negócio.""", + verbose=True +) + +# Para realizar buscas semânticas de um termo a partir de textos da internet +search_tool = SerperDevTool() + +task = Task( + description='Encontre e resuma as últimas notícias de IA', + expected_output='Uma lista em bullet points com o resumo das 5 notícias mais importantes de IA', + agent=research_agent, + tools=[search_tool] +) + +crew = Crew( + agents=[research_agent], + tasks=[task], + verbose=True +) + +result = crew.kickoff() +print(result) +``` + +Isso demonstra como tarefas com ferramentas específicas podem sobrescrever o conjunto padrão de um agente para uma execução mais personalizada da tarefa. + +## Referenciando Outras Tarefas + +No CrewAI, a saída de uma tarefa é automaticamente repassada para a próxima, mas você pode definir explicitamente de quais tarefas a saída deve ser utilizada como contexto por outra, inclusive múltiplas saídas. + +É útil especialmente quando você precisa que uma tarefa dependa do resultado de outra que não é executada imediatamente antes dela. Isso é feito pelo atributo `context`: + +```python Code +# ... + +research_ai_task = Task( + description="Pesquise os avanços mais recentes em IA", + expected_output="Uma lista de avanços recentes em IA", + async_execution=True, + agent=research_agent, + tools=[search_tool] +) + +research_ops_task = Task( + description="Pesquise os avanços mais recentes em AI Ops", + expected_output="Uma lista de avanços recentes em AI Ops", + async_execution=True, + agent=research_agent, + tools=[search_tool] +) + +write_blog_task = Task( + description="Escreva um post de blog completo sobre a importância da IA e suas últimas notícias", + expected_output="Post de blog completo com 4 parágrafos", + agent=writer_agent, + context=[research_ai_task, research_ops_task] +) + +#... +``` + +## Execução Assíncrona + +Você pode definir que uma tarefa seja executada de forma assíncrona. Isso significa que o crew não aguardará sua conclusão para seguir para a próxima tarefa. É útil para tarefas demoradas, ou que não são cruciais para as seguintes. + +Depois, utilize o atributo `context` para indicar, em uma tarefa futura, que ela deve aguardar os resultados da tarefa assíncrona. + +```python Code +#... + +list_ideas = Task( + description="Liste 5 ideias interessantes para explorar em um artigo sobre IA.", + expected_output="Lista em bullet points com 5 ideias para um artigo.", + agent=researcher, + async_execution=True # Será executada de forma assíncrona +) + +list_important_history = Task( + description="Pesquise a história da IA e forneça os 5 eventos mais importantes.", + expected_output="Lista em bullet points com 5 eventos importantes.", + agent=researcher, + async_execution=True # Será executada de forma assíncrona +) + +write_article = Task( + description="Escreva um artigo sobre IA, sua história e ideias interessantes.", + expected_output="Artigo de 4 parágrafos sobre IA.", + agent=writer, + context=[list_ideas, list_important_history] # Vai esperar o resultado das duas tarefas +) + +#... +``` + +## Mecanismo de Callback + +A função callback é executada após a conclusão da tarefa, permitindo acionar ações ou notificações baseadas no resultado da tarefa. + +```python Code +# ... + +def callback_function(output: TaskOutput): + # Realiza algo após a conclusão da tarefa + # Exemplo: Envia um e-mail ao gerente + print(f""" + Tarefa concluída! + Tarefa: {output.description} + Saída: {output.raw} + """) + +research_task = Task( + description='Encontre e resuma as últimas notícias de IA', + expected_output='Uma lista em bullet points com o resumo das 5 notícias mais importantes de IA', + agent=research_agent, + tools=[search_tool], + callback=callback_function +) + +#... +``` + +## Acessando a Saída de uma Tarefa Específica + +Assim que um crew finaliza sua execução, você pode acessar a saída de uma tarefa específica por meio do atributo `output` do objeto da tarefa: + +```python Code +# ... +task1 = Task( + description='Encontre e resuma as últimas notícias de IA', + expected_output='Uma lista em bullet points com o resumo das 5 notícias mais importantes de IA', + agent=research_agent, + tools=[search_tool] +) + +#... + +crew = Crew( + agents=[research_agent], + tasks=[task1, task2, task3], + verbose=True +) + +result = crew.kickoff() + +# Retorna um objeto TaskOutput com a descrição e resultado da tarefa +print(f""" + Tarefa concluída! + Tarefa: {task1.output.description} + Saída: {task1.output.raw} +""") +``` + +## Mecanismo de Sobrescrição de Ferramentas + +Especificar ferramentas em uma tarefa permite a adaptação dinâmica das capacidades do agente, destacando a flexibilidade do CrewAI. + +## Mecanismos de Validação e Tratamento de Erros + +Ao criar e executar tarefas, determinados mecanismos de validação garantem a robustez e confiabilidade dos atributos das tarefas. Isso inclui, mas não se limita a: + +- Garantir que apenas um tipo de saída seja definido por tarefa para manter expectativas de saída claras. +- Impedir a atribuição manual do atributo `id`, preservando a integridade do sistema de identificadores únicos. + +Estas validações colaboram para a consistência e confiabilidade das execuções de tarefas no framework CrewAI. + +## Guardrails em Tarefas + +Guardrails de tarefas oferecem uma maneira poderosa de validar, transformar ou filtrar as saídas das tarefas antes de serem encaminhadas à próxima. São funções opcionais que executam antes do início da próxima tarefa, garantindo que as saídas estejam em conformidade com requisitos ou formatos esperados. + +### Uso Básico + +#### Defina sua própria lógica de validação + +```python Code +from typing import Tuple, Union +from crewai import Task + +def validate_json_output(result: str) -> Tuple[bool, Union[dict, str]]: + """Valida se a saída é um JSON válido.""" + try: + json_data = json.loads(result) + return (True, json_data) + except json.JSONDecodeError: + return (False, "A saída deve ser um JSON válido") + +task = Task( + description="Gerar dados em JSON", + expected_output="Objeto JSON válido", + guardrail=validate_json_output +) +``` + +```python Code +@CrewBase +class InternalCrew: + agents_config = "config/agents.yaml" + tasks_config = "config/tasks.yaml" + + ... + @task + def research_task(self): + return Task(config=self.tasks_config["research_task"]) # type: ignore[index] + ... +``` + +#### Use modelos customizados para geração de código + +```python Code +from crewai import Task +from crewai.llm import LLM + +task = Task( + description="Gerar dados em JSON", + expected_output="Objeto JSON válido", + guardrail=LLMGuardrail( + description="Garanta que a resposta é um objeto JSON válido", + llm=LLM(model="gpt-4o-mini"), + ) +) +``` + +### Como Guardrails Funcionam + +1. **Atributo Opcional**: Guardrails são opcionais por tarefa, permitindo adicionar validação só onde for necessário. +2. **Momento de Execução**: A função guardrail é executada antes do início da próxima tarefa, garantindo fluxo de dados válido entre tarefas. +3. **Formato de Retorno**: Guardrails devem retornar uma tupla `(sucesso, dados)`: + - Se `sucesso` é `True`, `dados` é o resultado validado/transformado + - Se `sucesso` é `False`, `dados` é a mensagem de erro +4. **Roteamento do Resultado**: + - Sucesso (`True`): o resultado é automaticamente passado para a próxima tarefa + - Falha (`False`): o erro é enviado de volta ao agente para gerar uma nova resposta + +### Casos Comuns de Uso + +#### Validação de Formato de Dados + +```python Code +def validate_email_format(result: str) -> Tuple[bool, Union[str, str]]: + """Garante que a saída contenha um e-mail válido.""" + import re + email_pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$' + if re.match(email_pattern, result.strip()): + return (True, result.strip()) + return (False, "A saída deve ser um e-mail válido") +``` + +#### Filtragem de Conteúdo + +```python Code +def filter_sensitive_info(result: str) -> Tuple[bool, Union[str, str]]: + """Remove ou valida informações sensíveis.""" + sensitive_patterns = ['SSN:', 'password:', 'secret:'] + for pattern in sensitive_patterns: + if pattern.lower() in result.lower(): + return (False, f"A saída contém informação sensível ({pattern})") + return (True, result) +``` + +#### Transformação de Dados + +```python Code +def normalize_phone_number(result: str) -> Tuple[bool, Union[str, str]]: + """Garante que números de telefone estejam em formato consistente.""" + import re + digits = re.sub(r'\D', '', result) + if len(digits) == 10: + formatted = f"({digits[:3]}) {digits[3:6]}-{digits[6:]}" + return (True, formatted) + return (False, "A saída deve ser um telefone com 10 dígitos") +``` + +### Recursos Avançados + +#### Encadeando Múltiplas Validações + +```python Code +def chain_validations(*validators): + """Encadeia múltiplos validadores.""" + def combined_validator(result): + for validator in validators: + success, data = validator(result) + if not success: + return (False, data) + result = data + return (True, result) + return combined_validator + +# Uso +task = Task( + description="Obtenha informações de contato do usuário", + expected_output="E-mail e telefone", + guardrail=chain_validations( + validate_email_format, + filter_sensitive_info + ) +) +``` + +#### Lógica Customizada de Retentativas + +```python Code +task = Task( + description="Gerar dados", + expected_output="Dados válidos", + guardrail=validate_data, + guardrail_max_retries=5 # Sobrescreve o limite padrão de tentativas +) +``` + +## Criando Diretórios ao Salvar Arquivos + +O parâmetro `create_directory` controla se o CrewAI deve criar automaticamente diretórios ao salvar saídas de tarefas em arquivos. Este recurso é particularmente útil para organizar outputs e garantir que os caminhos de arquivos estejam estruturados corretamente, especialmente ao trabalhar com hierarquias de projetos complexas. + +### Comportamento Padrão + +Por padrão, `create_directory=True`, o que significa que o CrewAI criará automaticamente qualquer diretório ausente no caminho do arquivo de saída: + +```python Code +# Comportamento padrão - diretórios são criados automaticamente +report_task = Task( + description='Gerar um relatório abrangente de análise de mercado', + expected_output='Uma análise detalhada de mercado com gráficos e insights', + agent=analyst_agent, + output_file='reports/2025/market_analysis.md', # Cria 'reports/2025/' se não existir + markdown=True +) +``` + +### Desabilitando a Criação de Diretórios + +Se você quiser evitar a criação automática de diretórios e garantir que o diretório já exista, defina `create_directory=False`: + +```python Code +# Modo estrito - o diretório já deve existir +strict_output_task = Task( + description='Salvar dados críticos que requerem infraestrutura existente', + expected_output='Dados salvos em localização pré-configurada', + agent=data_agent, + output_file='secure/vault/critical_data.json', + create_directory=False # Gerará RuntimeError se 'secure/vault/' não existir +) +``` + +### Configuração YAML + +Você também pode configurar este comportamento em suas definições de tarefas YAML: + +```yaml tasks.yaml +analysis_task: + description: > + Gerar análise financeira trimestral + expected_output: > + Um relatório financeiro abrangente com insights trimestrais + agent: financial_analyst + output_file: reports/quarterly/q4_2024_analysis.pdf + create_directory: true # Criar automaticamente o diretório 'reports/quarterly/' + +audit_task: + description: > + Realizar auditoria de conformidade e salvar no diretório de auditoria existente + expected_output: > + Um relatório de auditoria de conformidade + agent: auditor + output_file: audit/compliance_report.md + create_directory: false # O diretório já deve existir +``` + +### Casos de Uso + +**Criação Automática de Diretórios (`create_directory=True`):** + +- Ambientes de desenvolvimento e prototipagem +- Geração dinâmica de relatórios com pastas baseadas em datas +- Fluxos de trabalho automatizados onde a estrutura de diretórios pode variar +- Aplicações multi-tenant com pastas específicas do usuário + +**Gerenciamento Manual de Diretórios (`create_directory=False`):** + +- Ambientes de produção com controles rígidos do sistema de arquivos +- Aplicações sensíveis à segurança onde diretórios devem ser pré-configurados +- Sistemas com requisitos específicos de permissão +- Ambientes de conformidade onde a criação de diretórios é auditada + +### Tratamento de Erros + +Quando `create_directory=False` e o diretório não existe, o CrewAI gerará um `RuntimeError`: + +```python Code +try: + result = crew.kickoff() +except RuntimeError as e: + # Tratar erro de diretório ausente + print(f"Falha na criação do diretório: {e}") + # Criar diretório manualmente ou usar local alternativo +``` + +Veja o vídeo abaixo para aprender como utilizar saídas estruturadas no CrewAI: + + + +## Conclusão + +Tarefas são a força motriz por trás das ações dos agentes no CrewAI. +Ao definir corretamente as tarefas e seus resultados, você prepara seus agentes de IA para trabalhar de forma eficaz, seja de forma independente ou colaborativa. +Equipar tarefas com as ferramentas adequadas, compreender o processo de execução e seguir práticas sólidas de validação são fundamentais para maximizar o potencial do CrewAI, +assegurando que os agentes estejam devidamente preparados para suas atribuições e que as tarefas sejam executadas conforme o esperado. diff --git a/docs/v1.15.13/pt-BR/concepts/testing.mdx b/docs/v1.15.13/pt-BR/concepts/testing.mdx new file mode 100644 index 0000000000..8277757e06 --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/testing.mdx @@ -0,0 +1,49 @@ +--- +title: Testes +description: Saiba como testar sua CrewAI Crew e avaliar seu desempenho. +icon: vial +mode: "wide" +--- + +## Visão Geral + +Testar é uma parte crucial do processo de desenvolvimento, sendo essencial para garantir que sua crew está performando conforme o esperado. Com o crewAI, você pode facilmente testar sua crew e avaliar seu desempenho utilizando as funcionalidades de teste integradas. + +### Utilizando o Recurso de Teste + +Adicionamos o comando de CLI `crewai test` para facilitar o teste da sua crew. Esse comando executará sua crew por um número especificado de iterações e fornecerá métricas de desempenho detalhadas. Os parâmetros são `n_iterations` e `model`, ambos opcionais e com valores padrão de 2 e `gpt-4o-mini`, respectivamente. Por enquanto, o único provedor disponível é a OpenAI. + +```bash +crewai test +``` + +Se quiser rodar mais iterações ou utilizar um modelo diferente, você pode especificar os parâmetros assim: + +```bash +crewai test --n_iterations 5 --model gpt-4o +``` + +ou usando as formas abreviadas: + +```bash +crewai test -n 5 -m gpt-4o +``` + +Ao executar o comando `crewai test`, a crew será executada pelo número especificado de iterações, e as métricas de desempenho serão exibidas ao final da execução. + +Uma tabela de pontuações ao final mostrará o desempenho da crew em relação às seguintes métricas: + +
**Pontuações das Tarefas (1-10, quanto maior melhor)**
+ +| Tarefas/Crew/Agentes | Exec. 1 | Exec. 2 | Méd. Total | Agentes | Informações Adicionais | +|:---------------------|:-------:|:-------:|:----------:|:------------------------------:|:---------------------------------| +| Tarefa 1 | 9,0 | 9,5 | **9,2** | Professional Insights | | +| | | | | Researcher | | +| Tarefa 2 | 9,0 | 10,0 | **9,5** | Company Profile Investigator | | +| Tarefa 3 | 9,0 | 9,0 | **9,0** | Automation Insights | | +| | | | | Specialist | | +| Tarefa 4 | 9,0 | 9,0 | **9,0** | Final Report Compiler | Automation Insights Specialist | +| Crew | 9,00 | 9,38 | **9,2** | | | +| Tempo de Execução (s)| 126 | 145 | **135** | | | + +O exemplo acima mostra os resultados dos testes para duas execuções da crew com duas tarefas, apresentando a pontuação média total de cada tarefa e da crew como um todo. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/concepts/tools.mdx b/docs/v1.15.13/pt-BR/concepts/tools.mdx new file mode 100644 index 0000000000..da7e6f24a2 --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/tools.mdx @@ -0,0 +1,292 @@ +--- +title: Ferramentas +description: Compreendendo e aproveitando ferramentas dentro do framework CrewAI para colaboração e execução de tarefas por agentes. +icon: screwdriver-wrench +mode: "wide" +--- + +## Visão geral + +As ferramentas do CrewAI capacitam agentes com habilidades que vão desde busca na web e análise de dados até colaboração e delegação de tarefas entre colegas de trabalho. +Esta documentação descreve como criar, integrar e aproveitar essas ferramentas dentro do framework CrewAI, incluindo um novo foco em ferramentas de colaboração. + + + Ferramentas dão aos agentes **funções chamáveis** para tomar ações. Elas funcionam junto com [MCPs](/pt-BR/mcp/overview) (servidores de ferramentas remotos), [Apps](/pt-BR/concepts/agent-capabilities) (integrações com plataformas), [Skills](/pt-BR/concepts/skills) (expertise de domínio) e [Knowledge](/pt-BR/concepts/knowledge) (fatos recuperados). Veja a visão geral de [Capacidades do Agente](/pt-BR/concepts/agent-capabilities) para entender quando usar cada um. + + +## O que é uma Ferramenta? + +Uma ferramenta no CrewAI é uma habilidade ou função que os agentes podem utilizar para executar diversas ações. +Isso inclui ferramentas do [CrewAI Toolkit](https://github.com/joaomdmoura/crewai-tools) e [LangChain Tools](https://python.langchain.com/docs/integrations/tools), +permitindo desde buscas simples até interações complexas e trabalho em equipe eficiente entre agentes. + + +O CrewAI AMP oferece um Repositório de Ferramentas abrangente, com integrações pré-construídas para sistemas empresariais e APIs comuns. Implemente agentes com ferramentas corporativas em minutos em vez de dias. + +O Repositório de Ferramentas Empresariais inclui: + +- Conectores pré-construídos para sistemas empresariais populares +- Interface para criação de ferramentas personalizadas +- Controle de versão e funcionalidades de compartilhamento +- Recursos de segurança e conformidade + + +## Características Principais das Ferramentas + +- **Utilidade**: Desenvolvidas para tarefas como busca web, análise de dados, geração de conteúdo e colaboração entre agentes. +- **Integração**: Potencializa as habilidades dos agentes ao integrar ferramentas de forma transparente ao seu fluxo de trabalho. +- **Personalização**: Oferece flexibilidade para desenvolver ferramentas personalizadas ou utilizar existentes, atendendo necessidades específicas dos agentes. +- **Tratamento de Erros**: Incorpora mecanismos robustos de tratamento de erros para garantir operação sem interrupções. +- **Mecanismo de Cache**: Possui cache inteligente para otimizar desempenho e reduzir operações redundantes. +- **Suporte Assíncrono**: Suporta ferramentas síncronas e assíncronas, permitindo operações não bloqueantes. + +## Utilizando Ferramentas CrewAI + +Para aprimorar as capacidades de seus agentes com as ferramentas do CrewAI, comece instalando nosso pacote extra de ferramentas: + +```bash +pip install 'crewai[tools]' +``` + +Aqui está um exemplo demonstrando seu uso: + +```python Code +import os +from crewai import Agent, Task, Crew +# Importando ferramentas do crewAI +from crewai_tools import ( + DirectoryReadTool, + FileReadTool, + SerperDevTool, + WebsiteSearchTool +) + +# Configure as chaves de API +os.environ["SERPER_API_KEY"] = "Your Key" # chave da API serper.dev +os.environ["OPENAI_API_KEY"] = "Your Key" + +# Instanciar as ferramentas +docs_tool = DirectoryReadTool(directory='./blog-posts') +file_tool = FileReadTool() +search_tool = SerperDevTool() +web_rag_tool = WebsiteSearchTool() + +# Criar agentes +researcher = Agent( + role='Analista de Mercado', + goal='Fornecer análise de mercado atualizada da indústria de IA', + backstory='Analista especialista com olhar atento para tendências de mercado.', + tools=[search_tool, web_rag_tool], + verbose=True +) + +writer = Agent( + role='Redator de Conteúdo', + goal='Criar posts de blog envolventes sobre a indústria de IA', + backstory='Redator habilidoso com paixão por tecnologia.', + tools=[docs_tool, file_tool], + verbose=True +) + +# Definir tarefas +research = Task( + description='Research the latest trends in the AI industry and provide a summary.', + expected_output='A summary of the top 3 trending developments in the AI industry with a unique perspective on their significance.', + agent=researcher +) + +write = Task( + description='Write an engaging blog post about the AI industry, based on the research analyst's summary. Draw inspiration from the latest blog posts in the directory.', + expected_output='A 4-paragraph blog post formatted in markdown with engaging, informative, and accessible content, avoiding complex jargon.', + agent=writer, + output_file='blog-posts/new_post.md' # O post final do blog será salvo aqui +) + +# Montar um crew com o planejamento habilitado +crew = Crew( + agents=[researcher, writer], + tasks=[research, write], + verbose=True, + planning=True, # Habilitar o recurso de planejamento +) + +# Executar tarefas +crew.kickoff() +``` + +## Ferramentas CrewAI Disponíveis + +- **Tratamento de Erros**: Todas as ferramentas são construídas com capacidades de tratamento de erros, permitindo que os agentes administrem exceções de forma adequada e prossigam com suas tarefas. +- **Mecanismo de Cache**: Todas as ferramentas suportam cache, possibilitando que agentes reutilizem de forma eficiente resultados obtidos anteriormente, reduzindo a carga em recursos externos e acelerando o tempo de execução. Também é possível definir controles mais precisos sobre o mecanismo de cache usando o atributo `cache_function` na ferramenta. + +Aqui está uma lista das ferramentas disponíveis e suas descrições: + +| Ferramenta | Descrição | +| :------------------------------- | :--------------------------------------------------------------------------------------------------- | +| **ApifyActorsTool** | Ferramenta que integra Apify Actors aos seus fluxos de trabalho para web scraping e automação. | +| **BrowserbaseLoadTool** | Ferramenta para interação e extração de dados de navegadores web. | +| **CodeDocsSearchTool** | Uma ferramenta RAG otimizada para busca em documentações de código e documentos técnicos. | +| **CodeInterpreterTool** | Ferramenta para interpretar código Python. | +| **ComposioTool** | Permite o uso de ferramentas Composio. | +| **CSVSearchTool** | Ferramenta RAG projetada para busca em arquivos CSV, ideal para dados estruturados. | +| **DALL-E Tool** | Ferramenta para gerar imagens utilizando a API do DALL-E. | +| **DirectorySearchTool** | Ferramenta RAG para busca em diretórios, útil para navegação em sistemas de arquivos. | +| **DOCXSearchTool** | Ferramenta RAG voltada para busca em documentos DOCX, ideal para processar arquivos Word. | +| **DirectoryReadTool** | Facilita a leitura e processamento de estruturas de diretórios e seus conteúdos. | +| **ExaSearchTool** | Ferramenta projetada para buscas exaustivas em diversas fontes de dados. | +| **FileReadTool** | Permite a leitura e extração de dados de arquivos, suportando diversos formatos. | +| **FirecrawlSearchTool** | Ferramenta para buscar páginas web usando Firecrawl e retornar os resultados. | +| **FirecrawlCrawlWebsiteTool** | Ferramenta para rastrear páginas web utilizando o Firecrawl. | +| **FirecrawlScrapeWebsiteTool** | Ferramenta para extrair o conteúdo de URLs usando Firecrawl. | +| **GithubSearchTool** | Ferramenta RAG para buscar em repositórios GitHub, útil para pesquisa de código e documentação. | +| **SerperDevTool** | Ferramenta especializada para finalidades de desenvolvimento, com funcionalidades em evolução. | +| **TXTSearchTool** | Ferramenta RAG voltada para busca em arquivos de texto (.txt), adaptada para dados não estruturados. | +| **JSONSearchTool** | Ferramenta RAG para busca em arquivos JSON, voltada ao manuseio de dados estruturados. | +| **LlamaIndexTool** | Permite o uso das ferramentas LlamaIndex. | +| **MDXSearchTool** | Ferramenta RAG para busca em arquivos Markdown (MDX), útil para documentação. | +| **PDFSearchTool** | Ferramenta RAG para busca em documentos PDF, ideal para processar documentos digitalizados. | +| **PGSearchTool** | Ferramenta RAG otimizada para busca em bancos de dados PostgreSQL, adequada para consultas. | +| **Vision Tool** | Ferramenta para gerar imagens utilizando a API do DALL-E. | +| **RagTool** | Ferramenta RAG de uso geral, capaz de lidar com diferentes fontes e tipos de dados. | +| **ScrapeElementFromWebsiteTool** | Permite extrair elementos específicos de sites, útil para extração de dados direcionada. | +| **ScrapeWebsiteTool** | Facilita o scraping de sites inteiros, ideal para coleta abrangente de dados. | +| **WebsiteSearchTool** | Ferramenta RAG para busca em conteúdos de sites, otimizada para extração de dados web. | +| **XMLSearchTool** | Ferramenta RAG para busca em arquivos XML, adequada para formatos de dados estruturados. | +| **YoutubeChannelSearchTool** | Ferramenta RAG para busca em canais do YouTube, útil para análise de conteúdo em vídeo. | +| **YoutubeVideoSearchTool** | Ferramenta RAG para busca em vídeos do YouTube, ideal para extração de dados de vídeo. | + +## Criando suas próprias Ferramentas + + + Desenvolvedores podem criar `ferramentas personalizadas` adaptadas para as + necessidades de seus agentes ou utilizar opções pré-construídas. + + +Existem duas formas principais de criar uma ferramenta CrewAI: + +### Herança de `BaseTool` + +```python Code +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class MyToolInput(BaseModel): + """Input schema for MyCustomTool.""" + argument: str = Field(..., description="Description of the argument.") + +class MyCustomTool(BaseTool): + name: str = "Name of my tool" + description: str = "What this tool does. It's vital for effective utilization." + args_schema: Type[BaseModel] = MyToolInput + + def _run(self, argument: str) -> str: + # Seu código da ferramenta aqui + return "Tool's result" +``` + +## Suporte a Ferramentas Assíncronas + +O CrewAI suporta ferramentas assíncronas, permitindo que você implemente ferramentas que realizam operações não bloqueantes, como requisições de rede, I/O de arquivos ou outras operações async sem bloquear o fluxo principal de execução. + +### Criando Ferramentas Assíncronas + +Você pode criar ferramentas assíncronas de duas formas: + +#### 1. Utilizando o Decorador `tool` com Funções Assíncronas + +```python Code +from crewai.tools import tool + +@tool("fetch_data_async") +async def fetch_data_async(query: str) -> str: + """Asynchronously fetch data based on the query.""" + # Simulate async operation + await asyncio.sleep(1) + return f"Data retrieved for {query}" +``` + +#### 2. Implementando Métodos Assíncronos em Classes de Ferramentas Personalizadas + +```python Code +from crewai.tools import BaseTool + +class AsyncCustomTool(BaseTool): + name: str = "async_custom_tool" + description: str = "An asynchronous custom tool" + + async def _run(self, query: str = "") -> str: + """Asynchronously run the tool""" + # Sua implementação assíncrona aqui + await asyncio.sleep(1) + return f"Processed {query} asynchronously" +``` + +### Utilizando Ferramentas Assíncronas + +Ferramentas assíncronas funcionam perfeitamente tanto em fluxos tradicionais do Crew quanto em fluxos baseados em Flow: + +```python Code +# No Crew tradicional +agent = Agent(role="researcher", tools=[async_custom_tool]) + +# Em Flow +class MyFlow(Flow): + @start() + async def begin(self): + crew = Crew(agents=[agent]) + result = await crew.kickoff_async() + return result +``` + +O framework CrewAI lida automaticamente com a execução de ferramentas síncronas e assíncronas, então você não precisa se preocupar com diferenças na chamada. + +### Utilizando o Decorador `tool` + +```python Code +from crewai.tools import tool +@tool("Name of my tool") +def my_tool(question: str) -> str: + """Clear description for what this tool is useful for, your agent will need this information to use it.""" + # Lógica da função aqui + return "Result from your custom tool" +``` + +### Mecanismo de Cache Personalizado + + + As ferramentas podem implementar opcionalmente uma `cache_function` para + ajuste fino do comportamento de cache. Esta função determina quando armazenar + resultados em cache com base em condições específicas, oferecendo controle + granular sobre a lógica de cache. + + +```python Code +from crewai.tools import tool + +@tool +def multiplication_tool(first_number: int, second_number: int) -> str: + """Useful for when you need to multiply two numbers together.""" + return first_number * second_number + +def cache_func(args, result): + # Neste exemplo, só cacheamos o resultado se for múltiplo de 2 + cache = result % 2 == 0 + return cache + +multiplication_tool.cache_function = cache_func + +writer1 = Agent( + role="Writer", + goal="You write lessons of math for kids.", + backstory="You're an expert in writing and you love to teach kids but you know nothing of math.", + tools=[multiplication_tool], + allow_delegation=False, + ) + #... +``` + +## Conclusão + +Ferramentas são fundamentais para expandir as capacidades dos agentes CrewAI, permitindo que assumam uma ampla gama de tarefas e colaborem de forma eficiente. +Ao construir soluções com CrewAI, aproveite tanto ferramentas existentes quanto personalizadas para potencializar seus agentes e ampliar o ecossistema de IA. Considere utilizar tratamento de erros, +mecanismos de cache e a flexibilidade de argumentos das ferramentas para otimizar o desempenho e as capacidades dos seus agentes. diff --git a/docs/v1.15.13/pt-BR/concepts/training.mdx b/docs/v1.15.13/pt-BR/concepts/training.mdx new file mode 100644 index 0000000000..85e405fe8a --- /dev/null +++ b/docs/v1.15.13/pt-BR/concepts/training.mdx @@ -0,0 +1,66 @@ +--- +title: Treinamento +description: Aprenda como treinar seus agentes CrewAI fornecendo feedback desde o início e obtenha resultados consistentes. +icon: dumbbell +mode: "wide" +--- + +## Visão Geral + +O recurso de treinamento no CrewAI permite que você treine seus agentes de IA usando a interface de linha de comando (CLI). +Ao executar o comando `crewai train -n `, você pode especificar o número de iterações para o processo de treinamento. + +Durante o treinamento, o CrewAI utiliza técnicas para otimizar o desempenho dos seus agentes juntamente com o feedback humano. +Isso ajuda os agentes a aprimorar sua compreensão, tomada de decisão e habilidades de resolução de problemas. + +### Treinando sua Crew Usando a CLI + +Para utilizar o recurso de treinamento, siga estes passos: + +1. Abra seu terminal ou prompt de comando. +2. Navegue até o diretório onde seu projeto CrewAI está localizado. +3. Execute o seguinte comando: + +```shell +crewai train -n (optional) +``` + + Substitua `` pelo número desejado de iterações de treinamento e `` pelo nome de arquivo apropriado terminando com `.pkl`. + + +### Treinando sua Crew Programaticamente + +Para treinar sua crew de forma programática, siga estes passos: + +1. Defina o número de iterações para o treinamento. +2. Especifique os parâmetros de entrada para o processo de treinamento. +3. Execute o comando de treinamento dentro de um bloco try-except para tratar possíveis erros. + +```python Code +n_iteracoes = 2 +entradas = {"topic": "Treinamento CrewAI"} +nome_arquivo = "seu_modelo.pkl" + +try: + SuaCrew().crew().train( + n_iterations=n_iteracoes, + inputs=entradas, + filename=nome_arquivo + ) +except Exception as e: + raise Exception(f"Ocorreu um erro ao treinar a crew: {e}") +``` + +### Pontos Importantes + +- **Requisito de Número Inteiro Positivo:** Certifique-se de que o número de iterações (`n_iterations`) seja um inteiro positivo. O código lançará um `ValueError` se essa condição não for atendida. +- **Requisito de Nome de Arquivo:** Certifique-se de que o nome do arquivo termine com `.pkl`. O código lançará um `ValueError` se essa condição não for atendida. +- **Tratamento de Erros:** O código trata erros de subprocessos e exceções inesperadas, fornecendo mensagens de erro ao usuário. + +É importante observar que o processo de treinamento pode levar algum tempo, dependendo da complexidade dos seus agentes e também exigirá seu feedback em cada iteração. + +Uma vez concluído o treinamento, seus agentes estarão equipados com capacidades e conhecimentos aprimorados, prontos para enfrentar tarefas complexas e fornecer insights mais consistentes e valiosos. + +Lembre-se de atualizar e treinar seus agentes regularmente para garantir que permaneçam atualizados com as últimas informações e avanços na área. + +Bom treinamento com o CrewAI! 🚀 \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/examples/cookbooks.mdx b/docs/v1.15.13/pt-BR/examples/cookbooks.mdx new file mode 100644 index 0000000000..7057621a19 --- /dev/null +++ b/docs/v1.15.13/pt-BR/examples/cookbooks.mdx @@ -0,0 +1,23 @@ +--- +title: CrewAI Cookbooks +description: Quickstarts e notebooks focados em recursos para aprender padrões rapidamente. +icon: book +mode: "wide" +--- + +## Quickstarts & Demos + + + + Demos e projetos pequenos que mostram capacidades específicas do CrewAI. + + + Notebooks interativos para aprendizado prático. + + + + +Use Cookbooks para aprender um padrão rapidamente e, em seguida, avance para os Exemplos completos para implementações de produção. + + + diff --git a/docs/v1.15.13/pt-BR/examples/example.mdx b/docs/v1.15.13/pt-BR/examples/example.mdx new file mode 100644 index 0000000000..9e30069b31 --- /dev/null +++ b/docs/v1.15.13/pt-BR/examples/example.mdx @@ -0,0 +1,86 @@ +--- +title: Exemplos CrewAI +description: Explore exemplos organizados por Crews, Flows, Integrações e Notebooks. +icon: rocket-launch +mode: "wide" +--- + +## Crews + + + + Planejamento de campanhas com múltiplos agentes. + + + Planejamento de viagens personalizadas. + + + Correspondência de CV para vagas com busca vetorial. + + + Criação automatizada de descrições de vagas. + + + Equipe multiagente que projeta e constrói jogos em Python. + + + Prospecção e avaliação de candidatos. + + + Lista completa de exemplos de crews. + + + +## Flows + + + + Geração de conteúdo com roteamento. + + + Monitoramento e respostas de e‑mail. + + + Qualificação de leads com revisão humana. + + + Processamento de notas com integrações. + + + Fluxos de autoaperfeiçoamento iterativo. + + + Geração paralela de capítulos. + + + Lista completa de exemplos de flows. + + + +## Integrações + + + + Integração com o framework LangGraph. + + + Usando CrewAI com Azure OpenAI. + + + Integrações com o ecossistema NVIDIA. + + + Todos os exemplos de integrações. + + + +## Notebooks + + + + Simple QA Crew + Flow. + + + Exemplos interativos para aprendizado e experimentação. + + \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/guides/advanced/customizing-prompts.mdx b/docs/v1.15.13/pt-BR/guides/advanced/customizing-prompts.mdx new file mode 100644 index 0000000000..ad1d7b096a --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/advanced/customizing-prompts.mdx @@ -0,0 +1,331 @@ +--- +title: Personalizando Prompts +description: Aprofunde-se na personalização de prompts de baixo nível no CrewAI, habilitando casos de uso super customizados e complexos para diferentes modelos e idiomas. +icon: message-pen +mode: "wide" +--- + +## Por Que Personalizar Prompts? + +Embora os prompts padrão do CrewAI funcionem bem para muitos cenários, a personalização de baixo nível permite comportamentos de agentes significativamente mais flexíveis e poderosos. Veja por que você pode querer aproveitar esse controle mais profundo: + +1. **Otimizar para LLMs específicas** – Diferentes modelos (como GPT-4, Claude ou Llama) funcionam melhor com formatos de prompt adaptados às suas arquiteturas exclusivas. +2. **Alterar o idioma** – Construa agentes que operam exclusivamente em idiomas além do inglês, lidando com nuances com precisão. +3. **Especializar para domínios complexos** – Adapte prompts para setores altamente especializados como saúde, finanças ou jurídico. +4. **Ajustar tom e estilo** – Torne os agentes mais formais, casuais, criativos ou analíticos. +5. **Suportar casos de uso super customizados** – Utilize estruturas e formatações avançadas de prompt para atender requisitos detalhados e específicos do projeto. + +Este guia explora como acessar os prompts do CrewAI em um nível mais baixo, oferecendo controle granular sobre como os agentes pensam e interagem. + +## Entendendo o Sistema de Prompt do CrewAI + +Nos bastidores, o CrewAI adota um sistema de prompt modular que pode ser amplamente customizado: + +- **Templates de agente** – Determinam o modo como cada agente aborda o papel que lhe foi atribuído. +- **Prompt slices** – Controlam comportamentos especializados como tarefas, o uso de ferramentas e a estrutura de saída. +- **Tratamento de erros** – Definem como os agentes respondem a falhas, exceções ou timeouts. +- **Prompts específicos de ferramentas** – Definem instruções detalhadas para como as ferramentas são invocadas ou utilizadas. + +Confira os [templates de prompt originais no repositório do CrewAI](https://github.com/crewAIInc/crewAI/blob/main/src/crewai/translations/en.json) para ver como esses elementos são organizados. A partir daí, você pode sobrescrever ou adaptar conforme necessário para desbloquear comportamentos avançados. + +## Entendendo as Instruções de Sistema Padrão + + +**Questão de Transparência em Produção**: O CrewAI injeta automaticamente instruções padrão nos seus prompts que talvez você não conheça. Esta seção explica o que acontece nos bastidores e como obter controle total. + + +Ao definir um agente com `role`, `goal` e `backstory`, o CrewAI automaticamente adiciona instruções de sistema adicionais que controlam a formatação e o comportamento. Entender essas injeções padrão é essencial para sistemas em produção onde você precisa de total transparência nos prompts. + +### O Que CrewAI Injeta Automaticamente + +Baseado na configuração do seu agente, o CrewAI adiciona diferentes instruções padrão: + +#### Para Agentes Sem Ferramentas +```text +"I MUST use these formats, my job depends on it!" +``` + +#### Para Agentes Com Ferramentas +```text +"IMPORTANT: Use the following format in your response: + +Thought: you should always think about what to do +Action: the action to take, only one name of [tool_names] +Action Input: the input to the action, just a simple JSON object... +``` + +#### Para Saídas Estruturadas (JSON/Pydantic) +```text +"Ensure your final answer contains only the content in the following format: {output_format} +Ensure the final output does not include any code block markers like ```json or ```python." +``` + +### Visualizando o Prompt de Sistema Completo + +Para ver exatamente qual prompt está sendo enviado para seu LLM, você pode inspecionar o prompt gerado: + +```python +from crewai import Agent, Crew, Task +from crewai.utilities.prompts import Prompts + +# Crie seu agente +agent = Agent( + role="Data Analyst", + goal="Analyze data and provide insights", + backstory="You are an expert data analyst with 10 years of experience.", + verbose=True +) + +# Crie uma tarefa de exemplo +task = Task( + description="Analyze the sales data and identify trends", + expected_output="A detailed analysis with key insights and trends", + agent=agent +) + +# Crie o gerador de prompt +prompt_generator = Prompts( + agent=agent, + has_tools=len(agent.tools) > 0, + use_system_prompt=agent.use_system_prompt +) + +# Gere e inspecione o prompt atual +generated_prompt = prompt_generator.task_execution() + +# Imprima o prompt completo de sistema que será enviado ao LLM +if "system" in generated_prompt: + print("=== SYSTEM PROMPT ===") + print(generated_prompt["system"]) + print("\n=== USER PROMPT ===") + print(generated_prompt["user"]) +else: + print("=== COMPLETE PROMPT ===") + print(generated_prompt["prompt"]) + +# Você também pode ver como a descrição da tarefa é formatada +print("\n=== TASK CONTEXT ===") +print(f"Task Description: {task.description}") +print(f"Expected Output: {task.expected_output}") +``` + +### Sobrescrevendo Instruções Padrão + +Você tem várias opções para obter controle total sobre os prompts: + +#### Opção 1: Templates Personalizados (Recomendado) +```python +from crewai import Agent + +# Defina seu próprio template de sistema sem instruções padrão +custom_system_template = """You are {role}. {backstory} +Your goal is: {goal} + +Respond naturally and conversationally. Focus on providing helpful, accurate information.""" + +custom_prompt_template = """Task: {input} + +Please complete this task thoughtfully.""" + +agent = Agent( + role="Research Assistant", + goal="Help users find accurate information", + backstory="You are a helpful research assistant.", + system_template=custom_system_template, + prompt_template=custom_prompt_template, + use_system_prompt=True # Use mensagens separadas system/user +) +``` + +#### Opção 2: Arquivo de Prompt Personalizado +Crie um arquivo `custom_prompts.json` para sobrescrever slices específicas de prompt: + +```json +{ + "slices": { + "no_tools": "\nProvide your best answer in a natural, conversational way.", + "tools": "\nYou have access to these tools: {tools}\n\nUse them when helpful, but respond naturally.", + "formatted_task_instructions": "Format your response as: {output_format}" + } +} +``` + +Em seguida, utilize no seu crew: + +```python +crew = Crew( + agents=[agent], + tasks=[task], + prompt_file="custom_prompts.json", + verbose=True +) +``` + + +`agent.i18n` é mantido apenas para compatibilidade retroativa e está obsoleto. Para customização de prompts em tempo de execução, passe `prompt_file` para `Crew`. Para acesso programático aos slices de prompt, use diretamente o utilitário de i18n: + + +```python +from crewai.utilities.i18n import get_i18n + +i18n = get_i18n("custom_prompts.json") +format_slice = i18n.slice("format") +tool_prompt = i18n.tools("ask_question") +``` + +#### Opção 3: Desativar Prompts de Sistema para Modelos o1 +```python +agent = Agent( + role="Analyst", + goal="Analyze data", + backstory="Expert analyst", + use_system_prompt=False # Desativa separação de mensagens system prompt +) +``` + +### Depuração com Ferramentas de Observabilidade + +Para garantir transparência em produção, integre com plataformas de observabilidade para monitorar todos os prompts e interações com LLM. Isso permite que você veja exatamente quais prompts (incluindo instruções padrão) estão sendo enviados para os seus LLMs. + +Veja nossa [documentação sobre Observabilidade](/pt-BR/observability/overview) para guias detalhados de integração com diversas plataformas como Langfuse, MLflow, Weights & Biases e soluções de logging customizadas. + +### Boas Práticas para Produção + +1. **Sempre inspecione prompts gerados** antes de implantar em produção +2. **Use templates customizados** quando precisar de controle total sobre o conteúdo do prompt +3. **Integre ferramentas de observabilidade** para monitoramento contínuo de prompts (veja [docs de Observabilidade](/pt-BR/observability/overview)) +4. **Teste com diferentes LLMs** já que instruções padrão podem se comportar de maneira diferente em cada modelo +5. **Documente suas customizações de prompt** para transparência da equipe + + +As instruções padrão existem para garantir comportamento consistente nos agentes, mas podem interferir com requisitos de domínio específicos. Use as opções de customização acima para manter controle total sobre o comportamento do seu agente em sistemas de produção. + + +## Melhores Práticas para Gerenciar Arquivos de Prompt + +Ao realizar personalização de prompts em baixo nível, siga estas diretrizes para manter tudo organizado e fácil de manter: + +1. **Mantenha arquivos separados** – Armazene seus prompts personalizados em arquivos JSON dedicados fora do código principal. +2. **Controle de versão** – Acompanhe as alterações no seu repositório, garantindo documentação clara das mudanças nos prompts ao longo do tempo. +3. **Organize por modelo ou idioma** – Utilize nomes como `prompts_llama.json` ou `prompts_es.json` para identificar rapidamente configurações especializadas. +4. **Documente as alterações** – Adicione comentários ou mantenha um README detalhando o propósito e o escopo das customizações. +5. **Minimize alterações** – Sobrescreva apenas os slices específicos que realmente precisam de ajuste, mantendo a funcionalidade padrão para o restante. + +## O Jeito Mais Simples de Personalizar Prompts + +Uma abordagem direta é criar um arquivo JSON para os prompts que deseja sobrescrever e então indicar este arquivo no seu Crew: + +1. Crie um arquivo JSON com os slices de prompt atualizados. +2. Referencie este arquivo no parâmetro `prompt_file` do seu Crew. + +O CrewAI então mescla suas customizações com os padrões, assim você não precisa redefinir todos os prompts. Veja como: + +Para código que precisa ler slices de prompt diretamente, use `crewai.utilities.i18n.get_i18n()` com o mesmo arquivo de prompts em vez de ler `agent.i18n`. + +### Exemplo: Customização Básica de Prompt + +Crie um arquivo `custom_prompts.json` com os prompts que deseja modificar. Certifique-se de listar todos os prompts de nível superior que ele deve conter, não apenas suas alterações: + +```json +{ + "slices": { + "format": "When responding, follow this structure:\n\nTHOUGHTS: Your step-by-step thinking\nACTION: Any tool you're using\nRESULT: Your final answer or conclusion" + } +} +``` + +Integre assim: + +```python +from crewai import Agent, Crew, Task, Process + +# Crie agentes e tarefas normalmente +researcher = Agent( + role="Research Specialist", + goal="Find information on quantum computing", + backstory="You are a quantum physics expert", + verbose=True +) + +research_task = Task( + description="Research quantum computing applications", + expected_output="A summary of practical applications", + agent=researcher +) + +# Crie um crew com seu arquivo de prompt personalizado +crew = Crew( + agents=[researcher], + tasks=[research_task], + prompt_file="path/to/custom_prompts.json", + verbose=True +) + +# Execute o crew +result = crew.kickoff() +``` + +Com essas poucas edições, você conquista controle de baixo nível sobre como seus agentes se comunicam e solucionam tarefas. + +## Otimizando para Modelos Específicos + +Modelos diferentes respondem melhor a estruturas de prompt diferentes. Ajustes mais profundos podem aumentar significativamente o desempenho ao alinhar seus prompts às nuances de cada modelo. + +### Exemplo: Template de Prompt para Llama 3.3 + +Por exemplo, ao lidar com o Llama 3.3 da Meta, a personalização de baixo nível pode refletir a estrutura recomendada descrita em: +https://www.llama.com/docs/model-cards-and-prompt-formats/llama3_1/#prompt-template + +Veja um exemplo destacando como você pode ajustar um Agent para usar o Llama 3.3 em código: + +```python +from crewai import Agent, Crew, Task, Process +from crewai_tools import DirectoryReadTool, FileReadTool + +# Defina templates para mensagens de system, user (prompt) e assistant (resposta) +system_template = """<|begin_of_text|><|start_header_id|>system<|end_header_id|>{{ .System }}<|eot_id|>""" +prompt_template = """<|start_header_id|>user<|end_header_id|>{{ .Prompt }}<|eot_id|>""" +response_template = """<|start_header_id|>assistant<|end_header_id|>{{ .Response }}<|eot_id|>""" + +# Crie um Agent usando layouts específicos do Llama +principal_engineer = Agent( + role="Principal Engineer", + goal="Oversee AI architecture and make high-level decisions", + backstory="You are the lead engineer responsible for critical AI systems", + verbose=True, + llm="groq/llama-3.3-70b-versatile", # Usando o modelo Llama 3 + system_template=system_template, + prompt_template=prompt_template, + response_template=response_template, + tools=[DirectoryReadTool(), FileReadTool()] +) + +# Defina uma tarefa de exemplo +engineering_task = Task( + description="Review AI implementation files for potential improvements", + expected_output="A summary of key findings and recommendations", + agent=principal_engineer +) + +# Crie um Crew para a tarefa +llama_crew = Crew( + agents=[principal_engineer], + tasks=[engineering_task], + process=Process.sequential, + verbose=True +) + +# Execute o crew +result = llama_crew.kickoff() +print(result.raw) +``` + +Com essa configuração, você exerce controle abrangente e de baixo nível sobre seus fluxos de trabalho baseados em Llama sem precisar de um arquivo JSON separado. + +## Conclusão + +A personalização de prompts em baixo nível no CrewAI abre portas para casos de uso super customizados e complexos. Mantendo arquivos de prompt organizados (ou templates inline diretos), é possível acomodar diferentes modelos, idiomas e domínios especializados. Esse nível de flexibilidade garante que você possa criar exatamente o comportamento de IA que precisa, sabendo que o CrewAI ainda fornece padrões confiáveis quando você não sobrescreve. + + +Agora você tem a base para customizações avançadas de prompt no CrewAI. Seja adaptando para estruturas específicas de modelo ou restrições de domínio, esta abordagem de baixo nível permite moldar as interações dos agentes de forma altamente especializada. + diff --git a/docs/v1.15.13/pt-BR/guides/advanced/fingerprinting.mdx b/docs/v1.15.13/pt-BR/guides/advanced/fingerprinting.mdx new file mode 100644 index 0000000000..20f082d185 --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/advanced/fingerprinting.mdx @@ -0,0 +1,134 @@ +--- +title: Impressão digital +description: Saiba como usar o sistema de impressão digital da CrewAI para identificar e rastrear componentes de forma única durante todo o seu ciclo de vida. +icon: fingerprint +mode: "wide" +--- + +## Visão geral + +As impressões digitais na CrewAI fornecem uma maneira de identificar e rastrear componentes de forma única durante todo o seu ciclo de vida. Cada `Agent`, `Crew` e `Task` recebe automaticamente uma impressão digital única quando criado, que não pode ser sobrescrita manualmente. + +Essas impressões digitais podem ser usadas para: +- Auditoria e rastreamento do uso de componentes +- Garantir a integridade da identidade dos componentes +- Anexar metadados aos componentes +- Criar uma cadeia rastreável de operações + +## Como funciona a impressão digital + +Uma impressão digital é uma instância da classe `Fingerprint` do módulo `crewai.security`. Cada impressão digital contém: + +- Uma string UUID: Um identificador único para o componente, gerado automaticamente e que não pode ser definido manualmente +- Um timestamp de criação: Quando a impressão digital foi gerada, definido automaticamente e que não pode ser modificado manualmente +- Metadados: Um dicionário de informações adicionais que pode ser customizado + +As impressões digitais são geradas e atribuídas automaticamente quando um componente é criado. Cada componente expõe sua impressão digital por meio de uma propriedade de somente leitura. + +## Uso básico + +### Acessando impressões digitais + +```python +from crewai import Agent, Crew, Task + +# Criar componentes - impressões digitais são geradas automaticamente +agent = Agent( + role="Data Scientist", + goal="Analyze data", + backstory="Expert in data analysis" +) + +crew = Crew( + agents=[agent], + tasks=[] +) + +task = Task( + description="Analyze customer data", + expected_output="Insights from data analysis", + agent=agent +) + +# Acessar as impressões digitais +agent_fingerprint = agent.fingerprint +crew_fingerprint = crew.fingerprint +task_fingerprint = task.fingerprint + +# Imprimir as strings UUID +print(f"Agent fingerprint: {agent_fingerprint.uuid_str}") +print(f"Crew fingerprint: {crew_fingerprint.uuid_str}") +print(f"Task fingerprint: {task_fingerprint.uuid_str}") +``` + +### Trabalhando com metadados das impressões digitais + +Você pode adicionar metadados às impressões digitais para fornecer contexto adicional: + +```python +# Adicionar metadados à impressão digital do agente +agent.security_config.fingerprint.metadata = { + "version": "1.0", + "department": "Data Science", + "project": "Customer Analysis" +} + +# Acessar os metadados +print(f"Agent metadata: {agent.fingerprint.metadata}") +``` + +## Persistência das impressões digitais + +As impressões digitais foram projetadas para persistir e permanecer inalteradas durante todo o ciclo de vida de um componente. Se você modificar um componente, a impressão digital permanece a mesma: + +```python +original_fingerprint = agent.fingerprint.uuid_str + +# Modificar o agente +agent.goal = "New goal for analysis" + +# A impressão digital permanece inalterada +assert agent.fingerprint.uuid_str == original_fingerprint +``` + +## Impressões digitais determinísticas + +Apesar de não ser possível definir diretamente o UUID e o timestamp de criação, é possível criar impressões digitais determinísticas usando o método `generate` com uma seed: + +```python +from crewai.security import Fingerprint + +# Criar uma impressão digital determinística usando uma string seed +deterministic_fingerprint = Fingerprint.generate(seed="my-agent-id") + +# A mesma seed sempre gera a mesma impressão digital +same_fingerprint = Fingerprint.generate(seed="my-agent-id") +assert deterministic_fingerprint.uuid_str == same_fingerprint.uuid_str + +# Também é possível definir metadados +custom_fingerprint = Fingerprint.generate( + seed="my-agent-id", + metadata={"version": "1.0"} +) +``` + +## Uso avançado + +### Estrutura da impressão digital + +Cada impressão digital possui a seguinte estrutura: + +```python +from crewai.security import Fingerprint + +fingerprint = agent.fingerprint + +# String UUID - identificador único (gerado automaticamente) +uuid_str = fingerprint.uuid_str # e.g., "123e4567-e89b-12d3-a456-426614174000" + +# Timestamp de criação (gerado automaticamente) +created_at = fingerprint.created_at # Um objeto datetime + +# Metadados - informações adicionais (podem ser customizadas) +metadata = fingerprint.metadata # Um dicionário, padrão {} +``` \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/guides/agents/crafting-effective-agents.mdx b/docs/v1.15.13/pt-BR/guides/agents/crafting-effective-agents.mdx new file mode 100644 index 0000000000..b80fd6fe52 --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/agents/crafting-effective-agents.mdx @@ -0,0 +1,453 @@ +--- +title: Criando Agentes Eficazes +description: Aprenda as melhores práticas para projetar agentes de IA poderosos e especializados que colaboram de forma eficaz para resolver problemas complexos. +icon: robot +mode: "wide" +--- + +## A Arte e a Ciência do Design de Agentes + +No núcleo do CrewAI está o agente – uma entidade de IA especializada projetada para desempenhar funções específicas dentro de um framework colaborativo. Embora criar agentes básicos seja simples, criar agentes verdadeiramente eficazes que geram resultados excepcionais requer a compreensão de princípios fundamentais de design e boas práticas. + +Este guia vai ajudá-lo a dominar a arte de projetar agentes, permitindo criar personas de IA especializadas que colaboram de forma eficaz, pensam criticamente e produzem resultados de alta qualidade adaptados às suas necessidades específicas. + +### Por Que o Design de Agentes é Importante + +A forma como você define seus agentes impacta significativamente: + +1. **Qualidade do resultado**: Agentes bem projetados produzem resultados mais relevantes e de alta qualidade +2. **Eficiência da colaboração**: Agentes com habilidades complementares trabalham juntos de maneira mais eficiente +3. **Desempenho nas tarefas**: Agentes com papéis e objetivos claros executam tarefas de forma mais eficaz +4. **Escalabilidade do sistema**: Agentes bem projetados podem ser reutilizados em múltiplos crews e contextos + +Vamos explorar as melhores práticas para criar agentes que se destacam nessas dimensões. + +## A Regra 80/20: Foque Mais nas Tarefas do que nos Agentes + +Ao construir sistemas de IA eficazes, lembre-se deste princípio crucial: **80% do seu esforço deve ser dedicado ao design das tarefas, e apenas 20% à definição dos agentes**. + +Por quê? Porque mesmo o agente mais perfeitamente definido irá falhar com tarefas mal elaboradas, mas tarefas bem projetadas podem elevar até mesmo agentes simples. Isso significa: + +- Dedique a maior parte do seu tempo escrevendo instruções claras para as tarefas +- Defina entradas detalhadas e saídas esperadas +- Adicione exemplos e contexto para orientar a execução +- Reserve o tempo restante para o papel, objetivo e histórico do agente + +Isso não quer dizer que o design do agente não seja importante – ele é, sim. Mas o design das tarefas é onde ocorrem a maioria das falhas de execução, então priorize de acordo. + +## Princípios Fundamentais do Design de Agentes Eficazes + +### 1. O Framework Papel–Objetivo–Histórico + +Os agentes mais poderosos no CrewAI têm uma base sólida em três elementos-chave: + +#### Papel: A Função Especializada do Agente + +O papel define o que o agente faz e sua área de especialização. Ao criar papéis: + +- **Seja específico e especializado**: Em vez de “Escritor”, use “Especialista em Documentação Técnica” ou “Contador de Histórias Criativo” +- **Alinhe com profissões do mundo real**: Baseie os papéis em arquétipos profissionais reconhecíveis +- **Inclua expertise no domínio**: Especifique o campo de conhecimento do agente (ex: “Analista Financeiro especializado em tendências de mercado”) + +**Exemplos de papéis eficazes:** +```yaml +role: "Pesquisador Sênior de UX especializado em análise de entrevistas com usuários" +role: "Arquiteto de Software Full-Stack com expertise em sistemas distribuídos" +role: "Diretor de Comunicação Corporativa especializado em gestão de crises" +``` + +#### Objetivo: A Finalidade e Motivação do Agente + +O objetivo direciona os esforços do agente e orienta seu processo de tomada de decisão. Objetivos eficazes devem: + +- **Ser claros e focados em resultado**: Defina o que o agente precisa alcançar +- **Enfatizar padrões de qualidade**: Inclua expectativas sobre a qualidade do trabalho +- **Incorporar critérios de sucesso**: Ajude o agente a entender o que é considerado “bom” + +**Exemplos de objetivos eficazes:** +```yaml +goal: "Descobrir insights acionáveis analisando dados de entrevistas, identificando padrões recorrentes, necessidades não atendidas e oportunidades de melhoria" +goal: "Projetar arquiteturas de sistemas robustas e escaláveis que equilibrem performance, manutenção e custo-benefício" +goal: "Criar comunicações de crise claras e empáticas, abordando as preocupações das partes interessadas e protegendo a reputação organizacional" +``` + +#### Histórico: Experiência e Perspectiva do Agente + +O histórico aprofunda o agente, influenciando como ele aborda problemas e interage com os demais. Bons históricos: + +- **Estabelecem expertise e experiência**: Explique como o agente adquiriu suas habilidades +- **Definem estilo de trabalho e valores**: Descreva como o agente encara seu trabalho +- **Criam uma persona coesa**: Garanta que todos os elementos do histórico estejam alinhados ao papel e ao objetivo + +**Exemplos de históricos eficazes:** +```yaml +backstory: "Você passou 15 anos conduzindo e analisando pesquisas com usuários em grandes empresas de tecnologia. Tem talento para ler nas entrelinhas e identificar padrões que outros não enxergam. Acredita que uma boa experiência do usuário é invisível e que os melhores insights vêm tanto do que os usuários não dizem quanto do que dizem." + +backstory: "Com mais de 20 anos de experiência construindo sistemas distribuídos em larga escala, você desenvolveu uma abordagem pragmática para arquitetura de software. Viu sistemas bem sucedidos e fracassados e aprendeu lições valiosas com ambos. Equilibra as melhores práticas teóricas com restrições práticas e sempre considera os aspectos de manutenção e operação em seus projetos." + +backstory: "Como um profissional de comunicação experiente que já orientou múltiplas organizações em crises de grande repercussão, você entende a importância da transparência, agilidade e empatia em respostas a crises. Tem uma abordagem metódica para criar mensagens que abordam preocupações mantendo a credibilidade da organização." +``` + +### 2. Especialistas em vez de Generalistas + +Agentes desempenham muito melhor quando recebem papéis especializados em vez de papéis genéricos. Um agente altamente focado gera resultados mais precisos e relevantes: + +**Genérico (Menos Eficaz):** +```yaml +role: "Writer" +``` + +**Especializado (Mais Eficaz):** +```yaml +role: "Redator Técnico de Blog especializado em explicar conceitos complexos de IA para públicos não técnicos" +``` + +**Vantagens dos Especialistas:** +- Compreensão mais clara do resultado esperado +- Performance mais consistente +- Melhor alinhamento com tarefas específicas +- Maior capacidade de fazer julgamentos específicos do domínio + +### 3. Equilibrando Especialização e Versatilidade + +Agentes eficazes equilibram bem a especialização (fazer uma coisa muito bem) e a versatilidade (adaptar-se a diversas situações): + +- **Especialize no papel, seja versátil na aplicação**: Crie agentes com habilidades especializadas aplicáveis em múltiplos contextos +- **Evite definições excessivamente restritas**: Garanta que agentes possam lidar com variações dentro de sua área de expertise +- **Considere o contexto colaborativo**: Projete agentes cujas especialidades complementem os demais do crew + +### 4. Definição Nível Apropriado de Expertise + +O nível de expertise atribuído ao agente determina como ele realiza as tarefas: + +- **Agentes iniciantes**: Bons para tarefas simples, brainstorm, rascunhos iniciais +- **Agentes intermediários**: Adequados para a maioria das tarefas padrão com execução confiável +- **Agentes especialistas**: Ideais para tarefas complexas e especializadas que exigem profundidade e nuances +- **Agentes de classe mundial**: Reservados para tarefas críticas onde a qualidade excepcional é essencial + +Escolha o nível de expertise baseado na complexidade da tarefa e no padrão de qualidade exigido. Em crews colaborativos, tendem a funcionar melhor equipes com níveis variados de expertise, reservando maior especialização para as funções mais chave. + +## Exemplos Práticos: Antes e Depois + +Veja exemplos de definições de agentes antes e depois de aplicar essas boas práticas: + +### Exemplo 1: Agente de Criação de Conteúdo + +**Antes:** +```yaml +role: "Writer" +goal: "Write good content" +backstory: "You are a writer who creates content for websites." +``` + +**Depois:** +```yaml +role: "Estrategista de Conteúdo B2B para Tecnologia" +goal: "Criar conteúdos envolventes e tecnicamente precisos, explicando tópicos complexos em linguagem acessível, promovendo engajamento e apoiando os objetivos do negócio" +backstory: "Você passou uma década criando conteúdos para empresas líderes em tecnologia, especializando-se na tradução de conceitos técnicos para públicos empresariais. É ótimo em pesquisa, entrevistas com especialistas e estruturação da informação para máxima clareza e impacto. Acredita que o melhor conteúdo B2B educa antes de vender, construindo confiança através da expertise genuína e não do hype de marketing." +``` + +### Exemplo 2: Agente de Pesquisa + +**Antes:** +```yaml +role: "Researcher" +goal: "Find information" +backstory: "You are good at finding information online." +``` + +**Depois:** +```yaml +role: "Especialista em Pesquisa Acadêmica de Tecnologias Emergentes" +goal: "Descobrir e sintetizar pesquisas de ponta, identificando tendências, metodologias e resultados principais, avaliando a qualidade e confiabilidade das fontes" +backstory: "Com formação em ciência da computação e biblioteconomia, você dominou a arte da pesquisa digital. Já trabalhou com equipes de pesquisa em universidades de prestígio e sabe como navegar bancos de dados acadêmicos, avaliar a qualidade das pesquisas e sintetizar descobertas em diferentes áreas. Seu método é rigoroso: sempre cruza informações e rastreia a origem dos dados antes de chegar a conclusões." +``` + +## Criando Tarefas Eficazes para seus Agentes + +Embora o design dos agentes seja importante, o design das tarefas é crítico para uma boa execução. Aqui estão as melhores práticas para definir tarefas que irão impulsionar o sucesso dos seus agentes: + +### A Anatomia de uma Tarefa Eficaz + +Uma tarefa bem projetada tem dois componentes-chave com propósitos distintos: + +#### Descrição da Tarefa: O Processo +A descrição deve focar no que fazer e como fazer, incluindo: +- Instruções detalhadas de execução +- Contexto e informações de fundo +- Escopo e restrições +- Passos do processo a serem seguidos + +#### Saída Esperada: O Entregável +A saída esperada deve definir como o resultado final deve ser apresentado: +- Especificações de formato (markdown, JSON, etc.) +- Estrutura exigida +- Critérios de qualidade +- Exemplos de bons entregáveis (sempre que possível) + +### Melhores Práticas para Design de Tarefas + +#### 1. Propósito Único, Saída Única +Tarefas funcionam melhor quando são focadas em um objetivo claro: + +**Exemplo Ruim (Muito Abrangente):** +```yaml +task_description: "Research market trends, analyze the data, and create a visualization." +``` + +**Exemplo Bom (Focado):** +```yaml +# Task 1 +research_task: + description: "Research the top 5 market trends in the AI industry for 2024." + expected_output: "A markdown list of the 5 trends with supporting evidence." + +# Task 2 +analysis_task: + description: "Analyze the identified trends to determine potential business impacts." + expected_output: "A structured analysis with impact ratings (High/Medium/Low)." + +# Task 3 +visualization_task: + description: "Create a visual representation of the analyzed trends." + expected_output: "A description of a chart showing trends and their impact ratings." +``` + +#### 2. Seja Explícito Sobre Entradas e Saídas +Sempre especifique claramente quais são as entradas da tarefa e como deve ser o resultado: + +**Exemplo:** +```yaml +analysis_task: + description: > + Analyze the customer feedback data from the CSV file. + Focus on identifying recurring themes related to product usability. + Consider sentiment and frequency when determining importance. + expected_output: > + A markdown report with the following sections: + 1. Executive summary (3-5 bullet points) + 2. Top 3 usability issues with supporting data + 3. Recommendations for improvement +``` + +#### 3. Inclua Propósito e Contexto +Explique por que a tarefa importa e como ela se encaixa no fluxo de trabalho maior: + +**Exemplo:** +```yaml +competitor_analysis_task: + description: > + Analyze our three main competitors' pricing strategies. + This analysis will inform our upcoming pricing model revision. + Focus on identifying patterns in how they price premium features + and how they structure their tiered offerings. +``` + +#### 4. Use Ferramentas de Saída Estruturada +Para saídas legíveis por máquina, especifique claramente o formato: + +**Exemplo:** +```yaml +data_extraction_task: + description: "Extract key metrics from the quarterly report." + expected_output: "JSON object with the following keys: revenue, growth_rate, customer_acquisition_cost, and retention_rate." +``` + +## Erros Comuns a Evitar + +Baseando-se em experiências de casos reais, estes são os erros mais comuns no design de agentes e tarefas: + +### 1. Instruções de Tarefa Pouco Claras + +**Problema:** Tarefas sem detalhes suficientes, dificultando a execução pelo agente. + +**Exemplo de Design Ruim:** +```yaml +research_task: + description: "Research AI trends." + expected_output: "A report on AI trends." +``` + +**Versão Melhorada:** +```yaml +research_task: + description: > + Research the top emerging AI trends for 2024 with a focus on: + 1. Enterprise adoption patterns + 2. Technical breakthroughs in the past 6 months + 3. Regulatory developments affecting implementation + + For each trend, identify key companies, technologies, and potential business impacts. + expected_output: > + A comprehensive markdown report with: + - Executive summary (5 bullet points) + - 5-7 major trends with supporting evidence + - For each trend: definition, examples, and business implications + - References to authoritative sources +``` + +### 2. "Tarefas-Deus" Que Tentam Fazer Demais + +**Problema:** Tarefas que combinam múltiplas operações complexas em um único conjunto de instruções. + +**Exemplo de Design Ruim:** +```yaml +comprehensive_task: + description: "Research market trends, analyze competitor strategies, create a marketing plan, and design a launch timeline." +``` + +**Versão Melhorada:** +Divida em tarefas sequenciais e focadas: +```yaml +# Task 1: Research +market_research_task: + description: "Research current market trends in the SaaS project management space." + expected_output: "A markdown summary of key market trends." + +# Task 2: Competitive Analysis +competitor_analysis_task: + description: "Analyze strategies of the top 3 competitors based on the market research." + expected_output: "A comparison table of competitor strategies." + context: [market_research_task] + +# Continue with additional focused tasks... +``` + +### 3. Descrição e Saída Esperada Desalinhadas + +**Problema:** O que a descrição pede não corresponde ao que a saída esperada especifica. + +**Exemplo de Design Ruim:** +```yaml +analysis_task: + description: "Analyze customer feedback to find areas of improvement." + expected_output: "A marketing plan for the next quarter." +``` + +**Versão Melhorada:** +```yaml +analysis_task: + description: "Analyze customer feedback to identify the top 3 areas for product improvement." + expected_output: "A report listing the 3 priority improvement areas with supporting customer quotes and data points." +``` + +### 4. Não Entender o Processo Você Mesmo + +**Problema:** Pedir para o agente executar tarefas que você mesmo não entende completamente. + +**Solução:** +1. Tente realizar a tarefa manualmente primeiro +2. Documente o processo, pontos de decisão e fontes de informação +3. Use esta documentação como base para a descrição da tarefa + +### 5. Uso Prematuro de Estruturas Hierárquicas + +**Problema:** Criar hierarquias de agentes desnecessariamente complexas quando processos sequenciais seriam suficientes. + +**Solução:** Comece com processos sequenciais e só adote modelos hierárquicos quando a complexidade do fluxo de trabalho realmente justificar. + +### 6. Definições Genéricas ou Pouco Claras de Agentes + +**Problema:** Definições genéricas de agentes levam a resultados genéricos. + +**Exemplo de Design Ruim:** +```yaml +agent: + role: "Business Analyst" + goal: "Analyze business data" + backstory: "You are good at business analysis." +``` + +**Versão Melhorada:** +```yaml +agent: + role: "Especialista em Métricas SaaS focado em startups em fase de crescimento" + goal: "Identificar insights acionáveis em dados de negócios que possam impactar diretamente a retenção de clientes e o crescimento de receita" + backstory: "Com mais de 10 anos analisando modelos de negócios SaaS, você desenvolveu um olhar apurado para as métricas que realmente impulsionam crescimento sustentável. Já ajudou diversas empresas a identificar pontos de alavancagem que mudaram o rumo dos negócios. Acredita em conectar dados a recomendações específicas e acionáveis, e não apenas a observações genéricas." +``` + +## Estratégias Avançadas de Design de Agentes + +### Projetando para Colaboração + +Ao criar agentes que trabalharão em conjunto em um crew, pense em: + +- **Habilidades complementares**: Projete agentes com competências distintas, porém complementares +- **Pontos de transferência**: Defina interfaces claras para a passagem de trabalho entre agentes +- **Tensão construtiva**: Às vezes, agentes com perspectivas um pouco diferentes promovem melhores resultados por meio de diálogos construtivos + +Por exemplo, um crew de criação de conteúdo pode incluir: + +```yaml +# Research Agent +role: "Research Specialist for technical topics" +goal: "Gather comprehensive, accurate information from authoritative sources" +backstory: "You are a meticulous researcher with a background in library science..." + +# Writer Agent +role: "Technical Content Writer" +goal: "Transform research into engaging, clear content that educates and informs" +backstory: "You are an experienced writer who excels at explaining complex concepts..." + +# Editor Agent +role: "Content Quality Editor" +goal: "Ensure content is accurate, well-structured, and polished while maintaining consistency" +backstory: "With years of experience in publishing, you have a keen eye for detail..." +``` + +### Criando Usuários Especializados de Ferramentas + +Alguns agentes podem ser projetados para explorar certas ferramentas de maneira eficiente: + +```yaml +role: "Data Analysis Specialist" +goal: "Derive meaningful insights from complex datasets through statistical analysis" +backstory: "With a background in data science, you excel at working with structured and unstructured data..." +tools: [PythonREPLTool, DataVisualizationTool, CSVAnalysisTool] +``` + +### Personalizando Agentes para Capacidades do LLM + +Diferentes LLMs têm pontos fortes distintos. Projete seus agentes levando essas capacidades em conta: + +```yaml +# For complex reasoning tasks +analyst: + role: "Data Insights Analyst" + goal: "..." + backstory: "..." + llm: openai/gpt-4o + +# For creative content +writer: + role: "Creative Content Writer" + goal: "..." + backstory: "..." + llm: anthropic/claude-3-opus +``` + +## Testando e Iterando no Design de Agentes + +A construção de agentes geralmente é um processo iterativo. Veja como colocar em prática: + +1. **Comece com um protótipo**: Crie uma definição inicial do agente +2. **Teste com tarefas de exemplo**: Avalie o desempenho em tarefas representativas +3. **Analise os resultados**: Identifique pontos fortes e fracos +4. **Refine a definição**: Ajuste papel, objetivo e histórico conforme suas observações +5. **Teste em colaboração**: Avalie como o agente se sai em conjunto no crew + +## Conclusão + +Criar agentes eficazes é tanto arte quanto ciência. Ao definir cuidadosamente papéis, objetivos e históricos alinhados às suas necessidades, e combinar isso com tarefas bem projetadas, você constrói colaboradores de IA especializados capazes de gerar resultados excepcionais. + +Lembre-se de que o design de agentes e tarefas é um processo iterativo. Comece com essas boas práticas, observe os agentes em ação e refine sua abordagem conforme necessário. E sempre tenha em mente a regra 80/20 – concentre a maior parte do esforço em criar tarefas claras e focadas para tirar o melhor de seus agentes. + + +Parabéns! Agora você entende os princípios e práticas do design eficaz de agentes. Aplique estas técnicas para criar agentes poderosos e especializados que trabalham juntos perfeitamente e realizam tarefas complexas. + + +## Próximos Passos + +- Experimente diferentes configurações de agentes para o seu caso de uso +- Aprenda sobre [como construir seu primeiro crew](/pt-BR/guides/crews/first-crew) para ver como agentes trabalham juntos +- Explore os [CrewAI Flows](/pt-BR/guides/flows/first-flow) para uma orquestração mais avançada diff --git a/docs/v1.15.13/pt-BR/guides/coding-tools/agents-md.mdx b/docs/v1.15.13/pt-BR/guides/coding-tools/agents-md.mdx new file mode 100644 index 0000000000..771fd807b2 --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/coding-tools/agents-md.mdx @@ -0,0 +1,61 @@ +--- +title: Ferramentas de Codificação +description: Use o AGENTS.md para guiar agentes de codificação e IDEs em seus projetos CrewAI. +icon: terminal +mode: "wide" +--- + +## Por que AGENTS.md + +`AGENTS.md` é um arquivo de instruções leve e local do repositório que fornece aos agentes de codificação orientações consistentes e específicas do projeto. Mantenha-o na raiz do projeto e trate-o como a fonte da verdade para como você deseja que os assistentes trabalhem: convenções, comandos, notas de arquitetura e proteções. + +## Criar um Projeto com o CLI + +Use o CLI do CrewAI para criar a estrutura de um projeto, e o `AGENTS.md` será automaticamente adicionado na raiz. + +```bash +# Crew +crewai create crew my_crew + +# Flow +crewai create flow my_flow + +# Tool repository +crewai tool create my_tool +``` + +## Configuração de Ferramentas: Direcione Assistentes para o AGENTS.md + +### Codex + +O Codex pode ser guiado por arquivos `AGENTS.md` colocados no seu repositório. Use-os para fornecer contexto persistente do projeto, como convenções, comandos e expectativas de fluxo de trabalho. + +### Claude Code + +O Claude Code armazena a memória do projeto em `CLAUDE.md`. Você pode inicializá-lo com `/init` e editá-lo usando `/memory`. O Claude Code também suporta importações dentro do `CLAUDE.md`, então você pode adicionar uma única linha como `@AGENTS.md` para incluir as instruções compartilhadas sem duplicá-las. + +Você pode simplesmente usar: + +```bash +mv AGENTS.md CLAUDE.md +``` + +### Gemini CLI e Google Antigravity + +O Gemini CLI e o Antigravity carregam um arquivo de contexto do projeto (padrão: `GEMINI.md`) da raiz do repositório e diretórios pais. Você pode configurá-lo para ler o `AGENTS.md` em vez disso (ou além) definindo `context.fileName` nas configurações do Gemini CLI. Por exemplo, defina apenas para `AGENTS.md`, ou inclua tanto `AGENTS.md` quanto `GEMINI.md` se quiser manter o formato de cada ferramenta. + +Você pode simplesmente usar: + +```bash +mv AGENTS.md GEMINI.md +``` + +### Cursor + +O Cursor suporta `AGENTS.md` como arquivo de instruções do projeto. Coloque-o na raiz do projeto para fornecer orientação ao assistente de codificação do Cursor. + +### Windsurf + +O Claude Code fornece uma integração oficial com o Windsurf. Se você usa o Claude Code dentro do Windsurf, siga a orientação do Claude Code acima e importe o `AGENTS.md` a partir do `CLAUDE.md`. + +Se você está usando o assistente nativo do Windsurf, configure o recurso de regras ou instruções do projeto (se disponível) para ler o `AGENTS.md` ou cole o conteúdo diretamente. diff --git a/docs/v1.15.13/pt-BR/guides/coding-tools/build-with-ai.mdx b/docs/v1.15.13/pt-BR/guides/coding-tools/build-with-ai.mdx new file mode 100644 index 0000000000..05bf90e32b --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/coding-tools/build-with-ai.mdx @@ -0,0 +1,214 @@ +--- +title: "Construa com IA" +description: "Tudo o que agentes de codificação com IA precisam para criar, implantar e escalar com CrewAI — skills, documentação legível por máquina, implantação e recursos enterprise." +icon: robot +mode: "wide" +--- + +# Construa com IA + +O CrewAI é nativo de IA. Esta página reúne o que um agente de codificação com IA precisa para construir com CrewAI — seja Claude Code, Codex, Cursor, Gemini CLI ou qualquer outro assistente que ajude um desenvolvedor a entregar crews e flows. + +### Agentes de codificação compatíveis + + + + + + + + + + + Esta página serve para humanos e para assistentes de IA. Se você é um agente de codificação, comece por **Skills** para obter contexto do CrewAI e depois use **llms.txt** para acesso completo à documentação. + + +--- + +## 1. Skills — ensine CrewAI ao seu agente + +**Skills** são pacotes de instruções que dão aos agentes de codificação conhecimento profundo do CrewAI — como estruturar Flows, configurar Crews, usar ferramentas e seguir convenções do framework. + + + + Anthropic + As skills do CrewAI estão no **plugin marketplace do Claude Code** — o mesmo canal usado por empresas líderes em IA: + ```shell + /plugin marketplace add crewAIInc/skills + /plugin install crewai-skills@crewai-plugins + /reload-plugins + ``` + + Quatro skills são ativadas automaticamente quando você faz perguntas relevantes sobre CrewAI: + + | Skill | Quando é usada | + |-------|----------------| + | `getting-started` | Novos projetos, escolha entre `LLM.call()` / `Agent` / `Crew` / `Flow`, arquivos `crew.jsonc` / `main.py` | + | `design-agent` | Configurar agentes — papel, objetivo, história, ferramentas, LLMs, memória, guardrails | + | `design-task` | Descrever tarefas, dependências, saída estruturada (`output_pydantic`, `output_json`), revisão humana | + | `ask-docs` | Consultar o [servidor MCP da documentação CrewAI](https://docs.crewai.com/mcp) em tempo real para detalhes de API | + + + Funciona com Claude Code, Codex, Cursor, Gemini CLI ou qualquer agente de codificação: + ```shell + npx skills add crewaiinc/skills + ``` + Obtido do [registro skills.sh](https://skills.sh/crewaiinc/skills). + + + + + + Use um dos métodos acima — o plugin marketplace do Claude Code ou `npx skills add`. Ambos instalam o pacote oficial [crewAIInc/skills](https://github.com/crewAIInc/skills). + + + O pacote ensina ao seu agente: + - **Flows** — apps com estado, passos e disparo de crews + - **Crews e agentes** — padrões JSON-first (`crew.jsonc`, `agents/*.jsonc`), papéis, tarefas, delegação + - **Ferramentas e integrações** — busca, APIs, servidores MCP e ferramentas comuns do CrewAI + - **Estrutura do projeto** — scaffolds da CLI e convenções de repositório + - **Padrões atualizados** — alinhado à documentação e às melhores práticas atuais do CrewAI + + + Seu agente pode estruturar e construir projetos CrewAI sem você precisar reexplicar o framework a cada sessão. + + + + + + Como skills funcionam em agentes CrewAI — injeção, ativação e padrões. + + + Visão geral do pacote crewAIInc/skills e do que ele inclui. + + + Configure o AGENTS.md para Claude Code, Codex, Cursor e Gemini CLI. + + + Listagem oficial — skills, estatísticas de instalação e auditorias. + + + +--- + +## 2. llms.txt — documentação legível por máquina + +O CrewAI publica um arquivo `llms.txt` que dá aos assistentes de IA acesso direto à documentação completa em formato legível por máquinas. + +``` +https://docs.crewai.com/llms.txt +``` + + + + [`llms.txt`](https://llmstxt.org/) é um padrão emergente para tornar a documentação consumível por grandes modelos de linguagem. Em vez de fazer scraping de HTML, seu agente pode buscar um único arquivo de texto estruturado com o conteúdo necessário. + + O `llms.txt` do CrewAI **já está no ar** — seu agente pode usar agora. + + + Indique ao agente de codificação a URL quando precisar da referência do CrewAI: + + ``` + Fetch https://docs.crewai.com/llms.txt for CrewAI documentation. + ``` + + Muitos agentes (Claude Code, Cursor etc.) conseguem buscar URLs diretamente. O arquivo contém documentação estruturada sobre conceitos, APIs e guias do CrewAI. + + + - **Sem scraping** — conteúdo limpo e estruturado em uma requisição + - **Sempre atualizado** — servido diretamente de docs.crewai.com + - **Otimizado para LLMs** — formatado para janelas de contexto, não para navegadores + - **Complementa as skills** — skills ensinam padrões; llms.txt fornece referência + + + +--- + +## 3. Implantação enterprise + +Do crew local à produção no **CrewAI AMP** (Agent Management Platform) em minutos. + + + + Estruture e teste seu crew ou flow: + ```bash + crewai create crew my_crew + cd my_crew + crewai run + ``` + + + Garanta que a estrutura do projeto está pronta: + ```bash + crewai deploy --prepare + ``` + Veja o [guia de preparação](https://docs-platform.crewai.com/platform/pt-BR/guides/prepare-for-deployment) para detalhes de estrutura e requisitos. + + + Envie para a plataforma CrewAI AMP: + ```bash + crewai deploy + ``` + Também é possível implantar pela [integração com GitHub](https://docs-platform.crewai.com/platform/pt-BR/guides/deploy-to-amp) ou pelo [Crew Studio](https://docs-platform.crewai.com/platform/pt-BR/guides/enable-crew-studio). + + + O crew implantado recebe um endpoint REST. Integre em qualquer aplicação: + ```bash + curl -X POST https://app.crewai.com/api/v1/crews//kickoff \ + -H "Authorization: Bearer $CREWAI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{"inputs": {"topic": "AI agents"}}' + ``` + + + + + + Guia completo de implantação — CLI, GitHub e Crew Studio. + + + Visão da plataforma — o que o AMP oferece para crews em produção. + + + +--- + +## 4. Recursos enterprise + +O CrewAI AMP foi feito para equipes em produção. Além da implantação, você obtém: + + + + Traces de execução, logs e métricas de desempenho para cada execução de crew. Monitore decisões de agentes, chamadas de ferramentas e conclusão de tarefas em tempo real. + + + Interface no-code/low-code para criar, personalizar e implantar crews visualmente — exporte para código ou implante direto. + + + Transmita eventos em tempo real das execuções para seus sistemas. Integre com Slack, Zapier ou qualquer consumidor de webhook. + + + SSO, RBAC e controles em nível de organização. Gerencie quem pode criar, implantar e acessar crews. + + + Publique e compartilhe ferramentas customizadas na organização. Instale ferramentas da comunidade a partir do registro. + + + Execute o CrewAI AMP na sua infraestrutura. Capacidades completas da plataforma com residência de dados e controles de conformidade. + + + + + + Para equipes que precisam levar fluxos de agentes de IA do protótipo à produção — com observabilidade, controles de acesso e infraestrutura escalável. De startups a grandes empresas, o AMP cuida da complexidade operacional para você focar nos agentes. + + + - **Nuvem (app.crewai.com)** — gerenciada pela CrewAI, caminho mais rápido para produção + - **Factory (self-hosted)** — na sua infraestrutura para controle total dos dados + - **Híbrido** — combine nuvem e self-hosted conforme a sensibilidade dos dados + + + + + Cadastre-se e leve seu primeiro crew à produção. + diff --git a/docs/v1.15.13/pt-BR/guides/concepts/evaluating-use-cases.mdx b/docs/v1.15.13/pt-BR/guides/concepts/evaluating-use-cases.mdx new file mode 100644 index 0000000000..6d6e31f834 --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/concepts/evaluating-use-cases.mdx @@ -0,0 +1,504 @@ +--- +title: Avaliando Casos de Uso para CrewAI +description: Aprenda a avaliar as necessidades da sua aplicação de IA e escolher a abordagem certa entre Crews e Flows com base nos requisitos de complexidade e precisão. +icon: scale-balanced +mode: "wide" +--- + +## Entendendo o Framework de Decisão + +Ao construir aplicações de IA com CrewAI, uma das decisões mais importantes que você tomará é escolher a abordagem correta para o seu caso de uso específico. Você deve usar uma Crew? Um Flow? Uma combinação dos dois? Este guia vai ajudar você a avaliar seus requisitos e tomar decisões arquitetônicas embasadas. + +No centro dessa decisão está o entendimento da relação entre **complexidade** e **precisão** em sua aplicação: + + + Matriz de Complexidade vs. Precisão + + +Essa matriz ajuda a visualizar como diferentes abordagens se alinham com os requisitos variados de complexidade e precisão. Vamos explorar o significado de cada quadrante e como isso orienta suas escolhas arquiteturais. + +## Explicando a Matriz Complexidade-Precisão + +### O que é Complexidade? + +No contexto das aplicações CrewAI, **complexidade** refere-se a: + +- O número de etapas ou operações distintas necessárias +- A diversidade de tarefas que precisam ser realizadas +- As interdependências entre diferentes componentes +- A necessidade de lógica condicional e ramificações +- A sofisticação do fluxo de trabalho como um todo + +### O que é Precisão? + +**Precisão** nesse contexto refere-se a: + +- O grau de exatidão exigido no resultado final +- A necessidade de resultados estruturados e previsíveis +- A importância da reprodutibilidade +- O nível de controle necessário sobre cada etapa +- A tolerância à variação nos resultados + +### Os Quatro Quadrantes + +#### 1. Baixa Complexidade, Baixa Precisão + +**Características:** +- Tarefas simples e diretas +- Tolerância a alguma variação nos resultados +- Número limitado de etapas +- Aplicações criativas ou exploratórias + +**Abordagem Recomendada:** Crews simples com poucos agentes + +**Exemplos de Casos de Uso:** +- Geração básica de conteúdo +- Brainstorming de ideias +- Tarefas simples de sumarização +- Assistência à escrita criativa + +#### 2. Baixa Complexidade, Alta Precisão + +**Características:** +- Fluxos de trabalho simples que exigem resultados exatos e estruturados +- Necessidade de resultados reproduzíveis +- Poucas etapas, mas alto requisito de precisão +- Frequentemente envolve processamento ou transformação de dados + +**Abordagem Recomendada:** Flows com chamadas diretas a LLM ou Crews simples com saídas estruturadas + +**Exemplos de Casos de Uso:** +- Extração e transformação de dados +- Preenchimento e validação de formulários +- Geração estruturada de conteúdo (JSON, XML) +- Tarefas simples de classificação + +#### 3. Alta Complexidade, Baixa Precisão + +**Características:** +- Processos multiestágio com muitas etapas +- Saídas criativas ou exploratórias +- Interações complexas entre componentes +- Tolerância à variação nos resultados finais + +**Abordagem Recomendada:** Crews complexas com múltiplos agentes especializados + +**Exemplos de Casos de Uso:** +- Pesquisa e análise +- Pipelines de criação de conteúdo +- Análise exploratória de dados +- Solução criativa de problemas + +#### 4. Alta Complexidade, Alta Precisão + +**Características:** +- Fluxos de trabalho complexos que requerem saídas estruturadas +- Múltiplas etapas interdependentes com rígida exigência de precisão +- Necessidade tanto de processamento sofisticado quanto de resultados precisos +- Frequentemente aplicações críticas + +**Abordagem Recomendada:** Flows orquestrando múltiplas Crews com etapas de validação + +**Exemplos de Casos de Uso:** +- Sistemas corporativos de suporte à decisão +- Pipelines complexos de processamento de dados +- Processamento de documentos em múltiplos estágios +- Aplicações em indústrias reguladas + +## Escolhendo Entre Crews e Flows + +### Quando Escolher Crews + +Crews são ideais quando: + +1. **Você precisa de inteligência colaborativa** - Múltiplos agentes com especializações diferentes precisam trabalhar juntos +2. **O problema requer pensamento emergente** - A solução se beneficia de diferentes perspectivas e abordagens +3. **A tarefa é principalmente criativa ou analítica** - O trabalho envolve pesquisa, criação de conteúdo ou análise +4. **Você valoriza adaptabilidade mais do que estrutura rígida** - O fluxo de trabalho pode se beneficiar da autonomia dos agentes +5. **O formato da saída pode ser um pouco flexível** - Alguma variação na estrutura do resultado é aceitável + +```python +# Example: Research Crew for market analysis +from crewai import Agent, Crew, Process, Task + +# Create specialized agents +researcher = Agent( + role="Market Research Specialist", + goal="Find comprehensive market data on emerging technologies", + backstory="You are an expert at discovering market trends and gathering data." +) + +analyst = Agent( + role="Market Analyst", + goal="Analyze market data and identify key opportunities", + backstory="You excel at interpreting market data and spotting valuable insights." +) + +# Define their tasks +research_task = Task( + description="Research the current market landscape for AI-powered healthcare solutions", + expected_output="Comprehensive market data including key players, market size, and growth trends", + agent=researcher +) + +analysis_task = Task( + description="Analyze the market data and identify the top 3 investment opportunities", + expected_output="Analysis report with 3 recommended investment opportunities and rationale", + agent=analyst, + context=[research_task] +) + +# Create the crew +market_analysis_crew = Crew( + agents=[researcher, analyst], + tasks=[research_task, analysis_task], + process=Process.sequential, + verbose=True +) + +# Run the crew +result = market_analysis_crew.kickoff() +``` + +### Quando Escolher Flows + +Flows são ideais quando: + +1. **Você precisa de controle preciso da execução** - O fluxo de trabalho exige sequenciamento exato e gerenciamento de estado +2. **A aplicação tem requisitos complexos de estado** - Você precisa manter e transformar estado ao longo de múltiplas etapas +3. **Você precisa de saídas estruturadas e previsíveis** - A aplicação exige resultados consistentes e formatados +4. **O fluxo de trabalho envolve lógica condicional** - Caminhos diferentes precisam ser seguidos com base em resultados intermediários +5. **Você precisa combinar IA com código procedural** - A solução demanda tanto capacidades de IA quanto programação tradicional + +```python +# Example: Customer Support Flow with structured processing +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel +from typing import List, Dict + +# Define structured state +class SupportTicketState(BaseModel): + ticket_id: str = "" + customer_name: str = "" + issue_description: str = "" + category: str = "" + priority: str = "medium" + resolution: str = "" + satisfaction_score: int = 0 + +class CustomerSupportFlow(Flow[SupportTicketState]): + @start() + def receive_ticket(self): + # In a real app, this might come from an API + self.state.ticket_id = "TKT-12345" + self.state.customer_name = "Alex Johnson" + self.state.issue_description = "Unable to access premium features after payment" + return "Ticket received" + + @listen(receive_ticket) + def categorize_ticket(self, _): + # Use a direct LLM call for categorization + from crewai import LLM + llm = LLM(model="openai/gpt-4o-mini") + + prompt = f""" + Categorize the following customer support issue into one of these categories: + - Billing + - Account Access + - Technical Issue + - Feature Request + - Other + + Issue: {self.state.issue_description} + + Return only the category name. + """ + + self.state.category = llm.call(prompt).strip() + return self.state.category + + @router(categorize_ticket) + def route_by_category(self, category): + # Route to different handlers based on category + return category.lower().replace(" ", "_") + + @listen("billing") + def handle_billing_issue(self): + # Handle billing-specific logic + self.state.priority = "high" + # More billing-specific processing... + return "Billing issue handled" + + @listen("account_access") + def handle_access_issue(self): + # Handle access-specific logic + self.state.priority = "high" + # More access-specific processing... + return "Access issue handled" + + # Additional category handlers... + + @listen("billing", "account_access", "technical_issue", "feature_request", "other") + def resolve_ticket(self, resolution_info): + # Final resolution step + self.state.resolution = f"Issue resolved: {resolution_info}" + return self.state.resolution + +# Run the flow +support_flow = CustomerSupportFlow() +result = support_flow.kickoff() +``` + +### Quando Combinar Crews e Flows + +As aplicações mais sofisticadas frequentemente se beneficiam da combinação de Crews e Flows: + +1. **Processos complexos em múltiplos estágios** - Use Flows para orquestrar o processo geral e Crews para sub-tarefas complexas +2. **Aplicações que exigem criatividade e estrutura** - Use Crews para tarefas criativas e Flows para processamento estruturado +3. **Aplicações corporativas de IA** - Use Flows para gerenciar estado e fluxo de processo enquanto aproveita Crews para tarefas especializadas + +```python +# Example: Content Production Pipeline combining Crews and Flows +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel +from typing import List, Dict + +class ContentState(BaseModel): + topic: str = "" + target_audience: str = "" + content_type: str = "" + outline: Dict = {} + draft_content: str = "" + final_content: str = "" + seo_score: int = 0 + +class ContentProductionFlow(Flow[ContentState]): + @start() + def initialize_project(self): + # Set initial parameters + self.state.topic = "Sustainable Investing" + self.state.target_audience = "Millennial Investors" + self.state.content_type = "Blog Post" + return "Project initialized" + + @listen(initialize_project) + def create_outline(self, _): + # Use a research crew to create an outline + researcher = Agent( + role="Content Researcher", + goal=f"Research {self.state.topic} for {self.state.target_audience}", + backstory="You are an expert researcher with deep knowledge of content creation." + ) + + outliner = Agent( + role="Content Strategist", + goal=f"Create an engaging outline for a {self.state.content_type}", + backstory="You excel at structuring content for maximum engagement." + ) + + research_task = Task( + description=f"Research {self.state.topic} focusing on what would interest {self.state.target_audience}", + expected_output="Comprehensive research notes with key points and statistics", + agent=researcher + ) + + outline_task = Task( + description=f"Create an outline for a {self.state.content_type} about {self.state.topic}", + expected_output="Detailed content outline with sections and key points", + agent=outliner, + context=[research_task] + ) + + outline_crew = Crew( + agents=[researcher, outliner], + tasks=[research_task, outline_task], + process=Process.sequential, + verbose=True + ) + + # Run the crew and store the result + result = outline_crew.kickoff() + + # Parse the outline (in a real app, you might use a more robust parsing approach) + import json + try: + self.state.outline = json.loads(result.raw) + except: + # Fallback if not valid JSON + self.state.outline = {"sections": result.raw} + + return "Outline created" + + @listen(create_outline) + def write_content(self, _): + # Use a writing crew to create the content + writer = Agent( + role="Content Writer", + goal=f"Write engaging content for {self.state.target_audience}", + backstory="You are a skilled writer who creates compelling content." + ) + + editor = Agent( + role="Content Editor", + goal="Ensure content is polished, accurate, and engaging", + backstory="You have a keen eye for detail and a talent for improving content." + ) + + writing_task = Task( + description=f"Write a {self.state.content_type} about {self.state.topic} following this outline: {self.state.outline}", + expected_output="Complete draft content in markdown format", + agent=writer + ) + + editing_task = Task( + description="Edit and improve the draft content for clarity, engagement, and accuracy", + expected_output="Polished final content in markdown format", + agent=editor, + context=[writing_task] + ) + + writing_crew = Crew( + agents=[writer, editor], + tasks=[writing_task, editing_task], + process=Process.sequential, + verbose=True + ) + + # Run the crew and store the result + result = writing_crew.kickoff() + self.state.final_content = result.raw + + return "Content created" + + @listen(write_content) + def optimize_for_seo(self, _): + # Use a direct LLM call for SEO optimization + from crewai import LLM + llm = LLM(model="openai/gpt-4o-mini") + + prompt = f""" + Analyze this content for SEO effectiveness for the keyword "{self.state.topic}". + Rate it on a scale of 1-100 and provide 3 specific recommendations for improvement. + + Content: {self.state.final_content[:1000]}... (truncated for brevity) + + Format your response as JSON with the following structure: + {{ + "score": 85, + "recommendations": [ + "Recommendation 1", + "Recommendation 2", + "Recommendation 3" + ] + }} + """ + + seo_analysis = llm.call(prompt) + + # Parse the SEO analysis + import json + try: + analysis = json.loads(seo_analysis) + self.state.seo_score = analysis.get("score", 0) + return analysis + except: + self.state.seo_score = 50 + return {"score": 50, "recommendations": ["Unable to parse SEO analysis"]} + +# Run the flow +content_flow = ContentProductionFlow() +result = content_flow.kickoff() +``` + +## Framework Prático de Avaliação + +Para determinar a abordagem certa para seu caso de uso específico, siga este framework passo a passo: + +### Passo 1: Avalie a Complexidade + +Classifique a complexidade do seu aplicativo numa escala de 1-10 considerando: + +1. **Número de etapas**: Quantas operações distintas são necessárias? + - 1-3 etapas: Baixa complexidade (1-3) + - 4-7 etapas: Média complexidade (4-7) + - 8+ etapas: Alta complexidade (8-10) + +2. **Interdependências**: Quão interligadas estão as partes diferentes? + - Poucas dependências: Baixa complexidade (1-3) + - Algumas dependências: Média complexidade (4-7) + - Muitas dependências complexas: Alta complexidade (8-10) + +3. **Lógica condicional**: Quanto de ramificação e tomada de decisão é necessário? + - Processo linear: Baixa complexidade (1-3) + - Alguma ramificação: Média complexidade (4-7) + - Árvores de decisão complexas: Alta complexidade (8-10) + +4. **Conhecimento de domínio**: Quão especializado deve ser o conhecimento requerido? + - Conhecimento geral: Baixa complexidade (1-3) + - Algum conhecimento especializado: Média complexidade (4-7) + - Grande especialização em múltiplos domínios: Alta complexidade (8-10) + +Calcule a média das pontuações para determinar sua complexidade geral. + +### Passo 2: Avalie os Requisitos de Precisão + +Classifique seus requisitos de precisão numa escala de 1-10 considerando: + +1. **Estrutura da saída**: Quão estruturado o resultado deve ser? + - Texto livre: Baixa precisão (1-3) + - Semi-estruturado: Média precisão (4-7) + - Estritamente formatado (JSON, XML): Alta precisão (8-10) + +2. **Necessidade de exatidão**: Qual a importância da precisão factual? + - Conteúdo criativo: Baixa precisão (1-3) + - Conteúdo informacional: Média precisão (4-7) + - Informação crítica: Alta precisão (8-10) + +3. **Reprodutibilidade**: Quão consistentes devem ser os resultados entre execuções? + - Variação aceitável: Baixa precisão (1-3) + - Alguma consistência necessária: Média precisão (4-7) + - Exata reprodutibilidade: Alta precisão (8-10) + +4. **Tolerância a erros**: Qual o impacto de erros? + - Baixo impacto: Baixa precisão (1-3) + - Impacto moderado: Média precisão (4-7) + - Alto impacto: Alta precisão (8-10) + +Calcule a média das pontuações para determinar seu requisito geral de precisão. + +### Passo 3: Mapeie na Matriz + +Plote as pontuações de complexidade e precisão na matriz: + +- **Baixa Complexidade (1-4), Baixa Precisão (1-4)**: Crews simples +- **Baixa Complexidade (1-4), Alta Precisão (5-10)**: Flows com chamadas diretas a LLM +- **Alta Complexidade (5-10), Baixa Precisão (1-4)**: Crews complexas +- **Alta Complexidade (5-10), Alta Precisão (5-10)**: Flows orquestrando Crews + +### Passo 4: Considere Fatores Adicionais + +Além de complexidade e precisão, considere: + +1. **Tempo de desenvolvimento**: Crews costumam ser mais rápidas para prototipar +2. **Necessidades de manutenção**: Flows proporcionam melhor manutenção a longo prazo +3. **Expertise do time**: Considere a familiaridade de sua equipe com as abordagens +4. **Requisitos de escalabilidade**: Flows normalmente escalam melhor para aplicações complexas +5. **Necessidades de integração**: Considere como a solução se integrará aos sistemas existentes + +## Conclusão + +Escolher entre Crews e Flows — ou combiná-los — é uma decisão arquitetônica crítica que impacta a efetividade, manutenibilidade e escalabilidade da sua aplicação CrewAI. Ao avaliar seu caso de uso nas dimensões de complexidade e precisão, você toma decisões inteligentes que alinham-se aos seus requisitos. + +Lembre-se de que a melhor abordagem geralmente evolui na medida em que sua aplicação amadurece. Comece com a solução mais simples que atenda às suas necessidades e esteja preparado para refinar sua arquitetura conforme for ganhando experiência e seus requisitos se tornarem mais claros. + + +Agora você tem um framework para avaliar casos de uso CrewAI e escolher a abordagem certa de acordo com requisitos de complexidade e precisão. Isso vai ajudar você a construir aplicações de IA mais eficientes, de fácil manutenção e escaláveis. + + +## Próximos Passos + +- Saiba mais sobre [como criar agentes eficazes](/pt-BR/guides/agents/crafting-effective-agents) +- Explore [como construir sua primeira crew](/pt-BR/guides/crews/first-crew) +- Aprofunde-se em [gerenciamento de estado em flows](/pt-BR/guides/flows/mastering-flow-state) +- Confira os [conceitos centrais](/pt-BR/concepts/agents) para um entendimento mais aprofundado diff --git a/docs/v1.15.13/pt-BR/guides/crews/first-crew.mdx b/docs/v1.15.13/pt-BR/guides/crews/first-crew.mdx new file mode 100644 index 0000000000..6325ff528f --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/crews/first-crew.mdx @@ -0,0 +1,142 @@ +--- +title: Crie sua primeira Crew +description: Tutorial passo a passo para criar uma equipe colaborativa de IA com configuração JSON-first. +icon: users-gear +mode: "wide" +--- + +## Crie uma Crew de Pesquisa + +Neste guia, você criará uma crew com dois agentes que pesquisa um tópico e escreve um relatório em markdown. Novos projetos de crew são JSON-first: agentes ficam em `agents/*.jsonc`, tarefas e configurações ficam em `crew.jsonc`, e `crewai run` carrega essa definição diretamente. + +### Pré-requisitos + +Antes de começar: + +1. Instale o CrewAI seguindo o [guia de instalação](/pt-BR/installation) +2. Configure sua chave de LLM seguindo o [guia de LLMs](/pt-BR/concepts/llms#setting-up-your-llm) +3. Tenha uma chave [Serper.dev](https://serper.dev/) se quiser usar busca web + +## Etapa 1: Criar uma nova Crew + +```bash +crewai create crew research_crew +cd research_crew +``` + +Estrutura criada: + +```text +research_crew/ +├── .gitignore +├── .env +├── agents/ +│ └── researcher.jsonc +├── crew.jsonc +├── knowledge/ +├── pyproject.toml +├── README.md +├── skills/ +└── tools/ +``` + + +Precisa do layout antigo com `crew.py`, `config/agents.yaml` e `config/tasks.yaml`? Use `crewai create crew research_crew --classic`. + + +## Etapa 2: Definir os agentes + +Substitua o arquivo gerado `agents/researcher.jsonc` e adicione `agents/analyst.jsonc`. Os nomes dos arquivos são os nomes referenciados em `crew.jsonc`. + +```jsonc agents/researcher.jsonc +{ + "role": "Senior Research Specialist for {topic}", + "goal": "Find comprehensive and accurate information about {topic}, with a focus on recent developments and key insights.", + "backstory": "You are an experienced research specialist who organizes complex information into clear, useful notes.", + // Substitua pelo seu modelo, por exemplo "openai/gpt-4o". + "llm": "provider/model-id", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +```jsonc agents/analyst.jsonc +{ + "role": "Report Analyst for {topic}", + "goal": "Turn research findings into a clear, well-structured report.", + "backstory": "You are a careful analyst with strong technical writing skills and a talent for extracting useful insights.", + // Substitua pelo seu modelo, por exemplo "openai/gpt-4o". + "llm": "provider/model-id", + "settings": { + "verbose": true, + "allow_delegation": false + } +} +``` + +Substitua `provider/model-id` pelo modelo usado, como `openai/gpt-4o`, `anthropic/claude-sonnet-4-6` ou `gemini/gemini-2.0-flash-001`. + +## Etapa 3: Definir tarefas e configurações + +Substitua `crew.jsonc` por: + +```jsonc crew.jsonc +{ + "name": "Research Crew", + "agents": ["researcher", "analyst"], + "tasks": [ + { + "name": "research_task", + "description": "Conduct thorough research on {topic}. Focus on key concepts, recent developments, major challenges, notable applications, and future outlook.", + "expected_output": "A comprehensive research document with organized sections, specific facts, and useful examples about {topic}.", + "agent": "researcher" + }, + { + "name": "analysis_task", + "description": "Analyze the research findings and create a polished report on {topic}. Include an executive summary, key insights, trend analysis, and recommendations.", + "expected_output": "A professional markdown report with clear headings, a concise summary, main findings, and recommendations.", + "agent": "analyst", + "context": ["research_task"], + "output_file": "output/report.md", + "markdown": true + } + ], + "process": "sequential", + "verbose": true, + "memory": true, + "inputs": { + "topic": "Artificial Intelligence in Healthcare" + } +} +``` + +`context` aponta para tarefas anteriores, então o analista recebe a saída da pesquisa. `inputs` define valores padrão para `{topic}`; se um valor faltar, `crewai run` perguntará no terminal. + +## Etapa 4: Variáveis de ambiente + +Edite `.env`: + +```sh +SERPER_API_KEY=your_serper_api_key +# Adicione também a chave do seu provedor de modelo. +``` + +## Etapa 5: Instalar e executar + +```bash +crewai install +crewai run +``` + +Quando a execução terminar, abra `output/report.md`. + + +Execute projetos JSON crew apenas de fontes confiáveis. Ferramentas `custom:` e referências `{"python": "module.attribute"}` executam Python local ao carregar a crew. + + + +Você criou uma crew JSON-first funcional que pesquisa um tópico e escreve um relatório. + diff --git a/docs/v1.15.13/pt-BR/guides/flows/conversational-flows.mdx b/docs/v1.15.13/pt-BR/guides/flows/conversational-flows.mdx new file mode 100644 index 0000000000..10ffdcbd6a --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/flows/conversational-flows.mdx @@ -0,0 +1,475 @@ +--- +title: Flows Conversacionais +description: Crie apps de chat multi-turno com kickoff por turno, histórico de mensagens, roteamento de intenção, tracing e pontes WebSocket. +icon: comments +mode: "wide" +--- + +## Visão geral + +Apps conversacionais tratam cada linha do usuário como uma **nova execução do flow** com o **mesmo id de sessão**. A CrewAI oferece helpers para histórico de mensagens, classificação opcional de intenção, tracing adiado, pontes para UI e um REPL local `flow.chat()` para flows conversacionais. + +| Conceito | Implementação | +|---------|----------------| +| Id de sessão | `handle_turn(..., session_id=...)` → `kickoff(inputs={"id": ...})` → `state.id` | +| Linha do usuário | `handle_turn(message)` acrescenta em `state.messages` antes do grafo rodar | +| Fim do turno | `FlowFinished` só para **esta execução**; o chat segue no próximo `handle_turn` | +| Trace da sessão | `ConversationConfig(defer_trace_finalization=True)` + `finalize_session_traces()` | + +## APIs de turno + +Use **`flow.handle_turn(message, session_id=...)`** para cada mensagem de usuário em REST, WebSocket, testes e UIs customizadas. Use **`flow.chat()`** quando quiser um loop de chat local no terminal para um `Flow` conversacional. + +`Flow.kickoff()` não aceita os argumentos nomeados `user_message=` ou `session_id=`. Para flows conversacionais, `handle_turn()` guarda a mensagem pendente e chama `kickoff(inputs={"id": session_id})` internamente. + +| API | Uso | +|-----|-----| +| `handle_turn(message, session_id=...)` | Wrapper ergonômico de um turno para `Flow` conversacional | +| `chat()` | REPL local no terminal para `Flow` conversacional | +| `kickoff(inputs={...})` | Execução avançada do flow sem tratamento de turno conversacional | +| `ask()` | Prompt bloqueante **dentro** de um passo (wizard, esclarecimento) | +| `@human_feedback` | Aprovar/rejeitar **saída de um passo** — não a próxima linha do chat | +| `ChatSession.handle_turn(...)` | Camada de transporte sobre `handle_turn` (SSE / WebSocket) | + +## Início rápido + +```python +from uuid import uuid4 + +from crewai import Flow +from crewai.flow import listen +from crewai.experimental.conversational import ( + ConversationConfig, + ConversationState, +) + + +@ConversationConfig(defer_trace_finalization=True) +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context): + message = (self.state.current_user_message or "").lower() + if "pedido" in message or "order" in message: + return "order" + if "tchau" in message or "goodbye" in message: + return "goodbye" + return "help" + + @listen("order") + def handle_order(self): + reply = "Seu pedido está a caminho." + self.append_assistant_message(reply) + return reply + + @listen("help") + def handle_help(self): + reply = "Como posso ajudar?" + self.append_assistant_message(reply) + return reply + + @listen("goodbye") + def handle_goodbye(self): + reply = "Até logo!" + self.append_assistant_message(reply) + return reply + + +session_id = str(uuid4()) +flow = SupportFlow() + +try: + flow.handle_turn("Onde está meu pedido?", session_id=session_id) + flow.handle_turn("E as devoluções?", session_id=session_id) +finally: + flow.finalize_session_traces() # um link de trace para o chat inteiro +``` + +## Ciclo de vida do turno + +Cada `handle_turn` executa este pipeline: + +1. **`_configure_conversational_kickoff`** — mescla `session_id` / `user_message` em `inputs`, aplica `ConversationalConfig`, habilita tracing adiado quando configurado. +2. **Restauração de estado** — se `inputs["id"]` existe e `@persist` está configurado, carrega o snapshot mais recente. +3. **`FlowStarted`** — emitido apenas no primeiro turno da sessão adiada. +4. **`prepare_conversational_turn`** — acrescenta a mensagem do usuário em `state.messages`, define `last_user_message`, limpa `last_intent`, classifica opcionalmente quando `intents` / `default_intents` + `intent_llm` estão definidos. +5. **Execução do grafo** — `@start` → `@router` → handlers `@listen`. +6. **Fim da execução** — `flow_finished` por turno e finalização de trace são **ignorados** com adiamento; `Agent.kickoff()` / crews aninhados também não fecham o batch pai. + +Os handlers devem chamar **`append_assistant_message(reply)`** para que o próximo turno inclua a resposta do assistente. A linha do usuário já é salva por `handle_turn` — não acrescente de novo nos handlers. + +## `ConversationalConfig` (padrões em nível de classe) + +Defina na subclasse de `Flow` como `conversational_config: ClassVar[ConversationalConfig | None]`. + +| Campo | Padrão | Propósito | +|-------|---------|-----------| +| `default_intents` | `None` | Rótulos de outcome para classificação automática antes do kickoff | +| `intent_llm` | `None` | Modelo para classificação (obrigatório quando há intents) | +| `interactive_prompt` | `"You: "` | Prompt para `kickoff(interactive=True)` | +| `interactive_timeout` | `None` | Timeout por linha no modo interativo | +| `exit_commands` | `exit`, `quit` | Palavras que encerram o modo interativo | +| `defer_trace_finalization` | `True` | Manter um batch de trace aberto entre turnos | + +Sobrescreva por kickoff com `intents=` e `intent_llm=`. + +## `ChatState` (formato persistido recomendado) + +```python +from crewai.flow import ChatState + + +class MyChatState(ChatState): + # Herdados: id, messages, last_user_message, last_intent, session_ready + research_turn_count: int = 0 + custom_flag: bool = False +``` + +| Campo | Função | +|-------|--------| +| `id` | UUID da sessão (igual a `session_id` / `inputs["id"]`) | +| `messages` | `list` de `{role, content}` para histórico de LLM | +| `last_user_message` | Última linha do usuário neste turno | +| `last_intent` | Rótulo de rota após classificação (se usado) | +| `session_ready` | Flag de bootstrap único (permissões, caches, etc.) | + +`ConversationalInputs` é um `TypedDict` para `kickoff(inputs={...})`: `id`, `user_message`, `last_intent`. + +## API conversacional em `Flow` + +### Parâmetros de `kickoff` / `kickoff_async` + +| Parâmetro | Propósito | +|-----------|-----------| +| `user_message` | Texto deste turno (ou `{"role": "user", "content": "..."}`) | +| `session_id` | UUID da conversa → `inputs["id"]` / `state.id` | +| `intents` | Rótulos de outcome para `classify_intent` antes do kickoff | +| `intent_llm` | LLM para classificação (obrigatório com `intents`) | +| `interactive` | Loop CLI via `ask()` (só demos locais) | +| `interactive_prompt` | Prompt no modo interativo | +| `interactive_timeout` | Timeout de `ask()` por linha | +| `exit_commands` | Palavras que encerram o modo interativo | +| `inputs` | Campos extras de estado (mesclados com chaves conversacionais) | +| `restore_from_state_id` | Hidratação fork de outro flow persistido | + +### Atributos de instância + +| Atributo | Propósito | +|-----------|-----------| +| `conversational_config` | Padrões `ConversationalConfig` em nível de classe | +| `defer_trace_finalization` | Flag de instância; definida automaticamente a partir do config no kickoff | +| `suppress_flow_events` | Oculta painéis Rich no console; **tracing ainda registra** eventos | +| `stream` | Habilita streaming; use com `ChatSession.handle_turn(..., stream=True)` | + +### Métodos e propriedades + +| Nome | Descrição | +|------|-------------| +| `append_message(role, content, **extra)` | Acrescenta em `state.messages` (roles: `user`, `assistant`, `system`, `tool`) | +| `conversation_messages` | Histórico somente leitura para chamadas LLM | +| `classify_intent(text, outcomes, *, llm, context=None)` | Mapeia texto a um outcome (mesma lógica de `@human_feedback`) | +| `receive_user_message(text, *, outcomes=None, llm=None)` | Acrescenta mensagem do usuário; opcionalmente define `last_intent` | +| `finalize_session_traces()` | Emite `flow_finished` adiado e finaliza o batch de trace da sessão | +| `_should_defer_trace_finalization()` | Se este flow adia finalização de trace por turno | +| `input_history` | Trilha de auditoria de prompts e respostas de `ask()` | + +### Helpers do módulo (`crewai.flow.conversation`) + +Importáveis para testes ou orquestração customizada: + +| Função | Descrição | +|----------|-------------| +| `normalize_kickoff_inputs(inputs, user_message=..., session_id=...)` | Mescla kwargs conversacionais em `inputs` | +| `get_conversation_messages(flow)` | Lê mensagens do estado ou buffer interno | +| `append_message(flow, role, content, **extra)` | Igual ao método de instância | +| `prepare_conversational_turn(flow, ...)` | Hidratação do turno (geralmente chamado pelo kickoff) | +| `receive_user_message(flow, text, ...)` | Igual ao método de instância | +| `set_state_field(flow, name, value)` | Define campo em estado dict ou Pydantic | +| `get_conversational_config(flow)` | Lê `conversational_config` da classe | +| `input_history_to_messages(entries)` | Converte `input_history` para formato de mensagens LLM | + +## Padrões de roteamento de intenção + +### A. Pré-classificar via `ConversationalConfig` (mais simples) + +Defina `default_intents` e `intent_llm`. Cada kickoff classifica antes do `@router`; leia `self.state.last_intent` em `route()`. + +### B. Classificar dentro do `@router` (prompts mais ricos) + +Defina `default_intents=None` para o kickoff só acrescentar a mensagem. Em `route()`, chame `classify_intent` com prompt ou descrições customizadas: + +```python +@router(bootstrap) +def route(self): + intent = self.classify_intent( + self._routing_prompt(self.state.last_user_message), + ("GREETING", "ORDER", "RESEARCH", "GOODBYE"), + llm=self.conversational_config.intent_llm or "gpt-4o-mini", + ) + self.state.last_intent = intent + return intent +``` + +Use **`@listen("RESEARCH")`** (ou similar) para passos com `Agent.kickoff()` e ferramentas — não `LLM.call()` puro — quando precisar de pesquisa web ou uso multi-etapa de tools. + +## Quando o flow termina mas o usuário continua conversando + +`FlowFinished` significa que **esta execução do grafo** terminou. A conversa segue com outro `kickoff` e o mesmo `session_id`. `@persist` restaura `messages`, flags e contexto. + +**Padrão de persistência:** prefira `@persist` em um **único passo terminal** (por exemplo `finalize`) em vez de na classe `Flow` inteira. Persist em nível de classe salva após cada método; `load_state` usa a linha mais recente, que pode ser snapshot no meio da execução e perder atualizações dos handlers no mesmo turno. + +Não use `@human_feedback` para linhas de chat de follow-up, a menos que um humano precise aprovar uma saída específica antes de exibi-la. + +## `Flow` conversacional (experimental) + + + **Funcionalidade experimental.** A superfície do `Flow` conversacional + (`conversational = True`, `handle_turn`, `ConversationConfig`, + `RouterConfig`, `ConversationState`, o grafo embutido + helpers) vive em + `crewai.experimental` e pode mudar de formato antes de graduar. Fixe a + versão do CrewAI se depende de comportamento específico e acompanhe o + changelog para mudanças quebradoras. Feedback / issues bem-vindos. + + +Habilite o grafo conversacional definindo `conversational = True` em uma subclasse de `Flow`. O `Flow` base passa a expor um grafo embutido `@start` / `@router` / `converse_turn` / `end_conversation`, gerencia `state.messages`, dirige o LLM de roteamento e mantém o batch de trace aberto entre os turnos. Você escreve as **rotas customizadas**; o framework cuida do resto. + +Use isto quando quiser um chat multi-turno com router LLM e handlers por rota sem cablar o ciclo de vida na mão. Use `Flow[ChatState]` (o padrão de mais baixo nível acima) quando precisar de controle total. + +### Exemplo rápido + +```python +from crewai import LLM, Flow +from crewai.flow import listen +from crewai.experimental.conversational import ( + ConversationConfig, + ConversationState, + RouterConfig, +) + + +ROUTER_LLM = LLM(model="gpt-4o-mini") + + +@ConversationConfig( + system_prompt="A multi-agent assistant for ordinary chat and tool-backed tasks.", + llm=ROUTER_LLM, + router=RouterConfig(), # rotas + descrições auto-descobertas pelos handlers @listen +) +class SupportFlow(Flow[ConversationState]): + conversational = True + + @listen("INTERNET_SEARCH") + def handle_internet_search(self) -> str: + """Fresh web research, current news, real-time lookups.""" + ... + self.append_assistant_message(reply) + return reply + + @listen("CREWAI_DOCS") + def handle_crewai_docs(self) -> str: + """Look up the CrewAI documentation for framework/API questions.""" + ... + self.append_assistant_message(reply) + return reply + + +flow = SupportFlow() +try: + flow.handle_turn("O que você pode fazer?") # roteia para converse (built-in) + flow.handle_turn("Pesquise na web por notícias de IA.") # roteia para INTERNET_SEARCH + flow.handle_turn("Resuma o primeiro resultado.") # volta para converse +finally: + flow.finalize_session_traces() +``` + +Para um chat local no terminal, use `chat()`: + +```python +def kickoff() -> None: + SupportFlow().chat() +``` + +`chat()` envolve `handle_turn()` em um REPL, sai com `exit` / `quit`, ignora linhas em branco por padrão e chama `finalize_session_traces()` quando a sessão termina. + +### `ConversationConfig` + +Decorador de classe que anexa os defaults de chat por classe. + +| Campo | Padrão | Propósito | +|-------|--------|-----------| +| `system_prompt` | `slices.conversational_system_prompt` (i18n) | System message usado pelo `converse_turn` embutido. Passe `""` para desativar totalmente. | +| `llm` | `None` | LLM de conversa (usado pelo `converse_turn` e como fallback do router). | +| `router` | `None` | `RouterConfig` para roteamento por LLM. Sem ele, o flow sempre cai em `converse`. | +| `answer_from_history_prompt` | padrão do framework | System message para a rota opcional `answer_from_history`. | +| `answer_from_history_llm` | `None` | Habilita o atalho `answer_from_history` quando definido. | +| `intent_llm` | `None` | LLM para o caminho legado `intents=`/`default_intents`. | +| `default_intents` | `None` | Labels de outcome para pré-classificação legada. | +| `visible_agent_outputs` | `None` | `"all"` ou lista de nomes de agentes cujos `append_agent_result()` devem virar mensagens públicas. | +| `defer_trace_finalization` | `True` | Mantém um único batch de trace aberto entre chamadas de `handle_turn()`. | + +### `RouterConfig` e o catálogo de rotas auto-gerado + +```python +RouterConfig( + prompt="Enquadramento de domínio opcional (política, voz, persona).", + response_format=MyRoute, # opcional; auto-gerado caso contrário + llm=ROUTER_LLM, # usa ConversationConfig.llm como fallback + routes=["INTERNET_SEARCH", "CREWAI_DOCS"], # opcional; inferido dos listeners + route_descriptions={ + "INTERNET_SEARCH": "Sobrescreve a docstring só desta rota.", + }, + default_intent="converse", # usado quando a chamada ao LLM falha ou não há LLM + fallback_intent="converse", # usado quando o LLM retorna rota inválida + intent_field="intent", +) +``` + +O prompt do router é montado automaticamente. Para cada rota o framework escolhe a descrição nesta precedência: + +1. `RouterConfig.route_descriptions[label]` — override explícito. +2. `Flow.builtin_route_descriptions[label]` — texto canônico do framework para `converse`, `end`, `answer_from_history` (otimizado para o LLM de routing). +3. Primeira linha não vazia da docstring do handler `@listen(label)`. +4. Vazio (a rota aparece no catálogo sem descrição). + +Na prática, **adicionar uma rota é `@listen("X")` + uma docstring de uma linha**: + +```python +@listen("INTERNET_SEARCH") +def handle_internet_search(self) -> str: + """Fresh web research, current news, real-time lookups.""" + ... +``` + +…e o LLM de routing vê: + +``` +Routes: +- CREWAI_DOCS: Look up the CrewAI documentation for framework/API questions. +- INTERNET_SEARCH: Fresh web research, current news, real-time lookups. +- converse: Ordinary chat, follow-ups, summaries, clarifications… +- end: User signals the conversation is finished (goodbye, exit, done). +``` + +`RouterConfig.prompt` é para **enquadramento de domínio** (persona do assistente, regras de negócio, voz). O catálogo de rotas é auto-gerado — não liste rotas em `prompt`; elas vão sair de sincronia assim que você adicionar um handler. + +### Rotas embutidas + +| Rota | Handler | Propósito | +|------|---------|-----------| +| `converse` | `converse_turn` | Handler de chat padrão. Chama `ConversationConfig.llm` com o system prompt + histórico canônico. | +| `end` | `end_conversation` | Define `state.ended = True` e emite uma resposta de encerramento. | +| `answer_from_history` | `answer_from_history_turn` | Opcional. Cai aqui quando `ConversationConfig.answer_from_history_llm` está definido e a mensagem pode ser respondida só pelo histórico. | + +Você pode sobrescrever qualquer uma definindo um handler com o mesmo nome na subclasse. + +### Semântica de `handle_turn()` + +`flow.handle_turn(message)` roda um turno: + +1. Reseta o tracking por execução (`_completed_methods`, `_method_outputs`) para o grafo re-rodar — sem isso, chamadas repetidas de `kickoff` na mesma instância dariam curto-circuito no turno 2+ porque `Flow.kickoff_async` trata `inputs={"id": ...}` como restauração de checkpoint. +2. Anexa a mensagem do usuário em `state.messages`, define `current_user_message` / `last_user_message`. `last_intent` é **preservado do turno anterior** para que o LLM de routing possa usá-lo como sinal. +3. Roda `conversation_start` → `route_conversation` → o handler `@listen` escolhido. +4. O router grava sua decisão em `state.last_intent` (visível para o contexto de routing do próximo turno). +5. Se seu handler retornou uma string e ainda não chamou `append_assistant_message`, `handle_turn` anexa para você. + +Chame `handle_turn()` para mensagens de chat. Chamar `kickoff(inputs={"id": ...})` diretamente executa o grafo sem aplicar o wrapper de turno conversacional. + +### `chat()` para REPLs locais + +`flow.chat()` é o wrapper de terminal pronto para uso em cima de `handle_turn()`: + +```python +flow = SupportFlow() +flow.chat() +``` + +Ele cobre o loop local comum: + +1. Solicita uma mensagem do usuário. +2. Para com `exit` / `quit`, `EOFError` ou `KeyboardInterrupt`. +3. Chama `handle_turn(message, session_id=...)`. +4. Imprime o resultado do assistente. +5. Finaliza traces de sessão adiados em um bloco `finally`. + +Customize o comportamento do terminal com I/O injetável: + +```python +flow.chat( + session_id="demo-session", + prompt="You: ", + assistant_prefix="Assistant: ", + exit_commands=("exit", "quit", "bye"), +) +``` + +Para apps web, workers em background, testes e transportes customizados, continue usando `handle_turn()` diretamente. + +### Comportamento customizado do router + +Para rodar efeitos colaterais (setup de event bus, telemetria) em toda decisão de routing, sobrescreva `route_turn`: + +```python +class SupportFlow(Flow[ConversationState]): + conversational = True + + def route_turn(self, context: dict[str, Any]) -> str | None: + self.event_bus = MyBus(self) + return super().route_turn(context) +``` + +Para ignorar o router LLM e escolher uma rota programaticamente, retorne uma string de `route_turn`; retornar `None` cai no `_route_with_config(...)`. + +### `append_assistant_message` e `append_agent_result` + +Dentro de um handler `@listen(label)`, escolha: + +- `self.append_assistant_message(text)` — adiciona um turno de assistente visível ao usuário em `state.messages`. O `converse_turn` do próximo turno vai vê-lo. +- `self.append_agent_result(agent_name, result, visibility="private")` — registra um evento estruturado em `state.events` e uma thread em `state.agent_threads[agent_name]`. Visibilidade pública também chama `append_assistant_message` automaticamente. Use resultados privados para trabalho de bastidor que não deve poluir o histórico canônico. + +`ConversationConfig.visible_agent_outputs` pode promover globalmente os resultados privados de agentes específicos para públicos (`"all"` ou lista de nomes). + +## Tracing entre turnos + +Com `defer_trace_finalization=True` (padrão em `ConversationalConfig`): + +- **Um batch de trace** para toda a sessão de chat. +- **`flow_started`** só no primeiro turno; **`flow_finished`** uma vez em `finalize_session_traces()`. +- **`kickoff` por turno** não exibe “Trace batch finalized”. +- **Trabalho aninhado** (`Agent.kickoff()`, crews, tools Exa) acrescenta ao batch **pai**; flows internos de `AgentExecutor` não fecham o batch da sessão cedo. + +```python +flow.chat(session_id=session_id) +``` + +`flow.chat()` chama `finalize_session_traces()` para você. Quando você controla o loop com `handle_turn()` ou `kickoff(...)`, chame `finalize_session_traces()` quando a sessão terminar. + +`suppress_flow_events=True` só oculta painéis do console; eventos de trace e método ainda são emitidos. + +### Ciclo de vida de trace do `Flow` conversacional + +O [`Flow` conversacional](#flow-conversacional-experimental) experimental usa o mesmo ciclo de vida de tracing: `defer_trace_finalization` é `True` por padrão, então cada `handle_turn()` mantém o trace da sessão aberto. Sempre finalize ao fim da sessão — envolva seu loop em `try/finally` e chame `flow.finalize_session_traces()` na saída. Sem isso, o batch fica aberto e a última conversa pode nunca ser exportada. + +## Streaming + +Defina `stream = True` na classe `Flow`. `kickoff(...)` então emitirá `assistant_delta` (e eventos relacionados) pelo event bus padrão. + +## Imports + +```python +from crewai.flow import ( + ChatState, + ConversationalConfig, + ConversationalInputs, + Flow, + listen, + persist, + router, + start, +) +``` + +## Veja também + +- [Dominando o Gerenciamento de Estado em Flows](/pt-BR/guides/flows/mastering-flow-state) — persistência, estado Pydantic, `@persist` +- [Construa Seu Primeiro Flow](/pt-BR/guides/flows/first-flow) — fundamentos de flow +- Demo: `lib/crewai/runner_conversational_flow_simple.py` — REPL mínimo com `RESEARCH` + agente Exa diff --git a/docs/v1.15.13/pt-BR/guides/flows/first-flow.mdx b/docs/v1.15.13/pt-BR/guides/flows/first-flow.mdx new file mode 100644 index 0000000000..0ff1ba5d64 --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/flows/first-flow.mdx @@ -0,0 +1,550 @@ +--- +title: Construa Seu Primeiro Flow +description: Aprenda como criar fluxos de trabalho estruturados e orientados a eventos com controle preciso sobre a execução. +icon: diagram-project +mode: "wide" +--- + +## Assumindo o Controle de Workflows de IA com Flows + +Os Flows do CrewAI representam o próximo nível em orquestração de IA – combinando o poder colaborativo de equipes de agentes de IA com a precisão e flexibilidade da programação procedural. Enquanto os crews se destacam em colaboração de agentes, os flows dão a você controle detalhado sobre exatamente como e quando diferentes componentes do seu sistema de IA interagem. + +Neste guia, vamos percorrer a criação de um poderoso CrewAI Flow que gera um guia de aprendizado abrangente sobre qualquer tema. Este tutorial demonstrará como os Flows oferecem controle estruturado e orientado a eventos sobre seus workflows de IA ao combinar código regular, chamadas diretas a LLM e processamento baseado em crews. + +### O Que Torna os Flows Poderosos + +Com flows, você pode: + +1. **Combinar diferentes padrões de interação com IA** – Use crews para tarefas colaborativas complexas, chamadas diretas às LLMs para operações mais simples, e código regular para lógica procedural. +2. **Construir sistemas orientados a eventos** – Defina como os componentes respondem a eventos e mudanças de dados específicos. +3. **Manter estado entre componentes** – Compartilhe e transforme dados entre diferentes partes da sua aplicação. +4. **Integrar com sistemas externos** – Conecte seu fluxo de trabalho de IA com bancos de dados, APIs e interfaces de usuário de forma transparente. +5. **Criar caminhos de execução complexos** – Projete ramificações condicionais, processamento paralelo e workflows dinâmicos. + +### O Que Você Vai Construir e Aprender + +Ao final deste guia, você terá: + +1. **Criado um sistema sofisticado de geração de conteúdo** que combina entrada do usuário, planejamento por IA e criação de conteúdo multiagente. +2. **Orquestrado o fluxo de informações** entre diferentes componentes do seu sistema. +3. **Implementado uma arquitetura orientada a eventos** onde cada etapa responde à conclusão das etapas anteriores. +4. **Construído uma base para aplicações de IA mais complexas** que você pode expandir e personalizar. + +Este flow de criação de guia demonstra padrões fundamentais que podem ser aplicados para criar aplicações muito mais avançadas, como: + +- Assistentes de IA interativos que combinam múltiplos subsistemas especializados. +- Pipelines de processamento de dados complexos com transformações aprimoradas por IA. +- Agentes autônomos integrados a serviços e APIs externas. +- Sistemas de tomada de decisão em múltiplas etapas com processos envolvendo humanos no loop. + +Vamos começar e construir seu primeiro flow! + +## Pré-requisitos + +Antes de começar, certifique-se de ter: + +1. Instalado o CrewAI seguindo o [guia de instalação](/pt-BR/installation) +2. Configurado sua chave de API LLM no ambiente, conforme o [guia de configuração do LLM](/pt-BR/concepts/llms#setting-up-your-llm) +3. Conhecimentos básicos de Python + +## Passo 1: Crie um Novo Projeto de CrewAI Flow + +Primeiro, vamos criar um novo projeto de Flow do CrewAI usando a CLI. Este comando configura um projeto com todos os diretórios necessários e arquivos de template para seu flow. + +```bash +crewai create flow guide_creator_flow +cd guide_creator_flow +``` + +Isso gerará um projeto com a estrutura básica necessária para seu flow. + + + CrewAI Framework Overview + + +## Passo 2: Entendendo a Estrutura do Projeto + +O projeto gerado possui a seguinte estrutura. A crew inicial embutida usa o layout clássico Python/YAML. Para usar uma crew JSON-first dentro de um Flow, crie `crew.jsonc` e `agents/*.jsonc` na pasta da crew e carregue com `crewai.project.load_crew`, como mostrado em [Flows](/pt-BR/concepts/flows#building-your-crews). + +``` +guide_creator_flow/ +├── .gitignore +├── pyproject.toml +├── README.md +├── .env +└── src/ + └── guide_creator_flow/ + ├── __init__.py + ├── main.py + ├── crews/ + │ └── poem_crew/ + │ ├── config/ + │ │ ├── agents.yaml + │ │ └── tasks.yaml + │ └── poem_crew.py + └── tools/ + └── custom_tool.py +``` + +Esta estrutura oferece uma separação clara entre os diferentes componentes do seu flow: +- A lógica principal do flow no arquivo `src/guide_creator_flow/main.py` +- Crews especializados no diretório `src/guide_creator_flow/crews` +- Ferramentas customizadas no diretório `src/guide_creator_flow/tools` + +Vamos modificar esta estrutura para criar nosso flow de criação de guias, que irá orquestrar o processo de geração de guias de aprendizagem abrangentes. + +## Passo 3: Adicione um Crew de Redator de Conteúdo + +Nosso flow precisará de um crew especializado para lidar com o processo de criação de conteúdo. Vamos usar a CLI do CrewAI para adicionar um crew de redatores de conteúdo: + +```bash +crewai flow add-crew content-crew +``` + +Este comando cria automaticamente os diretórios e arquivos de template necessários para seu crew. O crew de redatores será responsável por escrever e revisar seções do nosso guia, trabalhando dentro do flow orquestrado pela aplicação principal. + +## Passo 4: Configure o Crew de Redator de Conteúdo + +Agora, vamos configurar o crew de redatores com JSONC. Vamos definir dois agentes especializados - um escritor e um revisor - que colaboram para criar conteúdo de alta qualidade para o guia. + +1. Crie `src/guide_creator_flow/crews/content_crew/agents/content_writer.jsonc`: + +```jsonc +{ + "role": "Educational Content Writer", + "goal": "Create engaging, informative content that thoroughly explains the assigned topic and provides valuable insights to the reader.", + "backstory": "You are a talented educational writer who explains complex concepts in accessible language and organizes information clearly.", + "llm": "provider/model-id", + "settings": { + "verbose": true + } +} +``` + +2. Crie `src/guide_creator_flow/crews/content_crew/agents/content_reviewer.jsonc`: + +```jsonc +{ + "role": "Educational Content Reviewer and Editor", + "goal": "Ensure content is accurate, comprehensive, well-structured, and consistent with previously written sections.", + "backstory": "You are a meticulous editor with an eye for detail, clarity, and coherence.", + "llm": "provider/model-id", + "settings": { + "verbose": true + } +} +``` + +Substitua `provider/model-id` pelo modelo que você usa, como `openai/gpt-4o`, `gemini/gemini-2.0-flash-001` ou `anthropic/claude-sonnet-4-6`. + +3. Crie `src/guide_creator_flow/crews/content_crew/crew.jsonc`: + +```jsonc +{ + "name": "Content Crew", + "agents": ["content_writer", "content_reviewer"], + "tasks": [ + { + "name": "write_section_task", + "description": "Write a comprehensive section on the topic: \"{section_title}\".\n\nSection description: {section_description}\nTarget audience: {audience_level} level learners\n\nYour content should begin with a brief introduction, explain key concepts clearly with examples, include practical applications where appropriate, end with a summary, and be approximately 500-800 words.\n\nPreviously written sections:\n{previous_sections}", + "expected_output": "A well-structured, comprehensive section in Markdown format that thoroughly explains the topic and is appropriate for the target audience.", + "agent": "content_writer", + "markdown": true + }, + { + "name": "review_section_task", + "description": "Review and improve this section on \"{section_title}\":\n\n{draft_content}\n\nTarget audience: {audience_level} level learners\nPreviously written sections:\n{previous_sections}\n\nFix errors, improve clarity, verify consistency, enhance structure, and add missing key information.", + "expected_output": "An improved, polished version of the section that maintains the original structure but enhances clarity, accuracy, and consistency.", + "agent": "content_reviewer", + "context": ["write_section_task"], + "markdown": true + } + ], + "process": "sequential", + "verbose": true +} +``` + +O campo `context` permite que o revisor use a saída do escritor. + +4. Substitua `src/guide_creator_flow/crews/content_crew/content_crew.py` por um pequeno loader: + +```python +from pathlib import Path + +from crewai.project import load_crew + + +def kickoff_content_crew(inputs: dict): + crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc")) + return crew.kickoff(inputs={**default_inputs, **inputs}) +``` + +Esse loader transforma `crew.jsonc` em uma `Crew` em runtime. Embora essa crew possa funcionar de forma independente, no nosso flow ela será orquestrada como parte de um sistema maior. + +## Passo 5: Crie o Flow + +Agora vem a parte emocionante – criar o flow que irá orquestrar todo o processo de criação do guia. Aqui iremos combinar código Python regular, chamadas diretas a LLM e nosso crew de criação de conteúdo em um sistema coeso. + +Nosso flow irá: +1. Obter a entrada do usuário sobre o tema e nível do público +2. Fazer uma chamada direta à LLM para criar um roteiro estruturado do guia +3. Processar cada seção sequencialmente usando o crew de redatores +4. Combinar tudo em um documento final abrangente + +Vamos criar nosso flow no arquivo `main.py`: + +```python +#!/usr/bin/env python +import json +import os +from typing import List, Dict +from pydantic import BaseModel, Field +from crewai import LLM +from crewai.flow.flow import Flow, listen, start +from guide_creator_flow.crews.content_crew.content_crew import kickoff_content_crew + +# Definir nossos modelos para dados estruturados +class Section(BaseModel): + title: str = Field(description="Title of the section") + description: str = Field(description="Brief description of what the section should cover") + +class GuideOutline(BaseModel): + title: str = Field(description="Title of the guide") + introduction: str = Field(description="Introduction to the topic") + target_audience: str = Field(description="Description of the target audience") + sections: List[Section] = Field(description="List of sections in the guide") + conclusion: str = Field(description="Conclusion or summary of the guide") + +# Definir o estado do nosso flow +class GuideCreatorState(BaseModel): + topic: str = "" + audience_level: str = "" + guide_outline: GuideOutline = None + sections_content: Dict[str, str] = {} + +class GuideCreatorFlow(Flow[GuideCreatorState]): + """Flow para criar um guia abrangente sobre qualquer tópico""" + + @start() + def get_user_input(self): + """Obter entrada do usuário sobre o tópico e público do guia""" + print("\n=== Create Your Comprehensive Guide ===\n") + + # Obter entrada do usuário + self.state.topic = input("What topic would you like to create a guide for? ") + + # Obter nível do público com validação + while True: + audience = input("Who is your target audience? (beginner/intermediate/advanced) ").lower() + if audience in ["beginner", "intermediate", "advanced"]: + self.state.audience_level = audience + break + print("Please enter 'beginner', 'intermediate', or 'advanced'") + + print(f"\nCreating a guide on {self.state.topic} for {self.state.audience_level} audience...\n") + return self.state + + @listen(get_user_input) + def create_guide_outline(self, state): + """Criar um esboço estruturado para o guia usando uma chamada direta ao LLM""" + print("Creating guide outline...") + + # Inicializar o LLM + llm = LLM(model="openai/gpt-4o-mini", response_format=GuideOutline) + + # Criar as mensagens para o esboço + messages = [ + {"role": "system", "content": "You are a helpful assistant designed to output JSON."}, + {"role": "user", "content": f""" + Create a detailed outline for a comprehensive guide on "{state.topic}" for {state.audience_level} level learners. + + The outline should include: + 1. A compelling title for the guide + 2. An introduction to the topic + 3. 4-6 main sections that cover the most important aspects of the topic + 4. A conclusion or summary + + For each section, provide a clear title and a brief description of what it should cover. + """} + ] + + # Fazer a chamada ao LLM com formato de resposta JSON + response = llm.call(messages=messages) + + # Analisar a resposta JSON + outline_dict = json.loads(response) + self.state.guide_outline = GuideOutline(**outline_dict) + + # Garantir que o diretório de saída exista antes de salvar + os.makedirs("output", exist_ok=True) + + # Salvar o esboço em um arquivo + with open("output/guide_outline.json", "w") as f: + json.dump(outline_dict, f, indent=2) + + print(f"Guide outline created with {len(self.state.guide_outline.sections)} sections") + return self.state.guide_outline + + @listen(create_guide_outline) + def write_and_compile_guide(self, outline): + """Escrever todas as seções e compilar o guia""" + print("Writing guide sections and compiling...") + completed_sections = [] + + # Processar seções uma por uma para manter o fluxo de contexto + for section in outline.sections: + print(f"Processing section: {section.title}") + + # Construir contexto a partir das seções anteriores + previous_sections_text = "" + if completed_sections: + previous_sections_text = "# Previously Written Sections\n\n" + for title in completed_sections: + previous_sections_text += f"## {title}\n\n" + previous_sections_text += self.state.sections_content.get(title, "") + "\n\n" + else: + previous_sections_text = "No previous sections written yet." + + # Executar a crew de conteúdo para esta seção + result = kickoff_content_crew(inputs={ + "section_title": section.title, + "section_description": section.description, + "audience_level": self.state.audience_level, + "previous_sections": previous_sections_text, + "draft_content": "" + }) + + # Armazenar o conteúdo + self.state.sections_content[section.title] = result.raw + completed_sections.append(section.title) + print(f"Section completed: {section.title}") + + # Compilar o guia final + guide_content = f"# {outline.title}\n\n" + guide_content += f"## Introduction\n\n{outline.introduction}\n\n" + + # Adicionar cada seção em ordem + for section in outline.sections: + section_content = self.state.sections_content.get(section.title, "") + guide_content += f"\n\n{section_content}\n\n" + + # Adicionar conclusão + guide_content += f"## Conclusion\n\n{outline.conclusion}\n\n" + + # Salvar o guia + with open("output/complete_guide.md", "w") as f: + f.write(guide_content) + + print("\nComplete guide compiled and saved to output/complete_guide.md") + return "Guide creation completed successfully" + +def kickoff(): + """Executar o flow criador de guias""" + GuideCreatorFlow().kickoff() + print("\n=== Flow Complete ===") + print("Your comprehensive guide is ready in the output directory.") + print("Open output/complete_guide.md to view it.") + +def plot(): + """Gerar uma visualização do flow""" + flow = GuideCreatorFlow() + flow.plot("guide_creator_flow") + print("Flow visualization saved to guide_creator_flow.html") + +if __name__ == "__main__": + kickoff() +``` + +Vamos analisar o que está acontecendo neste flow: + +1. Definimos modelos Pydantic para dados estruturados, garantindo segurança de tipos e representação clara dos dados. +2. Criamos uma classe de estado para manter dados entre os diferentes passos do flow. +3. Implementamos três etapas principais para o flow: + - Obtenção da entrada do usuário com o decorator `@start()` + - Criação do roteiro do guia com uma chamada direta à LLM + - Processamento das seções com nosso crew de conteúdo +4. Usamos o decorator `@listen()` para estabelecer relações orientadas a eventos entre as etapas + +Este é o poder dos flows – combinar diferentes tipos de processamento (interação com usuário, chamadas diretas a IA, tarefas colaborativas com crews) em um sistema orientado a eventos e coeso. + +## Passo 6: Configure suas Variáveis de Ambiente + +Crie um arquivo `.env` na raiz do projeto com suas chaves de API. Veja o [guia de configuração do LLM](/pt-BR/concepts/llms#setting-up-your-llm) para detalhes sobre como configurar o provedor. + +```sh .env +OPENAI_API_KEY=sua_chave_openai +# ou +GEMINI_API_KEY=sua_chave_gemini +# ou +ANTHROPIC_API_KEY=sua_chave_anthropic +``` + +## Passo 7: Instale as Dependências + +Instale as dependências necessárias: + +```bash +crewai install +``` + +## Passo 8: Execute Seu Flow + +Agora é hora de ver seu flow em ação! Execute-o usando a CLI do CrewAI: + +```bash +crewai run +``` + +Quando você rodar esse comando, verá seu flow ganhando vida: +1. Ele solicitará um tema e o nível do público para você +2. Criará um roteiro estruturado para o seu guia +3. Processará cada seção, com o redator e o revisor colaborando em cada uma +4. Por fim, irá compilar tudo em um guia abrangente + +Isso demonstra o poder dos flows para orquestrar processos complexos envolvendo múltiplos componentes, tanto de IA quanto não-IA. + +## Passo 9: Visualize Seu Flow + +Uma das funcionalidades mais poderosas dos flows é a possibilidade de visualizar sua estrutura: + +```bash +crewai flow plot +``` + +Isso irá criar um arquivo HTML que mostra a estrutura do seu flow, incluindo os relacionamentos entre etapas e o fluxo de dados. Essa visualização pode ser inestimável para entender e depurar flows complexos. + +## Passo 10: Revise o Resultado + +Depois que o flow finalizar, você encontrará dois arquivos no diretório `output`: + +1. `guide_outline.json`: Contém o roteiro estruturado do guia +2. `complete_guide.md`: O guia abrangente com todas as seções + +Reserve um momento para revisar esses arquivos e apreciar o que você construiu – um sistema que combina entrada do usuário, interações diretas com IA e trabalho colaborativo de agents para produzir um output complexo e de alta qualidade. + +## A Arte do Possível: Além do Seu Primeiro Flow + +O que você aprendeu neste guia é uma base para criar sistemas de IA muito mais sofisticados. Veja algumas formas de expandir este flow básico: + +### Aprimorando a Interação com o Usuário + +Você pode criar flows mais interativos com: +- Interfaces web para entrada e saída de dados +- Atualizações em tempo real de progresso +- Loops de feedback e refinamento interativos +- Interações multi-stage com o usuário + +### Adicionando Mais Etapas de Processamento + +Você pode expandir seu flow com etapas adicionais para: +- Pesquisa antes da criação do roteiro +- Geração de imagens para ilustrações +- Geração de snippets de código para guias técnicos +- Garantia de qualidade e checagem final de fatos + +### Criando Flows Mais Complexos + +Você pode implementar padrões de flow mais sofisticados: +- Ramificações condicionais com base na preferência do usuário ou tipo de conteúdo +- Processamento paralelo de seções independentes +- Loops de refinamento iterativo com feedback +- Integração a APIs e serviços externos + +### Aplicando a Diferentes Domínios + +Os mesmos padrões podem ser usados para criar flows de: +- **Narrativas interativas**: criação de histórias personalizadas com base na entrada do usuário +- **Inteligência de negócios**: processamento de dados, geração de insights e criação de relatórios +- **Desenvolvimento de produtos**: facilitação de ideação, design e planejamento +- **Sistemas educacionais**: criação de experiências de aprendizagem personalizadas + +## Principais Funcionalidades Demonstradas + +Este flow de criação de guia demonstra diversos recursos poderosos do CrewAI: + +1. **Interação com o usuário**: O flow coleta input diretamente do usuário +2. **Chamadas diretas à LLM**: Usa a classe LLM para interações eficientes e direcionadas com IA +3. **Dados estruturados com Pydantic**: Usa Pydantic para garantir segurança de tipos +4. **Processamento sequencial com contexto**: Escreve seções em ordem, fornecendo as anteriores como contexto +5. **Crews multiagentes**: Utiliza agents especializados (redator e revisor) para criação de conteúdo +6. **Gerenciamento de estado**: Mantém estado entre diferentes etapas do processo +7. **Arquitetura orientada a eventos**: Usa o decorator `@listen` para responder a eventos + +## Entendendo a Estrutura do Flow + +Vamos decompor os principais componentes dos flows para ajudá-lo a entender como construir o seu: + +### 1. Chamadas Diretas à LLM + +Flows permitem que você faça chamadas diretas a modelos de linguagem quando precisa de respostas simples e estruturadas: + +```python +llm = LLM( + model="model-id-here", # gpt-4o, gemini-2.0-flash, anthropic/claude... + response_format=GuideOutline +) +response = llm.call(messages=messages) +``` + +Isso é mais eficiente do que usar um crew quando você precisa de um output específico e estruturado. + +### 2. Arquitetura Orientada a Eventos + +Flows usam decorators para estabelecer relações entre componentes: + +```python +@start() +def get_user_input(self): + # Primeira etapa no flow + # ... + +@listen(get_user_input) +def create_guide_outline(self, state): + # Esta roda quando get_user_input é concluída + # ... +``` + +Isso cria uma estrutura clara e declarativa para sua aplicação. + +### 3. Gerenciamento de Estado + +Flows mantêm o estado entre as etapas, facilitando o compartilhamento de dados: + +```python +class GuideCreatorState(BaseModel): + topic: str = "" + audience_level: str = "" + guide_outline: GuideOutline = None + sections_content: Dict[str, str] = {} +``` + +Isso fornece uma maneira segura e tipada de rastrear e transformar dados ao longo do flow. + +### 4. Integração com Crews + +Flows podem integrar crews para tarefas colaborativas complexas: + +```python +result = kickoff_content_crew(inputs={ + "section_title": section.title, + # ... +}) +``` + +Assim, você usa a ferramenta certa para cada parte da aplicação – chamadas diretas para tarefas simples e crews para colaboração avançada. + +## Próximos Passos + +Agora que você construiu seu primeiro flow, pode: + +1. Experimentar estruturas e padrões mais complexos de flow +2. Testar o uso do `@router()` para criar ramificações condicionais em seus flows +3. Explorar as funções `and_` e `or_` para execuções paralelas e mais complexas +4. Conectar seu flow a APIs externas, bancos de dados ou interfaces de usuário +5. Combinar múltiplos crews especializados em um único flow +6. Criar apps de chat multi-turn com [Flows conversacionais](/pt-BR/guides/flows/conversational-flows) (`kickoff` por mensagem, `ChatSession`, tracing adiado) + + +Parabéns! Você construiu seu primeiro CrewAI Flow que combina código regular, chamadas diretas a LLM e processamento baseado em crews para criar um guia abrangente. Essas habilidades fundamentais permitem criar aplicações de IA cada vez mais sofisticadas, capazes de resolver problemas complexos de múltiplas etapas por meio de controle procedural e inteligência colaborativa. + diff --git a/docs/v1.15.13/pt-BR/guides/flows/inputs-id-deprecation.mdx b/docs/v1.15.13/pt-BR/guides/flows/inputs-id-deprecation.mdx new file mode 100644 index 0000000000..3e17d56401 --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/flows/inputs-id-deprecation.mdx @@ -0,0 +1,142 @@ +--- +title: "Migrando de inputs.id para restore_from_state_id" +description: "Mover fluxos @persist da hidratação obsoleta inputs.id para o campo suportado restore_from_state_id" +icon: "arrow-right-arrow-left" +--- + + + Passar `id` dentro de `inputs` para hidratar um fluxo `@persist` é **obsoleto** e + programado para remoção em uma versão futura. A substituição, `restore_from_state_id`, + está disponível no CrewAI **v1.14.5 e posterior** — os passos abaixo se aplicam uma vez que você + faça a atualização. + + +## Visão Geral + +A maneira documentada de hidratar um fluxo `@persist` de uma execução anterior é passar +o UUID dessa execução como `inputs.id`. O CrewAI agora expõe um campo dedicado, +`restore_from_state_id`, que realiza a mesma hidratação sem sobrecarregar a +carga útil de `inputs` — e sem acoplar a chave de hidratação à identidade da nova execução. + +## Migração + +Se você atualmente inicia um fluxo `@persist` com `inputs={"id": ...}`: + +```python +# Obsoleto +flow = CounterFlow() +flow.kickoff(inputs={"id": "abcd1234-5678-90ef-ghij-klmnopqrstuv"}) +``` + +Mude para `restore_from_state_id`: + +```python +# Suportado +flow = CounterFlow() +flow.kickoff(restore_from_state_id="abcd1234-5678-90ef-ghij-klmnopqrstuv") +``` + +Os dois modos têm semânticas de linhagem diferentes: + +- `inputs={"id": }` (obsoleto) — **retomar**: as gravações são feitas sob o id fornecido, + estendendo a mesma história de `flow_uuid`. +- `restore_from_state_id=` — **dividir**: hidrata o estado a partir de um snapshot, então + grava sob um novo `state.id`. A história do fluxo de origem é preservada. + +Para a maioria dos cenários de produção — reexecutar um fluxo hidratado de um estado anterior — criar um fork +é o que você deseja. Veja [Dominando o Estado do Fluxo](/pt-BR/guides/flows/mastering-flow-state) +para o modelo mental completo. + +Se você iniciar seu fluxo pela API REST do CrewAI AMP, veja [AMP](#amp) abaixo para a +migração equivalente da carga útil. + +## Por que estamos descontinuando `inputs.id` para `@persist`? + +`inputs.id` é atualmente a maneira documentada de retomar um fluxo `@persist` de uma +execução anterior. O problema é que o mesmo UUID faz duas funções ao mesmo tempo: + +1. **Seleciona qual snapshot o `@persist` usa para hidratar** — carrega o estado salvo + sob aquele UUID. +2. **Torna-se o ID de Execução do Fluxo da nova execução** (`state.id` no SDK; + apresentado como `flow_id` em alguns contextos) — cada gravação `@persist` a partir desta + inicialização também cai sob aquele mesmo UUID. + +Esse papel duplo é a causa raiz dos problemas que este guia descreve. Como o +UUID fornecido também é o id da nova execução, duas inicializações que passam o mesmo +`inputs.id` não são duas execuções distintas — elas compartilham um id, compartilham um registro +de persistência e (no AMP) compartilham uma linha na lista de execuções. Não há como dizer +"hidratar a partir deste snapshot, mas registrar esta execução separadamente" sem dividir as +duas responsabilidades. + +`restore_from_state_id` é essa divisão. Ele informa ao `@persist` de qual snapshot hidratar, +enquanto deixa a nova execução livre para receber um novo `state.id`. A +fonte de hidratação e a execução registrada não são mais o mesmo UUID — que é o que +a maioria dos cenários de produção realmente deseja. + +## Cronograma de remoção + +`inputs.id` para hidratação `@persist` está programado para remoção em uma versão futura do +CrewAI. Não há um corte imediato — fluxos existentes continuam a funcionar — mas +uma vez que você atualize para v1.14.5 ou posterior, novo código deve usar `restore_from_state_id`, e +fluxos existentes devem migrar na próxima oportunidade conveniente. + +## AMP + +Se você implantar seu fluxo no CrewAI AMP, a migração se estende à carga útil de inicialização +enviada para sua Crew implantada, e os sintomas visíveis de reutilização de `inputs.id` aparecem +no painel de controle de implantação. As duas subseções abaixo cobrem ambos. + +### Migrando a carga útil de inicialização + +Se você atualmente inicia um fluxo implantado incorporando `id` em `inputs`: + +```bash +# Obsoleto +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + -d '{"inputs": {"id": "abcd1234-5678-90ef-ghij-klmnopqrstuv", "topic": "AI Agent Frameworks"}}' \ + https://your-crew-url.crewai.com/kickoff +``` + +Mova o UUID para o campo `restoreFromStateId` de nível superior: + +```bash +# Suportado +curl -X POST \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_CREW_TOKEN" \ + -d '{ + "inputs": {"topic": "AI Agent Frameworks"}, + "restoreFromStateId": "abcd1234-5678-90ef-ghij-klmnopqrstuv" + }' \ + https://your-crew-url.crewai.com/kickoff +``` + +`restoreFromStateId` fica ao lado de `inputs` na carga útil de inicialização, não dentro dela. O +objeto `inputs` agora carrega apenas valores que seu fluxo realmente consome. + +### O que acontece quando `inputs.id` é reutilizado + +Quando o AMP recebe um kickoff para um fluxo cujo `inputs.id` corresponde a uma execução +existente, ele resolve para o registro existente em vez de criar um novo. A partir +do painel de controle de implantação, você verá: + +- **Status da execução** — o status da nova execução sobrescreve o status da execução anterior. Uma + execução finalizada pode voltar para `running`, ou uma execução `completed` pode mudar para + `error` se a nova inicialização falhar — de qualquer forma, o painel não reflete mais + a execução original. +- **Rastros** — Os OTel traces se acumulam entre as inicializações porque compartilham o mesmo + id de execução; os traces da execução anterior são substituídos ou misturados + com os da nova execução. Uma reprodução passo a passo não corresponde mais a uma única execução. +- **Lista de execuções** — kickoffs que deveriam aparecer como linhas separadas colapsam em + uma única entrada, ocultando o histórico. + +Migrar para `restoreFromStateId` mantém cada kickoff como sua própria execução — com +seu próprio status, traces e entrada na lista — enquanto ainda hidrata o estado de uma +execução anterior. + + + Entre em contato com nossa equipe de suporte se você não tiver certeza de qual modo seu fluxo precisa ou se encontrar problemas + durante a migração. + diff --git a/docs/v1.15.13/pt-BR/guides/flows/mastering-flow-state.mdx b/docs/v1.15.13/pt-BR/guides/flows/mastering-flow-state.mdx new file mode 100644 index 0000000000..1d3e6ee42d --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/flows/mastering-flow-state.mdx @@ -0,0 +1,815 @@ +--- +title: Dominando o Gerenciamento de Estado em Flows +description: Um guia abrangente sobre como gerenciar, persistir e utilizar o estado em CrewAI Flows para construir aplicações de IA robustas. +icon: diagram-project +mode: "wide" +--- + +## Entendendo o Poder do Estado em Flows + +O gerenciamento de estado é a espinha dorsal de qualquer workflow de IA sofisticado. Nos Flows da CrewAI, o sistema de estado permite manter o contexto, compartilhar dados entre etapas e construir lógicas de aplicação complexas. Dominar o gerenciamento de estado é essencial para criar aplicações de IA confiáveis, sustentáveis e poderosas. + +Este guia vai te levar por tudo o que você precisa saber sobre como gerenciar o estado em CrewAI Flows, desde conceitos básicos até técnicas avançadas, com exemplos práticos de código ao longo do conteúdo. + +### Por Que o Gerenciamento de Estado Importa + +Um gerenciamento de estado efetivo possibilita que você: + +1. **Mantenha o contexto entre as etapas de execução** – Transfira informações de forma transparente entre diferentes estágios do seu workflow +2. **Construa lógicas condicionais complexas** – Tome decisões baseadas nos dados acumulados +3. **Crie aplicações persistentes** – Salve e recupere o progresso do workflow +4. **Trate erros de forma elegante** – Implemente padrões de recuperação para aplicações mais robustas +5. **Escalone suas aplicações** – Ofereça suporte a workflows complexos com organização apropriada dos dados +6. **Habilite aplicações conversacionais** – Armazene e acesse o histórico da conversa para interações de IA com contexto + +Para chat multi-turn (`kickoff` por linha do usuário, `ChatState`, roteamento por intenção, tracing adiado e `ChatSession`), veja [Flows conversacionais](/pt-BR/guides/flows/conversational-flows). + +Vamos explorar como aproveitar essas capacidades de forma eficiente. + +## Fundamentos do Gerenciamento de Estado + +### O Ciclo de Vida do Estado em um Flow + +Nos Flows da CrewAI, o estado segue um ciclo de vida previsível: + +1. **Inicialização** – Quando um flow é criado, seu estado é inicializado (como um dicionário vazio ou uma instância de modelo Pydantic) +2. **Modificação** – Os métodos do flow acessam e modificam o estado durante a execução +3. **Transmissão** – O estado é automaticamente passado entre os métodos do flow +4. **Persistência** (opcional) – O estado pode ser salvo em um armazenamento e recuperado posteriormente +5. **Conclusão** – O estado final reflete as mudanças acumuladas de todos os métodos executados + +Compreender esse ciclo de vida é crucial para projetar flows eficientes. + +### Duas Abordagens Para Gerenciar Estado + +A CrewAI oferece duas maneiras para você gerenciar o estado nos seus flows: + +1. **Estado Não Estruturado** – Usando objetos do tipo dicionário para mais flexibilidade +2. **Estado Estruturado** – Usando modelos Pydantic para segurança de tipo e validação + +Vamos analisar cada abordagem em detalhe. + +## Gerenciamento de Estado Não Estruturado + +O estado não estruturado utiliza uma abordagem semelhante a dicionários, oferecendo flexibilidade e simplicidade para aplicações diretas. + +### Como Funciona + +Com estado não estruturado: +- Você acessa o estado via `self.state`, que se comporta como um dicionário +- Pode adicionar, modificar ou remover chaves livremente a qualquer momento +- Todo o estado está disponível automaticamente para todos os métodos do flow + +### Exemplo Básico + +Veja um exemplo simples de gerenciamento de estado não estruturado: + +```python +from crewai.flow.flow import Flow, listen, start + +class UnstructuredStateFlow(Flow): + @start() + def initialize_data(self): + print("Initializing flow data") + # Adiciona pares chave-valor ao estado + self.state["user_name"] = "Alex" + self.state["preferences"] = { + "theme": "dark", + "language": "English" + } + self.state["items"] = [] + + # O estado do flow recebe automaticamente um ID único + print(f"Flow ID: {self.state['id']}") + + return "Initialized" + + @listen(initialize_data) + def process_data(self, previous_result): + print(f"Previous step returned: {previous_result}") + + # Acessa e modifica o estado + user = self.state["user_name"] + print(f"Processing data for {user}") + + # Adiciona itens a uma lista no estado + self.state["items"].append("item1") + self.state["items"].append("item2") + + # Adiciona um novo par chave-valor + self.state["processed"] = True + + return "Processed" + + @listen(process_data) + def generate_summary(self, previous_result): + # Acessa múltiplos valores do estado + user = self.state["user_name"] + theme = self.state["preferences"]["theme"] + items = self.state["items"] + processed = self.state.get("processed", False) + + summary = f"User {user} has {len(items)} items with {theme} theme. " + summary += "Data is processed." if processed else "Data is not processed." + + return summary + +# Executa o flow +flow = UnstructuredStateFlow() +result = flow.kickoff() +print(f"Final result: {result}") +print(f"Final state: {flow.state}") +``` + +### Quando Usar Estado Não Estruturado + +O estado não estruturado é ideal para: +- Prototipagem rápida e flows simples +- Necessidade de estado que evolui dinamicamente +- Casos onde a estrutura pode não ser conhecida antecipadamente +- Flows com requisitos de estado simples + +Embora seja flexível, o estado não estruturado não possui checagem de tipos nem validação de esquema, o que pode gerar erros em aplicações mais complexas. + +## Gerenciamento de Estado Estruturado + +O estado estruturado utiliza modelos Pydantic para definir um esquema para o estado do seu flow, provendo segurança de tipo, validação e melhor experiência de desenvolvimento. + +### Como Funciona + +Ao utilizar estado estruturado: +- Você define um modelo Pydantic que representa a estrutura do seu estado +- Passa este tipo de modelo para sua classe Flow como parâmetro de tipo +- Acessa o estado via `self.state`, que se comporta como uma instância do modelo Pydantic +- Todos os campos são validados de acordo com os tipos definidos +- O IDE oferece autocompletar e suporte à checagem de tipos + +### Exemplo Básico + +Veja como implementar o gerenciamento de estado estruturado: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel, Field +from typing import List, Dict, Optional + +# Define o modelo de estado +class UserPreferences(BaseModel): + theme: str = "light" + language: str = "English" + +class AppState(BaseModel): + user_name: str = "" + preferences: UserPreferences = UserPreferences() + items: List[str] = [] + processed: bool = False + completion_percentage: float = 0.0 + +# Cria um flow com estado tipado +class StructuredStateFlow(Flow[AppState]): + @start() + def initialize_data(self): + print("Initializing flow data") + # Define valores do estado (com checagem de tipo) + self.state.user_name = "Taylor" + self.state.preferences.theme = "dark" + + # O campo ID está disponível automaticamente + print(f"Flow ID: {self.state.id}") + + return "Initialized" + + @listen(initialize_data) + def process_data(self, previous_result): + print(f"Processing data for {self.state.user_name}") + + # Modifica o estado (com checagem de tipo) + self.state.items.append("item1") + self.state.items.append("item2") + self.state.processed = True + self.state.completion_percentage = 50.0 + + return "Processed" + + @listen(process_data) + def generate_summary(self, previous_result): + # Acessa o estado (com autocompletar) + summary = f"User {self.state.user_name} has {len(self.state.items)} items " + summary += f"with {self.state.preferences.theme} theme. " + summary += "Data is processed." if self.state.processed else "Data is not processed." + summary += f" Completion: {self.state.completion_percentage}%" + + return summary + +# Executa o flow +flow = StructuredStateFlow() +result = flow.kickoff() +print(f"Final result: {result}") +print(f"Final state: {flow.state}") +``` + +### Benefícios do Estado Estruturado + +Utilizar estado estruturado traz várias vantagens: + +1. **Segurança de Tipo** – Detecte erros de tipo durante o desenvolvimento +2. **Autodocumentação** – O modelo de estado documenta claramente quais dados estão disponíveis +3. **Validação** – Validação automática de tipos de dados e restrições +4. **Suporte do IDE** – Obtenha autocompletar e documentação inline +5. **Valores Padrão** – Defina facilmente valores padrões para falta de dados + +### Quando Usar Estado Estruturado + +O estado estruturado é recomendado para: +- Flows complexos com esquemas de dados bem definidos +- Projetos em equipe com múltiplos desenvolvedores no mesmo código +- Aplicações onde a validação de dados é importante +- Flows que precisam impor tipos de dados e restrições específicas + +## O ID de Estado Automático + +Tanto estados não estruturados quanto estruturados recebem automaticamente um identificador único (UUID) para ajudar a rastrear e gerenciar instâncias de estado. + +### Como Funciona + +- Para estado não estruturado, o ID é acessível via `self.state["id"]` +- Para estado estruturado, o ID é acessível via `self.state.id` +- Este ID é gerado automaticamente ao criar o flow +- O ID permanece igual durante todo o ciclo de vida do flow +- O ID pode ser usado para rastreamento, logs e recuperação de estados persistidos + +Este UUID é útil especialmente ao implementar persistência ou monitorar múltiplas execuções de flows. + +## Atualizações Dinâmicas de Estado + +Independente de você usar estado estruturado ou não estruturado, é possível atualizar o estado dinamicamente ao longo da execução do flow. + +### Passando Dados Entre Etapas + +Métodos do flow podem retornar valores que serão passados como argumento para métodos listeners: + +```python +from crewai.flow.flow import Flow, listen, start + +class DataPassingFlow(Flow): + @start() + def generate_data(self): + # Este valor de retorno será passado para os métodos listeners + return "Generated data" + + @listen(generate_data) + def process_data(self, data_from_previous_step): + print(f"Received: {data_from_previous_step}") + # Você pode modificar os dados e repassá-los adiante + processed_data = f"{data_from_previous_step} - processed" + # Também atualiza o estado + self.state["last_processed"] = processed_data + return processed_data + + @listen(process_data) + def finalize_data(self, processed_data): + print(f"Received processed data: {processed_data}") + # Acessa tanto os dados passados quanto o estado + last_processed = self.state.get("last_processed", "") + return f"Final: {processed_data} (from state: {last_processed})" +``` + +Esse padrão permite combinar passagem de dados direta com atualizações de estado para obter máxima flexibilidade. + +## Persistindo o Estado do Flow + +Uma das funcionalidades mais poderosas da CrewAI é a habilidade de persistir o estado do flow entre execuções. Isso habilita workflows que podem ser pausados, retomados e até recuperados após falhas. + +### O Decorador @persist() + +O decorador `@persist()` automatiza a persistência de estado, salvando o estado do flow em pontos chave da execução. + +#### Persistência em Nível de Classe + +Ao aplicar em nível de classe, `@persist()` salva o estado após cada execução de método: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + value: int = 0 + +@persist() # Aplica à classe inteira do flow +class PersistentCounterFlow(Flow[CounterState]): + @start() + def increment(self): + self.state.value += 1 + print(f"Incremented to {self.state.value}") + return self.state.value + + @listen(increment) + def double(self, value): + self.state.value = value * 2 + print(f"Doubled to {self.state.value}") + return self.state.value + +# Primeira execução +flow1 = PersistentCounterFlow() +result1 = flow1.kickoff() +print(f"First run result: {result1}") + +# Segunda execução - passa o ID para carregar o estado persistido +flow2 = PersistentCounterFlow() +result2 = flow2.kickoff(inputs={"id": flow1.state.id}) +print(f"Second run result: {result2}") # Será maior devido ao estado persistido +``` + +#### Persistência em Nível de Método + +Para mais controle, você pode aplicar `@persist()` em métodos específicos: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai.flow.persistence import persist + +class SelectivePersistFlow(Flow): + @start() + def first_step(self): + self.state["count"] = 1 + return "First step" + + @persist() # Persiste apenas após este método + @listen(first_step) + def important_step(self, prev_result): + self.state["count"] += 1 + self.state["important_data"] = "This will be persisted" + return "Important step completed" + + @listen(important_step) + def final_step(self, prev_result): + self.state["count"] += 1 + return f"Complete with count {self.state['count']}" +``` + +#### Forking de Estado Persistido + +`@persist` suporta dois modos distintos de hidratação em `kickoff` / `kickoff_async`. Use **resume** (`inputs["id"]`) para continuar a mesma linhagem; use **fork** (`restore_from_state_id`) para iniciar uma nova linhagem a partir de um snapshot: + +| | `state.id` após o kickoff | Escritas do `@persist` vão para | +|---|---|---| +| `inputs["id"]` (resume) | id informado | id informado (estende o histórico) | +| `restore_from_state_id` (fork) | id novo, ou `inputs["id"]` se fixado | id novo (origem preservada) | + +```python +from crewai.flow.flow import Flow, start +from crewai.flow.persistence import persist +from pydantic import BaseModel + +class CounterState(BaseModel): + id: str = "" + counter: int = 0 + +@persist +class CounterFlow(Flow[CounterState]): + @start() + def step(self): + self.state.counter += 1 + +# Execução 1: estado novo, counter 0 -> 1 +flow_1 = CounterFlow() +flow_1.kickoff() + +# Fork: hidrata do snapshot mais recente de flow_1, mas escreve sob um state.id NOVO +flow_2 = CounterFlow() +flow_2.kickoff(restore_from_state_id=flow_1.state.id) +# flow_2 começa com counter=1 (hidratado), e step() incrementa para 2. +# O histórico do flow_uuid de flow_1 não é alterado. +``` + +Notas sobre o comportamento: + +- `restore_from_state_id` não encontrado na persistência → o kickoff retorna silenciosamente ao comportamento padrão (espelha o comportamento de `inputs["id"]` quando não encontrado). Nenhuma exceção é lançada. +- Combinar `restore_from_state_id` com `from_checkpoint` lança um `ValueError` — eles miram sistemas de estado diferentes (`@persist` vs. Checkpointing) e não podem ser combinados. +- `restore_from_state_id=None` (padrão) é byte-idêntico a um kickoff sem o parâmetro. +- Fixar `inputs["id"]` durante o fork significa que a nova execução compartilha uma chave de persistência com outro flow — geralmente você quer apenas `restore_from_state_id`. + +## Padrões Avançados de Estado + +### Lógica Condicional Baseada no Estado + +Você pode usar o estado para implementar lógicas condicionais complexas em seus flows: + +```python +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +class PaymentState(BaseModel): + amount: float = 0.0 + is_approved: bool = False + retry_count: int = 0 + +class PaymentFlow(Flow[PaymentState]): + @start() + def process_payment(self): + # Simula o processamento do pagamento + self.state.amount = 100.0 + self.state.is_approved = self.state.amount < 1000 + return "Payment processed" + + @router(process_payment) + def check_approval(self, previous_result): + if self.state.is_approved: + return "approved" + elif self.state.retry_count < 3: + return "retry" + else: + return "rejected" + + @listen("approved") + def handle_approval(self): + return f"Payment of ${self.state.amount} approved!" + + @listen("retry") + def handle_retry(self): + self.state.retry_count += 1 + print(f"Retrying payment (attempt {self.state.retry_count})...") + # Aqui poderia ser implementada a lógica de retry + return "Retry initiated" + + @listen("rejected") + def handle_rejection(self): + return f"Payment of ${self.state.amount} rejected after {self.state.retry_count} retries." +``` + +### Manipulações Complexas de Estado + +Para transformar estados complexos, você pode criar métodos dedicados: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel +from typing import List, Dict + +class UserData(BaseModel): + name: str + active: bool = True + login_count: int = 0 + +class ComplexState(BaseModel): + users: Dict[str, UserData] = {} + active_user_count: int = 0 + +class TransformationFlow(Flow[ComplexState]): + @start() + def initialize(self): + # Adiciona alguns usuários + self.add_user("alice", "Alice") + self.add_user("bob", "Bob") + self.add_user("charlie", "Charlie") + return "Initialized" + + @listen(initialize) + def process_users(self, _): + # Incrementa contagens de login + for user_id in self.state.users: + self.increment_login(user_id) + + # Desativa um usuário + self.deactivate_user("bob") + + # Atualiza a contagem de ativos + self.update_active_count() + + return f"Processed {len(self.state.users)} users" + + # Métodos auxiliares para transformações de estado + def add_user(self, user_id: str, name: str): + self.state.users[user_id] = UserData(name=name) + self.update_active_count() + + def increment_login(self, user_id: str): + if user_id in self.state.users: + self.state.users[user_id].login_count += 1 + + def deactivate_user(self, user_id: str): + if user_id in self.state.users: + self.state.users[user_id].active = False + self.update_active_count() + + def update_active_count(self): + self.state.active_user_count = sum( + 1 for user in self.state.users.values() if user.active + ) +``` + +Esse padrão de criar métodos auxiliares mantém seus métodos de flow limpos, enquanto permite manipulações complexas de estado. + +## Gerenciamento de Estado com Crews + +Um dos padrões mais poderosos na CrewAI é combinar o gerenciamento de estado do flow com a execução de crews. + +### Passando Estado para Crews + +Você pode usar o estado do flow para parametrizar crews: + +```python +from crewai.flow.flow import Flow, listen, start +from crewai import Agent, Crew, Process, Task +from pydantic import BaseModel + +class ResearchState(BaseModel): + topic: str = "" + depth: str = "medium" + results: str = "" + +class ResearchFlow(Flow[ResearchState]): + @start() + def get_parameters(self): + # Em uma aplicação real, isso pode vir da entrada do usuário + self.state.topic = "Artificial Intelligence Ethics" + self.state.depth = "deep" + return "Parameters set" + + @listen(get_parameters) + def execute_research(self, _): + # Cria os agentes + researcher = Agent( + role="Research Specialist", + goal=f"Research {self.state.topic} in {self.state.depth} detail", + backstory="You are an expert researcher with a talent for finding accurate information." + ) + + writer = Agent( + role="Content Writer", + goal="Transform research into clear, engaging content", + backstory="You excel at communicating complex ideas clearly and concisely." + ) + + # Cria as tarefas + research_task = Task( + description=f"Research {self.state.topic} with {self.state.depth} analysis", + expected_output="Comprehensive research notes in markdown format", + agent=researcher + ) + + writing_task = Task( + description=f"Create a summary on {self.state.topic} based on the research", + expected_output="Well-written article in markdown format", + agent=writer, + context=[research_task] + ) + + # Cria e executa a crew + research_crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + verbose=True + ) + + # Executa a crew e armazena o resultado no estado + result = research_crew.kickoff() + self.state.results = result.raw + + return "Research completed" + + @listen(execute_research) + def summarize_results(self, _): + # Acessa os resultados armazenados + result_length = len(self.state.results) + return f"Research on {self.state.topic} completed with {result_length} characters of results." +``` + +### Manipulando Saídas de Crews no Estado + +Quando um crew finaliza, é possível processar sua saída e armazená-la no estado do flow: + +```python +@listen(execute_crew) +def process_crew_results(self, _): + # Faz parsing dos resultados brutos (assumindo saída em JSON) + import json + try: + results_dict = json.loads(self.state.raw_results) + self.state.processed_results = { + "title": results_dict.get("title", ""), + "main_points": results_dict.get("main_points", []), + "conclusion": results_dict.get("conclusion", "") + } + return "Results processed successfully" + except json.JSONDecodeError: + self.state.error = "Failed to parse crew results as JSON" + return "Error processing results" +``` + +## Boas Práticas para Gerenciamento de Estado + +### 1. Mantenha o Estado Focado + +Projete seu estado para conter somente o necessário: + +```python +# Abrangente demais +class BloatedState(BaseModel): + user_data: Dict = {} + system_settings: Dict = {} + temporary_calculations: List = [] + debug_info: Dict = {} + # ...muitos outros campos + +# Melhor: estado focado +class FocusedState(BaseModel): + user_id: str + preferences: Dict[str, str] + completion_status: Dict[str, bool] +``` + +### 2. Use Estado Estruturado em Flows Complexos + +À medida que seus flows evoluem em complexidade, o estado estruturado se torna cada vez mais valioso: + +```python +# Flow simples pode usar estado não estruturado +class SimpleGreetingFlow(Flow): + @start() + def greet(self): + self.state["name"] = "World" + return f"Hello, {self.state['name']}!" + +# Flow complexo se beneficia de estado estruturado +class UserRegistrationState(BaseModel): + username: str + email: str + verification_status: bool = False + registration_date: datetime = Field(default_factory=datetime.now) + last_login: Optional[datetime] = None + +class RegistrationFlow(Flow[UserRegistrationState]): + # Métodos com acesso ao estado fortemente tipado +``` + +### 3. Documente Transições de Estado + +Para flows complexos, documente como o estado muda ao longo da execução: + +```python +@start() +def initialize_order(self): + """ + Initialize order state with empty values. + + State before: {} + State after: {order_id: str, items: [], status: 'new'} + """ + self.state.order_id = str(uuid.uuid4()) + self.state.items = [] + self.state.status = "new" + return "Order initialized" +``` + +### 4. Trate Erros de Estado de Forma Elegante + +Implemente tratamento de erros ao acessar o estado: + +```python +@listen(previous_step) +def process_data(self, _): + try: + # Tenta acessar um valor que pode não existir + user_preference = self.state.preferences.get("theme", "default") + except (AttributeError, KeyError): + # Trata o erro de forma elegante + self.state.errors = self.state.get("errors", []) + self.state.errors.append("Failed to access preferences") + user_preference = "default" + + return f"Used preference: {user_preference}" +``` + +### 5. Use o Estado Para Acompanhar o Progresso + +Aproveite o estado para monitorar o progresso em flows de longa duração: + +```python +class ProgressTrackingFlow(Flow): + @start() + def initialize(self): + self.state["total_steps"] = 3 + self.state["current_step"] = 0 + self.state["progress"] = 0.0 + self.update_progress() + return "Initialized" + + def update_progress(self): + """Helper method to calculate and update progress""" + if self.state.get("total_steps", 0) > 0: + self.state["progress"] = (self.state.get("current_step", 0) / + self.state["total_steps"]) * 100 + print(f"Progress: {self.state['progress']:.1f}%") + + @listen(initialize) + def step_one(self, _): + # Realiza o trabalho... + self.state["current_step"] = 1 + self.update_progress() + return "Step 1 complete" + + # Etapas adicionais... +``` + +### 6. Prefira Operações Imutáveis Quando Possível + +Especialmente com estado estruturado, prefira operações imutáveis para maior clareza: + +```python +# Em vez de modificar listas no local: +self.state.items.append(new_item) # Operação mutável + +# Considere criar um novo estado: +from pydantic import BaseModel +from typing import List + +class ItemState(BaseModel): + items: List[str] = [] + +class ImmutableFlow(Flow[ItemState]): + @start() + def add_item(self): + # Cria uma nova lista com o item adicionado + self.state.items = [*self.state.items, "new item"] + return "Item added" +``` + +## Depurando o Estado do Flow + +### Logando Alterações no Estado + +Ao desenvolver, adicione logs para acompanhar mudanças no estado: + +```python +import logging +logging.basicConfig(level=logging.INFO) + +class LoggingFlow(Flow): + def log_state(self, step_name): + logging.info(f"State after {step_name}: {self.state}") + + @start() + def initialize(self): + self.state["counter"] = 0 + self.log_state("initialize") + return "Initialized" + + @listen(initialize) + def increment(self, _): + self.state["counter"] += 1 + self.log_state("increment") + return f"Incremented to {self.state['counter']}" +``` + +### Visualizando o Estado + +Você pode adicionar métodos para visualizar seu estado durante o debug: + +```python +def visualize_state(self): + """Create a simple visualization of the current state""" + import json + from rich.console import Console + from rich.panel import Panel + + console = Console() + + if hasattr(self.state, "model_dump"): + # Pydantic v2 + state_dict = self.state.model_dump() + elif hasattr(self.state, "dict"): + # Pydantic v1 + state_dict = self.state.dict() + else: + # Estado não estruturado + state_dict = dict(self.state) + + # Remove o id para uma saída mais limpa + if "id" in state_dict: + state_dict.pop("id") + + state_json = json.dumps(state_dict, indent=2, default=str) + console.print(Panel(state_json, title="Current Flow State")) +``` + +## Conclusão + +Dominar o gerenciamento de estado em CrewAI Flows te dá poder para construir aplicações de IA sofisticadas e robustas, que mantêm contexto, tomam decisões complexas e entregam resultados consistentes. + +Seja escolhendo estado não estruturado ou estruturado, implementar boas práticas de gerenciamento de estado irá ajudar a criar flows manteníveis, extensíveis e eficazes na resolução de problemas do mundo real. + +À medida que desenvolver flows mais complexos, lembre-se de que um bom gerenciamento de estado está relacionado ao equilíbrio entre flexibilidade e estrutura, tornando seu código tanto poderoso quanto fácil de entender. + + +Agora você domina os conceitos e práticas de gerenciamento de estado em CrewAI Flows! Com este conhecimento, você pode criar workflows de IA robustos que mantêm contexto, compartilham dados entre as etapas e constroem lógicas avançadas de aplicação. + + +## Próximos Passos + +- Experimente usar estado estruturado e não estruturado em seus flows +- Teste a implementação de persistência de estado para workflows de longa duração +- Explore [como construir seu primeiro crew](/pt-BR/guides/crews/first-crew) para ver como crews e flows podem funcionar juntos +- Confira a [documentação de referência de Flow](/pt-BR/concepts/flows) para funcionalidades mais avançadas diff --git a/docs/v1.15.13/pt-BR/guides/migration/migrating-from-langgraph.mdx b/docs/v1.15.13/pt-BR/guides/migration/migrating-from-langgraph.mdx new file mode 100644 index 0000000000..4889c91f62 --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/migration/migrating-from-langgraph.mdx @@ -0,0 +1,518 @@ +--- +title: "Migrando do LangGraph para o CrewAI: um guia prático para engenheiros" +description: Se você já construiu com LangGraph, saiba como portar rapidamente seus projetos para o CrewAI +icon: switch +mode: "wide" +--- + +Você construiu agentes com LangGraph. Já lutou com o `StateGraph`, ligou arestas condicionais e depurou dicionários de estado às 2 da manhã. Funciona — mas, em algum momento, você começou a se perguntar se existe um caminho melhor para produção. + +Existe. **CrewAI Flows** entrega o mesmo poder — orquestração orientada a eventos, roteamento condicional, estado compartilhado — com muito menos boilerplate e um modelo mental que se alinha a como você realmente pensa sobre fluxos de trabalho de IA em múltiplas etapas. + +Este artigo apresenta os conceitos principais lado a lado, mostra comparações reais de código e demonstra por que o CrewAI Flows é o framework que você vai querer usar a seguir. + +--- + +## A Mudança de Modelo Mental + +LangGraph pede que você pense em **grafos**: nós, arestas e dicionários de estado. Todo workflow é um grafo direcionado em que você conecta explicitamente as transições entre as etapas de computação. É poderoso, mas a abstração traz overhead — especialmente quando o seu fluxo é fundamentalmente sequencial com alguns pontos de decisão. + +CrewAI Flows pede que você pense em **eventos**: métodos que iniciam, métodos que escutam resultados e métodos que roteiam a execução. A topologia do workflow emerge de anotações com decorators, em vez de construção explícita do grafo. Isso não é apenas açúcar sintático — muda como você projeta, lê e mantém seus pipelines. + +Veja o mapeamento principal: + +| Conceito no LangGraph | Equivalente no CrewAI Flows | +| --- | --- | +| `StateGraph` class | `Flow` class | +| `add_node()` | Methods decorated with `@start`, `@listen` | +| `add_edge()` / `add_conditional_edges()` | `@listen()` / `@router()` decorators | +| `TypedDict` state | Pydantic `BaseModel` state | +| `START` / `END` constants | `@start()` decorator / natural method return | +| `graph.compile()` | `flow.kickoff()` | +| Checkpointer / persistence | Built-in memory (LanceDB-backed) | + +Vamos ver como isso fica na prática. + +--- + +## Demo 1: Um Pipeline Sequencial Simples + +Imagine que você está construindo um pipeline que recebe um tema, pesquisa, escreve um resumo e formata a saída. Veja como cada framework lida com isso. + +### Abordagem com LangGraph + +```python +from typing import TypedDict +from langgraph.graph import StateGraph, START, END + +class ResearchState(TypedDict): + topic: str + raw_research: str + summary: str + formatted_output: str + +def research_topic(state: ResearchState) -> dict: + # Call an LLM or search API + result = llm.invoke(f"Research the topic: {state['topic']}") + return {"raw_research": result} + +def write_summary(state: ResearchState) -> dict: + result = llm.invoke( + f"Summarize this research:\n{state['raw_research']}" + ) + return {"summary": result} + +def format_output(state: ResearchState) -> dict: + result = llm.invoke( + f"Format this summary as a polished article section:\n{state['summary']}" + ) + return {"formatted_output": result} + +# Build the graph +graph = StateGraph(ResearchState) +graph.add_node("research", research_topic) +graph.add_node("summarize", write_summary) +graph.add_node("format", format_output) + +graph.add_edge(START, "research") +graph.add_edge("research", "summarize") +graph.add_edge("summarize", "format") +graph.add_edge("format", END) + +# Compile and run +app = graph.compile() +result = app.invoke({"topic": "quantum computing advances in 2026"}) +print(result["formatted_output"]) +``` + +Você define funções, registra-as como nós e conecta manualmente cada transição. Para uma sequência simples como essa, há muita cerimônia. + +### Abordagem com CrewAI Flows + +```python +from crewai import LLM, Agent, Crew, Process, Task +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class ResearchState(BaseModel): + topic: str = "" + raw_research: str = "" + summary: str = "" + formatted_output: str = "" + +class ResearchFlow(Flow[ResearchState]): + @start() + def research_topic(self): + # Option 1: Direct LLM call + result = llm.call(f"Research the topic: {self.state.topic}") + self.state.raw_research = result + return result + + @listen(research_topic) + def write_summary(self, research_output): + # Option 2: A single agent + summarizer = Agent( + role="Research Summarizer", + goal="Produce concise, accurate summaries of research content", + backstory="You are an expert at distilling complex research into clear, " + "digestible summaries.", + llm=llm, + verbose=True, + ) + result = summarizer.kickoff( + f"Summarize this research:\n{self.state.raw_research}" + ) + self.state.summary = str(result) + return self.state.summary + + @listen(write_summary) + def format_output(self, summary_output): + # Option 3: a complete crew (with one or more agents) + formatter = Agent( + role="Content Formatter", + goal="Transform research summaries into polished, publication-ready article sections", + backstory="You are a skilled editor with expertise in structuring and " + "presenting technical content for a general audience.", + llm=llm, + verbose=True, + ) + format_task = Task( + description=f"Format this summary as a polished article section:\n{self.state.summary}", + expected_output="A well-structured, polished article section ready for publication.", + agent=formatter, + ) + crew = Crew( + agents=[formatter], + tasks=[format_task], + process=Process.sequential, + verbose=True, + ) + result = crew.kickoff() + self.state.formatted_output = str(result) + return self.state.formatted_output + +# Run the flow +flow = ResearchFlow() +flow.state.topic = "quantum computing advances in 2026" +result = flow.kickoff() +print(flow.state.formatted_output) + +``` + +Repare a diferença: nada de construção de grafo, de ligação de arestas, nem de etapa de compilação. A ordem de execução é declarada exatamente onde a lógica vive. `@start()` marca o ponto de entrada, e `@listen(method_name)` encadeia as etapas. O estado é um modelo Pydantic de verdade, com segurança de tipos, validação e auto-complete na IDE. + +--- + +## Demo 2: Roteamento Condicional + +Aqui é que fica interessante. Digamos que você está construindo um pipeline de conteúdo que roteia para diferentes caminhos de processamento com base no tipo de conteúdo detectado. + +### Abordagem com LangGraph + +```python +from typing import TypedDict, Literal +from langgraph.graph import StateGraph, START, END + +class ContentState(TypedDict): + input_text: str + content_type: str + result: str + +def classify_content(state: ContentState) -> dict: + content_type = llm.invoke( + f"Classify this content as 'technical', 'creative', or 'business':\n{state['input_text']}" + ) + return {"content_type": content_type.strip().lower()} + +def process_technical(state: ContentState) -> dict: + result = llm.invoke(f"Process as technical doc:\n{state['input_text']}") + return {"result": result} + +def process_creative(state: ContentState) -> dict: + result = llm.invoke(f"Process as creative writing:\n{state['input_text']}") + return {"result": result} + +def process_business(state: ContentState) -> dict: + result = llm.invoke(f"Process as business content:\n{state['input_text']}") + return {"result": result} + +# Routing function +def route_content(state: ContentState) -> Literal["technical", "creative", "business"]: + return state["content_type"] + +# Build the graph +graph = StateGraph(ContentState) +graph.add_node("classify", classify_content) +graph.add_node("technical", process_technical) +graph.add_node("creative", process_creative) +graph.add_node("business", process_business) + +graph.add_edge(START, "classify") +graph.add_conditional_edges( + "classify", + route_content, + { + "technical": "technical", + "creative": "creative", + "business": "business", + } +) +graph.add_edge("technical", END) +graph.add_edge("creative", END) +graph.add_edge("business", END) + +app = graph.compile() +result = app.invoke({"input_text": "Explain how TCP handshakes work"}) +``` + +Você precisa de uma função de roteamento separada, de um mapeamento explícito de arestas condicionais e de arestas de término para cada ramificação. A lógica de roteamento fica desacoplada do nó que produz a decisão. + +### Abordagem com CrewAI Flows + +```python +from crewai import LLM, Agent +from crewai.flow.flow import Flow, listen, router, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class ContentState(BaseModel): + input_text: str = "" + content_type: str = "" + result: str = "" + +class ContentFlow(Flow[ContentState]): + @start() + def classify_content(self): + self.state.content_type = ( + llm.call( + f"Classify this content as 'technical', 'creative', or 'business':\n" + f"{self.state.input_text}" + ) + .strip() + .lower() + ) + return self.state.content_type + + @router(classify_content) + def route_content(self, classification): + if classification == "technical": + return "process_technical" + elif classification == "creative": + return "process_creative" + else: + return "process_business" + + @listen("process_technical") + def handle_technical(self): + agent = Agent( + role="Technical Writer", + goal="Produce clear, accurate technical documentation", + backstory="You are an expert technical writer who specializes in " + "explaining complex technical concepts precisely.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as technical doc:\n{self.state.input_text}") + ) + + @listen("process_creative") + def handle_creative(self): + agent = Agent( + role="Creative Writer", + goal="Craft engaging and imaginative creative content", + backstory="You are a talented creative writer with a flair for " + "compelling storytelling and vivid expression.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as creative writing:\n{self.state.input_text}") + ) + + @listen("process_business") + def handle_business(self): + agent = Agent( + role="Business Writer", + goal="Produce professional, results-oriented business content", + backstory="You are an experienced business writer who communicates " + "strategy and value clearly to professional audiences.", + llm=llm, + verbose=True, + ) + self.state.result = str( + agent.kickoff(f"Process as business content:\n{self.state.input_text}") + ) + +flow = ContentFlow() +flow.state.input_text = "Explain how TCP handshakes work" +flow.kickoff() +print(flow.state.result) + +``` + +O decorator `@router()` transforma um método em um ponto de decisão. Ele retorna uma string que corresponde a um listener — sem dicionários de mapeamento, sem funções de roteamento separadas. A lógica de ramificação parece um `if` em Python porque *é* um. + +--- + +## Demo 3: Integrando Crews de Agentes de IA em Flows + +É aqui que o verdadeiro poder do CrewAI aparece. Flows não servem apenas para encadear chamadas de LLM — elas orquestram **Crews** completas de agentes autônomos. Isso é algo para o qual o LangGraph simplesmente não tem um equivalente nativo. + +```python +from crewai import Agent, Task, Crew +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ArticleState(BaseModel): + topic: str = "" + research: str = "" + draft: str = "" + final_article: str = "" + +class ArticleFlow(Flow[ArticleState]): + + @start() + def run_research_crew(self): + """A full Crew of agents handles research.""" + researcher = Agent( + role="Senior Research Analyst", + goal=f"Produce comprehensive research on: {self.state.topic}", + backstory="You're a veteran analyst known for thorough, " + "well-sourced research reports.", + llm="gpt-4o" + ) + + research_task = Task( + description=f"Research '{self.state.topic}' thoroughly. " + "Cover key trends, data points, and expert opinions.", + expected_output="A detailed research brief with sources.", + agent=researcher + ) + + crew = Crew(agents=[researcher], tasks=[research_task]) + result = crew.kickoff() + self.state.research = result.raw + return result.raw + + @listen(run_research_crew) + def run_writing_crew(self, research_output): + """A different Crew handles writing.""" + writer = Agent( + role="Technical Writer", + goal="Write a compelling article based on provided research.", + backstory="You turn complex research into engaging, clear prose.", + llm="gpt-4o" + ) + + editor = Agent( + role="Senior Editor", + goal="Review and polish articles for publication quality.", + backstory="20 years of editorial experience at top tech publications.", + llm="gpt-4o" + ) + + write_task = Task( + description=f"Write an article based on this research:\n{self.state.research}", + expected_output="A well-structured draft article.", + agent=writer + ) + + edit_task = Task( + description="Review, fact-check, and polish the draft article.", + expected_output="A publication-ready article.", + agent=editor + ) + + crew = Crew(agents=[writer, editor], tasks=[write_task, edit_task]) + result = crew.kickoff() + self.state.final_article = result.raw + return result.raw + +# Run the full pipeline +flow = ArticleFlow() +flow.state.topic = "The Future of Edge AI" +flow.kickoff() +print(flow.state.final_article) +``` + +Este é o insight-chave: **Flows fornecem a camada de orquestração, e Crews fornecem a camada de inteligência.** Cada etapa em um Flow pode subir uma equipe completa de agentes colaborativos, cada um com seus próprios papéis, objetivos e ferramentas. Você obtém fluxo de controle estruturado e previsível *e* colaboração autônoma de agentes — o melhor dos dois mundos. + +No LangGraph, alcançar algo similar significa implementar manualmente protocolos de comunicação entre agentes, loops de chamada de ferramentas e lógica de delegação dentro das funções dos nós. É possível, mas é encanamento que você constrói do zero todas as vezes. + +--- + +## Demo 4: Execução Paralela e Sincronização + +Pipelines do mundo real frequentemente precisam dividir o trabalho e juntar os resultados. O CrewAI Flows lida com isso de forma elegante com os operadores `and_` e `or_`. + +```python +from crewai import LLM +from crewai.flow.flow import Flow, and_, listen, start +from pydantic import BaseModel + +llm = LLM(model="openai/gpt-5.2") + +class AnalysisState(BaseModel): + topic: str = "" + market_data: str = "" + tech_analysis: str = "" + competitor_intel: str = "" + final_report: str = "" + +class ParallelAnalysisFlow(Flow[AnalysisState]): + @start() + def start_method(self): + pass + + @listen(start_method) + def gather_market_data(self): + # Your agentic or deterministic code + pass + + @listen(start_method) + def run_tech_analysis(self): + # Your agentic or deterministic code + pass + + @listen(start_method) + def gather_competitor_intel(self): + # Your agentic or deterministic code + pass + + @listen(and_(gather_market_data, run_tech_analysis, gather_competitor_intel)) + def synthesize_report(self): + # Your agentic or deterministic code + pass + +flow = ParallelAnalysisFlow() +flow.state.topic = "AI-powered developer tools" +flow.kickoff() + +``` + +Vários decorators `@start()` disparam em paralelo. O combinador `and_()` no decorator `@listen` garante que `synthesize_report` só execute depois que *todos os três* métodos upstream forem concluídos. Também existe `or_()` para quando você quer prosseguir assim que *qualquer* tarefa upstream terminar. + +No LangGraph, você precisaria construir um padrão fan-out/fan-in com ramificações paralelas, um nó de sincronização e uma mesclagem de estado cuidadosa — tudo conectado explicitamente por arestas. + +--- + +## Por que CrewAI Flows em Produção + +Além de uma sintaxe mais limpa, Flows entrega várias vantagens críticas para produção: + +**Persistência de estado integrada.** O estado do Flow é respaldado pelo LanceDB, o que significa que seus workflows podem sobreviver a falhas, ser retomados e acumular conhecimento entre execuções. No LangGraph, você precisa configurar um checkpointer separado. + +**Gerenciamento de estado com segurança de tipos.** Modelos Pydantic oferecem validação, serialização e suporte de IDE prontos para uso. Estados `TypedDict` do LangGraph não validam em runtime. + +**Orquestração de agentes de primeira classe.** Crews são um primitivo nativo. Você define agentes com papéis, objetivos, histórias e ferramentas — e eles colaboram de forma autônoma dentro do envelope estruturado de um Flow. Não é preciso reinventar a coordenação multiagente. + +**Modelo mental mais simples.** Decorators declaram intenção. `@start` significa "comece aqui". `@listen(x)` significa "execute depois de x". `@router(x)` significa "decida para onde ir depois de x". O código lê como o workflow que ele descreve. + +**Integração com CLI.** Execute flows com `crewai run`. Sem etapa de compilação separada, sem serialização de grafo. Seu Flow é uma classe Python, e ele roda como tal. + +--- + +## Cheat Sheet de Migração + +Se você está com uma base de código LangGraph e quer migrar para o CrewAI Flows, aqui vai um guia prático de conversão: + +1. **Mapeie seu estado.** Converta seu `TypedDict` para um `BaseModel` do Pydantic. Adicione valores padrão para todos os campos. +2. **Converta nós em métodos.** Cada função de `add_node` vira um método na sua subclasse de `Flow`. Substitua leituras `state["field"]` por `self.state.field`. +3. **Substitua arestas por decorators.** `add_edge(START, "first_node")` vira `@start()` no primeiro método. A sequência `add_edge("a", "b")` vira `@listen(a)` no método `b`. +4. **Substitua arestas condicionais por `@router`.** A função de roteamento e o mapeamento do `add_conditional_edges()` viram um único método `@router()` que retorna a string de rota. +5. **Troque compile + invoke por kickoff.** Remova `graph.compile()`. Chame `flow.kickoff()`. +6. **Considere onde as Crews se encaixam.** Qualquer nó com lógica complexa de agentes em múltiplas etapas é um candidato a extração para uma Crew. É aqui que você verá a maior melhoria de qualidade. + +--- + +## Primeiros Passos + +Instale o CrewAI e crie o scaffold de um novo projeto Flow: + +```bash +pip install crewai +crewai create flow my_first_flow +cd my_first_flow +``` + +Isso gera uma estrutura de projeto com uma classe Flow pronta para edição, arquivos de configuração e um `pyproject.toml` com `type = "flow"` já definido. Execute com: + +```bash +crewai run +``` + +A partir daí, adicione seus agentes, conecte seus listeners e publique. + +--- + +## Considerações Finais + +O LangGraph ensinou ao ecossistema que workflows de IA precisam de estrutura. Essa foi uma lição importante. Mas o CrewAI Flows pega essa lição e a entrega de um jeito mais rápido de escrever, mais fácil de ler e mais poderoso em produção — especialmente quando seus workflows envolvem múltiplos agentes colaborando. + +Se você está construindo algo além de uma cadeia de agente único, dê uma olhada séria no Flows. O modelo baseado em decorators, a integração nativa com Crews e o gerenciamento de estado embutido significam menos tempo com encanamento e mais tempo nos problemas que importam. + +Comece com `crewai create flow`. Você não vai olhar para trás. diff --git a/docs/v1.15.13/pt-BR/guides/migration/upgrading-crewai.mdx b/docs/v1.15.13/pt-BR/guides/migration/upgrading-crewai.mdx new file mode 100644 index 0000000000..0c7472d0aa --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/migration/upgrading-crewai.mdx @@ -0,0 +1,190 @@ +--- +title: "Atualizando o CrewAI" +description: "Como atualizar o CrewAI no seu projeto e adaptar-se a breaking changes entre versões." +icon: "arrow-up-circle" +--- + +## Visão Geral + +Os lançamentos do CrewAI trazem novos recursos regularmente. Este guia mostra os passos práticos para manter sua instalação atualizada — tanto a CLI quanto o ambiente virtual do seu projeto. + +Se você está começando do zero, veja [Instalação](/pt-BR/installation). Se está vindo de outro framework, veja [Migrando do LangGraph](/pt-BR/guides/migration/migrating-from-langgraph). + +--- + +## As Duas Coisas Que Você Pode Querer Atualizar + +O CrewAI vive em dois lugares na sua máquina, e cada um se atualiza de forma independente: + +| O quê | Como é instalado | Como atualizar | +|---|---|---| +| A **CLI global `crewai`** | `uv tool install crewai` | `uv tool install crewai --upgrade` | +| O **venv do projeto** (onde seu código roda) | `crewai install` / `uv sync` | `uv add "crewai[...]>=X.Y.Z"` e depois `crewai install` | + +Esses dois podem — e frequentemente ficam — fora de sincronia. Rodar `crewai --version` mostra a versão da CLI. Rodar `uv pip show crewai` dentro do seu projeto mostra a versão do venv. Se forem diferentes, isso é normal; o que importa para o código em execução é a versão do venv. + +## Por Que `crewai install` Sozinho Não Atualiza + +`crewai install` é um wrapper fino em torno de `uv sync`. Ele instala exatamente o que o arquivo `uv.lock` atual diz — ele **não** muda nenhuma restrição de versão. + +Se seu `pyproject.toml` diz `crewai>=1.11.1` e o lock file resolveu para `1.11.1`, executar `crewai install` vai te manter em `1.11.1` para sempre, mesmo que `1.14.4` esteja disponível. + +Para realmente atualizar, você precisa: + +1. Atualizar a restrição de versão em `pyproject.toml` +2. Re-resolver o lock file +3. Sincronizar o venv + +`uv add` faz os três de uma vez só. + +## Como Atualizar Seu Projeto + +```bash +# Aumenta a restrição e re-resolve o lock em um único comando +uv add "crewai[tools]>=1.14.4" + +# Sincroniza o venv (crewai install chama uv sync por baixo dos panos) +crewai install + +# Verifica +uv pip show crewai +# → Version: 1.14.4 +``` + +Substitua `[tools]` por quaisquer extras que seu projeto utilize (ex.: `[tools,anthropic]`). Verifique a lista de `dependencies` do seu `pyproject.toml` se estiver em dúvida. + + + `uv add` atualiza tanto `pyproject.toml` **quanto** `uv.lock` atomicamente. Se você editar `pyproject.toml` manualmente, ainda precisa rodar `uv lock --upgrade-package crewai` para re-resolver o lock file antes que `crewai install` pegue a nova versão. + + +## Atualizando a CLI Global + +A CLI global é separada do seu projeto. Atualize com: + +```bash +uv tool install crewai --upgrade +``` + +Se seu shell avisar sobre o `PATH` após a atualização, recarregue-o: + +```bash +uv tool update-shell +``` + +Isso **não** mexe no venv do seu projeto — você ainda precisa de `uv add` + `crewai install` dentro do projeto. + +## Verifique Se Ambos Estão em Sincronia + +```bash +# Versão da CLI global +crewai --version + +# Versão do venv do projeto +uv pip show crewai | grep Version +``` + +Eles não precisam coincidir — mas a versão do venv do projeto é o que importa para o comportamento em runtime. + + + CrewAI requer `Python >=3.10, <3.14`. Se o `uv` foi instalado contra um interpretador mais antigo, recrie o venv do projeto com uma versão suportada do Python antes de rodar `crewai install`. + + +--- + +## Breaking Changes e Notas de Migração + +A maioria das atualizações requer apenas pequenos ajustes. As áreas abaixo são as que quebram silenciosamente ou com tracebacks confusos. + +### Caminhos de import: tools e `BaseTool` + +O caminho canônico para tools é `crewai.tools`. Caminhos antigos ainda aparecem em tutoriais, mas devem ser atualizados. + +```python +# Antes +from crewai_tools import BaseTool +from crewai.agents.tools import tool + +# Depois +from crewai.tools import BaseTool, tool +``` + +O decorador `@tool` e a subclasse `BaseTool` ambos vivem em `crewai.tools`. `AgentFinish` e outros símbolos internos do agente não fazem mais parte da superfície pública — se você os estava importando, mude para event listeners ou callbacks de `Task`. + +### Mudanças de parâmetros em `Agent` + +```python +from crewai import Agent + +agent = Agent( + role="Researcher", + goal="Find authoritative sources on {topic}", + backstory="You are a careful, source-driven researcher.", + llm="gpt-4o-mini", # nome do modelo como string OU um objeto LLM + verbose=True, # bool, não um nível inteiro + max_iter=15, # default mudou entre versões — defina explicitamente + allow_delegation=False, +) +``` + +- `llm` aceita tanto um nome de modelo como string (resolvido pelo provedor configurado) quanto um objeto `LLM` para controle granular. +- `verbose` é um `bool` puro. Passar um inteiro não alterna mais níveis de log. +- Os defaults de `max_iter` mudaram entre releases. Se seu agente para silenciosamente de iterar após a primeira chamada de tool, defina `max_iter` explicitamente. + +### Parâmetros de `Crew` + +```python +from crewai import Crew, Process + +crew = Crew( + agents=[...], + tasks=[...], + process=Process.sequential, # ou Process.hierarchical + memory=True, + cache=True, + embedder={"provider": "openai", "config": {"model": "text-embedding-3-small"}}, +) +``` + +- `process=Process.hierarchical` requer ou `manager_llm=` ou `manager_agent=`. Sem um deles, o kickoff lança erro na validação. +- `memory=True` com um provedor de embedding não-default precisa de um dicionário `embedder` — veja [Configuração de memória e embedder](#memory-embedder-config) abaixo. + +### Saída estruturada de `Task` + +Use `output_pydantic`, `output_json` ou `output_file` para forçar o resultado de uma task em um formato tipado: + +```python +from pydantic import BaseModel +from crewai import Task + +class Article(BaseModel): + title: str + body: str + +write = Task( + description="Write an article about {topic}", + expected_output="A short article with a title and body", + agent=writer, + output_pydantic=Article, # a classe, NÃO uma instância + output_file="output/article.md", +) +``` + +`output_pydantic` recebe a **classe** em si. Passar `Article(title="", body="")` é um erro comum e falha com um erro de validação confuso. + +### Configuração de memória e embedder {#memory-embedder-config} + +Se `memory=True` e você não está usando os embeddings padrão da OpenAI, é preciso passar um `embedder`: + +```python +crew = Crew( + agents=[...], + tasks=[...], + memory=True, + embedder={ + "provider": "ollama", + "config": {"model": "nomic-embed-text"}, + }, +) +``` + +Defina as credenciais do provedor relevante (`OPENAI_API_KEY`, `OLLAMA_HOST`, etc.) no seu arquivo `.env`. Os caminhos de armazenamento de memória são locais ao projeto por default — apague o diretório de memória do projeto se trocar de embedder, já que dimensões diferentes não se misturam. diff --git a/docs/v1.15.13/pt-BR/guides/tools/publish-custom-tools.mdx b/docs/v1.15.13/pt-BR/guides/tools/publish-custom-tools.mdx new file mode 100644 index 0000000000..1a56ee8e2b --- /dev/null +++ b/docs/v1.15.13/pt-BR/guides/tools/publish-custom-tools.mdx @@ -0,0 +1,244 @@ +--- +title: Publicar Ferramentas Personalizadas +description: Como construir, empacotar e publicar suas próprias ferramentas compatíveis com CrewAI no PyPI para que qualquer usuário do CrewAI possa instalá-las e usá-las. +icon: box-open +mode: "wide" +--- + +## Visão Geral + +O sistema de ferramentas do CrewAI foi projetado para ser extensível. Se você construiu uma ferramenta que pode beneficiar outros, pode empacotá-la como uma biblioteca Python independente, publicá-la no PyPI e disponibilizá-la para qualquer usuário do CrewAI — sem necessidade de PR para o repositório do CrewAI. + +Este guia percorre todo o processo: implementação do contrato de ferramentas, estruturação do pacote e publicação no PyPI. + + +Se você precisa apenas de uma ferramenta personalizada para seu próprio projeto, consulte o guia [Criar Ferramentas Personalizadas](/pt-BR/learn/create-custom-tools). + + +## O Contrato de Ferramentas + +Toda ferramenta CrewAI deve satisfazer uma das duas interfaces: + +### Opção 1: Subclassificar `BaseTool` + +Subclassifique `crewai.tools.BaseTool` e implemente o método `_run`. Defina `name`, `description` e, opcionalmente, um `args_schema` para validação de entrada. + +```python +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + + +class GeolocateInput(BaseModel): + """Esquema de entrada para GeolocateTool.""" + address: str = Field(..., description="O endereço para geolocalizar.") + + +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converte um endereço em coordenadas de latitude/longitude." + args_schema: type[BaseModel] = GeolocateInput + + def _run(self, address: str) -> str: + # Sua implementação aqui + return f"40.7128, -74.0060" +``` + +### Opção 2: Usar o Decorador `@tool` + +Para ferramentas mais simples, o decorador `@tool` transforma uma função em uma ferramenta CrewAI. A função **deve** ter uma docstring (usada como descrição da ferramenta) e anotações de tipo. + +```python +from crewai.tools import tool + + +@tool("Geolocate") +def geolocate(address: str) -> str: + """Converte um endereço em coordenadas de latitude/longitude.""" + return "40.7128, -74.0060" +``` + +### Requisitos Essenciais + +Independentemente da abordagem escolhida, sua ferramenta deve: + +- Ter um **`name`** — um identificador curto e descritivo. +- Ter uma **`description`** — informa ao agente quando e como usar a ferramenta. Isso afeta diretamente a qualidade do uso da ferramenta pelo agente, então seja claro e específico. +- Implementar **`_run`** (BaseTool) ou fornecer um **corpo de função** (@tool) — a lógica de execução síncrona. +- Usar **anotações de tipo** em todos os parâmetros e valores de retorno. +- Retornar um resultado em **string** (ou algo que possa ser convertido de forma significativa). + +### Opcional: Suporte Assíncrono + +Se sua ferramenta realiza operações de I/O, implemente `_arun` para execução assíncrona: + +```python +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converte um endereço em coordenadas de latitude/longitude." + + def _run(self, address: str) -> str: + # Implementação síncrona + ... + + async def _arun(self, address: str) -> str: + # Implementação assíncrona + ... +``` + +### Opcional: Validação de Entrada com `args_schema` + +Defina um modelo Pydantic como seu `args_schema` para obter validação automática de entrada e mensagens de erro claras. Se não fornecer um, o CrewAI irá inferi-lo da assinatura do seu método `_run`. + +```python +from pydantic import BaseModel, Field + + +class TranslateInput(BaseModel): + """Esquema de entrada para TranslateTool.""" + text: str = Field(..., description="O texto a ser traduzido.") + target_language: str = Field( + default="en", + description="Código de idioma ISO 639-1 para o idioma de destino.", + ) +``` + +Esquemas explícitos são recomendados para ferramentas publicadas — produzem melhor comportamento do agente e documentação mais clara para seus usuários. + +### Opcional: Variáveis de Ambiente + +Se sua ferramenta requer chaves de API ou outra configuração, declare-as com `env_vars` para que os usuários saibam o que configurar: + +```python +from crewai.tools import BaseTool, EnvVar + + +class GeolocateTool(BaseTool): + name: str = "Geolocate" + description: str = "Converte um endereço em coordenadas de latitude/longitude." + env_vars: list[EnvVar] = [ + EnvVar( + name="GEOCODING_API_KEY", + description="Chave de API para o serviço de geocodificação.", + required=True, + ), + ] + + def _run(self, address: str) -> str: + ... +``` + +## Estrutura do Pacote + +Estruture seu projeto como um pacote Python padrão. Layout recomendado: + +``` +crewai-geolocate/ +├── pyproject.toml +├── LICENSE +├── README.md +└── src/ + └── crewai_geolocate/ + ├── __init__.py + └── tools.py +``` + +### `pyproject.toml` + +```toml +[project] +name = "crewai-geolocate" +version = "0.1.0" +description = "Uma ferramenta CrewAI para geolocalizar endereços." +requires-python = ">=3.10" +dependencies = [ + "crewai", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" +``` + +Declare `crewai` como dependência para que os usuários obtenham automaticamente uma versão compatível. + +### `__init__.py` + +Re-exporte suas classes de ferramenta para que os usuários possam importá-las diretamente: + +```python +from crewai_geolocate.tools import GeolocateTool + +__all__ = ["GeolocateTool"] +``` + +### Convenções de Nomenclatura + +- **Nome do pacote**: Use o prefixo `crewai-` (ex.: `crewai-geolocate`). Isso torna sua ferramenta fácil de encontrar no PyPI. +- **Nome do módulo**: Use underscores (ex.: `crewai_geolocate`). +- **Nome da classe da ferramenta**: Use PascalCase terminando em `Tool` (ex.: `GeolocateTool`). + +## Testando sua Ferramenta + +Antes de publicar, verifique se sua ferramenta funciona dentro de uma crew: + +```python +from crewai import Agent, Crew, Task +from crewai_geolocate import GeolocateTool + +agent = Agent( + role="Analista de Localização", + goal="Encontrar coordenadas para os endereços fornecidos.", + backstory="Um especialista em dados geoespaciais.", + tools=[GeolocateTool()], +) + +task = Task( + description="Encontre as coordenadas de 1600 Pennsylvania Avenue, Washington, DC.", + expected_output="A latitude e longitude do endereço.", + agent=agent, +) + +crew = Crew(agents=[agent], tasks=[task]) +result = crew.kickoff() +print(result) +``` + +## Publicando no PyPI + +Quando sua ferramenta estiver testada e pronta: + +```bash +# Construir o pacote +uv build + +# Publicar no PyPI +uv publish +``` + +Se é sua primeira vez publicando, você precisará de uma [conta no PyPI](https://pypi.org/account/register/) e um [token de API](https://pypi.org/help/#apitoken). + +### Após a Publicação + +Os usuários podem instalar sua ferramenta com: + +```bash +pip install crewai-geolocate +``` + +Ou com uv: + +```bash +uv add crewai-geolocate +``` + +E então usá-la em suas crews: + +```python +from crewai_geolocate import GeolocateTool + +agent = Agent( + role="Analista de Localização", + tools=[GeolocateTool()], + # ... +) +``` diff --git a/docs/v1.15.13/pt-BR/index.mdx b/docs/v1.15.13/pt-BR/index.mdx new file mode 100644 index 0000000000..ccf585b1a3 --- /dev/null +++ b/docs/v1.15.13/pt-BR/index.mdx @@ -0,0 +1,102 @@ +--- +title: "CrewAI Documentação" +description: "Construa agentes colaborativos, crews e flows — prontos para produção desde o primeiro dia." +icon: "house" +mode: "wide" +--- + +
+ CrewAI +
+

Construa sistemas multiagentes com confiança

+

+ Crie agentes, orquestre crews e automatize flows com guardrails, memória, conhecimento e observabilidade integrados. +

+
+ + +
+ +
+ + + + Visão geral dos conceitos da CrewAI, arquitetura e casos de uso para agentes, crews e flows. + + + Instale com `uv`, configure chaves de API e prepare o CLI para desenvolvimento local. + + + Crie sua primeira crew em poucos minutos. Aprenda o runtime, a estrutura do projeto e o loop de desenvolvimento. + + + +## Fundamentos + + + + Modele agentes com ferramentas, memória, conhecimento e saídas estruturadas. Inclui templates e boas práticas. + + + Orquestre start/listen/router, gerencie estado, persista execuções e retome processos longos. + + + Defina processos sequenciais, hierárquicos ou híbridos com guardrails, callbacks e intervenção humana. + + + +## Jornada Enterprise + + + + Gerencie ambientes, faça deploy seguro e monitore execuções ao vivo diretamente no console Enterprise. + + + Conecte Gmail, Slack, Salesforce e muito mais. Injete payloads dos triggers em crews e flows automaticamente. + + + Convide integrantes, configure RBAC e controle o acesso às automations em produção. + + + +## Novidades + + + + Guia unificado para Gmail, Drive, Outlook, Teams, OneDrive, HubSpot e outros — com payloads e crews de exemplo. + + + Chame automations CrewAI existentes ou agentes do Amazon Bedrock diretamente das suas crews. + + + + + Acesse os examples e cookbooks para implementações completas envolvendo agentes, flows e automations Enterprise. + + +## Conecte-se + + + + Se a CrewAI acelera seu trabalho, deixe uma estrela e compartilhe seus projetos com a comunidade. + + + Tire dúvidas, divulgue workflows e solicite recursos junto a outros builders. + + diff --git a/docs/v1.15.13/pt-BR/installation.mdx b/docs/v1.15.13/pt-BR/installation.mdx new file mode 100644 index 0000000000..3ee8bb1b71 --- /dev/null +++ b/docs/v1.15.13/pt-BR/installation.mdx @@ -0,0 +1,216 @@ +--- +title: Instalação +description: Comece a usar o CrewAI - Instale, configure e crie seu primeiro crew de IA +icon: wrench +mode: "wide" +--- + +### Assista: Construindo Agents e Flows CrewAI com Coding Agent Skills + +Instale nossas coding agent skills (Claude Code, Codex, ...) para colocar seus agentes de código para funcionar rapidamente com o CrewAI. + +Você pode instalar com `npx skills add crewaiinc/skills` + + + +## Tutorial em Vídeo + +Assista a este tutorial em vídeo para uma demonstração passo a passo do processo de instalação: + + + +## Tutorial em Texto + + + **Requisitos de Versão do Python** + +CrewAI requer `Python >=3.10 e <3.14`. Veja como verificar sua versão: + +```bash +python3 --version +``` + +Se você precisar atualizar o Python, acesse [python.org/downloads](https://python.org/downloads) + + + +CrewAI utiliza o `uv` como ferramenta de gerenciamento de dependências e pacotes. Ele simplifica a configuração e execução do projeto, oferecendo uma experiência fluida. + +Se você ainda não instalou o `uv`, siga o **passo 1** para instalá-lo rapidamente em seu sistema, caso contrário, avance para o **passo 2**. + + + + - **No macOS/Linux:** + + Use `curl` para baixar o script e executá-lo com `sh`: + + ```shell + curl -LsSf https://astral.sh/uv/install.sh | sh + ``` + Se seu sistema não possuir `curl`, você pode usar `wget`: + + ```shell + wget -qO- https://astral.sh/uv/install.sh | sh + ``` + + - **No Windows:** + + Use `irm` para baixar o script e `iex` para executá-lo: + + ```shell + powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" + ``` + Caso enfrente algum problema, consulte o [guia de instalação do UV](https://docs.astral.sh/uv/getting-started/installation/) para mais informações. + + + + - Execute o seguinte comando para instalar o CLI do `crewai`: + ```shell + uv tool install crewai + ``` + + Se aparecer um aviso relacionado ao `PATH`, execute este comando para atualizar seu shell: + ```shell + uv tool update-shell + ``` + + + + Se você encontrar o erro de build ao instalar `chroma-hnswlib==0.7.6` (`fatal error C1083: Cannot open include file: 'float.h'`) no Windows, instale o (Visual Studio Build Tools)[https://visualstudio.microsoft.com/downloads/] com o *Desenvolvimento de Desktop com C++*. + + + - Para verificar se o `crewai` está instalado, execute: + ```shell + uv tool list + ``` + - Você deverá ver algo assim: + ```shell + crewai v0.102.0 + - crewai + ``` + - Caso precise atualizar o `crewai`, execute: + ```shell + uv tool install crewai --upgrade + ``` + Instalação realizada com sucesso! Você está pronto para criar seu primeiro crew! 🎉 + + + + +# Criando um Projeto CrewAI + +`crewai create crew` agora cria um projeto de crew JSON-first. Os agentes ficam em `agents/*.jsonc`, as tarefas e configurações da crew ficam em `crew.jsonc`, e `crewai run` carrega essa definição JSON diretamente. + + + + - Execute o comando CLI do `crewai`: + ```shell + crewai create crew + ``` + + - Isso criará um novo projeto com a seguinte estrutura: + + ``` + my_project/ + ├── .gitignore + ├── .env + ├── agents/ + │ └── researcher.jsonc + ├── crew.jsonc + ├── knowledge/ + ├── pyproject.toml + ├── README.md + ├── skills/ + └── tools/ + ``` + + + - Se você precisar do scaffold antigo em Python/YAML com `crew.py`, `config/agents.yaml` e `config/tasks.yaml`, execute: + ```shell + crewai create crew --classic + ``` + + + + + - Seu projeto conterá estes arquivos essenciais: + | Arquivo | Finalidade | + | --- | --- | + | `crew.jsonc` | Configure a crew, a ordem das tarefas, o processo e os inputs padrão | + | `agents/*.jsonc` | Defina o papel, objetivo, backstory, LLM, ferramentas e comportamento de cada agente | + | `.env` | Armazene chaves de API e variáveis de ambiente | + | `tools/` | Arquivos Python opcionais para ferramentas `custom:` | + | `knowledge/` | Arquivos opcionais de conhecimento para agentes | + | `skills/` | Arquivos opcionais de skills aplicadas à crew | + + - Comece editando `crew.jsonc` e os arquivos em `agents/` para definir o comportamento da crew. + - Use valores `{placeholder}` nos textos de agentes e tarefas e defina padrões em `crew.jsonc` dentro de `inputs`. Ao executar `crewai run`, a CLI pergunta por valores que estiverem faltando. + - Mantenha informações sensíveis como chaves de API no arquivo `.env`. + + + + + - Antes de rodar seu crew, execute: + ```bash + crewai install + ``` + - Se precisar instalar pacotes adicionais, utilize: + ```shell + uv add + ``` + - Para rodar seu crew, execute o seguinte comando na raiz do seu projeto: + ```bash + crewai run + ``` + + + +## Opções de Instalação Enterprise + + +Para equipes e organizações, o CrewAI oferece opções de implantação corporativa que eliminam a complexidade da configuração: + +### CrewAI AMP (SaaS) + +- Zero instalação necessária - basta se cadastrar gratuitamente em [app.crewai.com](https://app.crewai.com) +- Atualizações e manutenção automáticas +- Infraestrutura e escalabilidade gerenciadas +- Construa crews sem código + +### CrewAI Factory (Auto-Hospedado) + +- Implantação containerizada para sua infraestrutura +- Compatível com qualquer hyperscaler, incluindo ambientes on-premises +- Integração com seus sistemas de segurança existentes + + + Saiba mais sobre as soluções enterprise do CrewAI e agende uma demonstração + + + +## Próximos Passos + + + + Siga o guia rápido para gerar um Flow, executar um crew com um agente e produzir um relatório. + + + Conecte-se com outros desenvolvedores, obtenha ajuda e compartilhe suas + experiências com o CrewAI. + + diff --git a/docs/v1.15.13/pt-BR/introduction.mdx b/docs/v1.15.13/pt-BR/introduction.mdx new file mode 100644 index 0000000000..788e2b123f --- /dev/null +++ b/docs/v1.15.13/pt-BR/introduction.mdx @@ -0,0 +1,152 @@ +--- +title: Introdução +description: Construa equipes de agentes de IA que trabalham juntas para resolver tarefas complexas +icon: handshake +mode: "wide" +--- + +# O que é CrewAI? + +**CrewAI é o principal framework open-source para orquestrar agentes de IA autônomos e construir fluxos de trabalho complexos.** + +Ele capacita desenvolvedores a construir sistemas multi-agente prontos para produção, combinando a inteligência colaborativa dos **Crews** com o controle preciso dos **Flows**. + +- **[Flows do CrewAI](/pt-BR/guides/flows/first-flow)**: A espinha dorsal da sua aplicação de IA. Flows permitem criar fluxos de trabalho estruturados e orientados a eventos que gerenciam estado e controlam a execução. Eles fornecem a estrutura para seus agentes de IA trabalharem. +- **[Crews do CrewAI](/pt-BR/guides/crews/first-crew)**: As unidades de trabalho dentro do seu Flow. Crews são equipes de agentes autônomos que colaboram para resolver tarefas específicas delegadas a eles pelo Flow. + +Com mais de 100.000 desenvolvedores certificados em nossos cursos comunitários, o CrewAI é o padrão para automação de IA pronta para empresas. + +### Assista: Construindo Agents e Flows CrewAI com Coding Agent Skills + +Instale nossas coding agent skills (Claude Code, Codex, ...) para colocar seus agentes de código para funcionar rapidamente com o CrewAI. + +Você pode instalar com `npx skills add crewaiinc/skills` + + + +## A Arquitetura do CrewAI + +A arquitetura do CrewAI foi projetada para equilibrar autonomia com controle. + +### 1. Flows: A Espinha Dorsal + + + Pense em um Flow como o "gerente" ou a "definição do processo" da sua aplicação. Ele define as etapas, a lógica e como os dados se movem através do seu sistema. + + + + Visão Geral do Framework CrewAI + + +Flows fornecem: +- **Gerenciamento de Estado**: Persistem dados através de etapas e execuções. +- **Execução Orientada a Eventos**: Acionam ações com base em eventos ou entradas externas. +- **Controle de Fluxo**: Usam lógica condicional, loops e ramificações. + +### 2. Crews: A Inteligência + + + Crews são as "equipes" que fazem o trabalho pesado. Dentro de um Flow, você pode acionar um Crew para lidar com um problema complexo que requer criatividade e colaboração. + + + + Visão Geral do Framework CrewAI + + +Crews fornecem: +- **Agentes com Funções**: Agentes especializados com objetivos e ferramentas específicas. +- **Colaboração Autônoma**: Agentes trabalham juntos para resolver tarefas. +- **Delegação de Tarefas**: Tarefas são atribuídas e executadas com base nas capacidades dos agentes. + +## Como Tudo Funciona Junto + +1. **O Flow** aciona um evento ou inicia um processo. +2. **O Flow** gerencia o estado e decide o que fazer a seguir. +3. **O Flow** delega uma tarefa complexa para um **Crew**. +4. Os agentes do **Crew** colaboram para completar a tarefa. +5. **O Crew** retorna o resultado para o **Flow**. +6. **O Flow** continua a execução com base no resultado. + +## Principais Funcionalidades + + + + Construa fluxos de trabalho confiáveis e com estado que podem lidar com processos de longa duração e lógica complexa. + + + Implante equipes de agentes que podem planejar, executar e colaborar para alcançar objetivos de alto nível. + + + Conecte seus agentes a qualquer API, banco de dados ou ferramenta local. + + + Projetado com segurança e conformidade em mente para implantações empresariais. + + + +## Quando usar Crews vs. Flows + +**A resposta curta: Use ambos.** + +Para qualquer aplicação pronta para produção, **comece com um Flow**. + +- **Use um Flow** para definir a estrutura geral, estado e lógica da sua aplicação. +- **Use um Crew** dentro de uma etapa do Flow quando precisar de uma equipe de agentes para realizar uma tarefa específica e complexa que requer autonomia. + +| Caso de Uso | Arquitetura | +| :--- | :--- | +| **Automação Simples** | Flow único com tarefas Python | +| **Pesquisa Complexa** | Flow gerenciando estado -> Crew realizando pesquisa | +| **Backend de Aplicação** | Flow lidando com requisições API -> Crew gerando conteúdo -> Flow salvando no BD | + +## Por que escolher o CrewAI? + +- 🧠 **Operação Autônoma**: Agentes tomam decisões inteligentes com base em suas funções e nas ferramentas disponíveis +- 📝 **Interação Natural**: Agentes se comunicam e colaboram como membros humanos de uma equipe +- 🛠️ **Design Extensível**: Fácil de adicionar novas ferramentas, funções e capacidades +- 🚀 **Pronto para Produção**: Construído para confiabilidade e escalabilidade em aplicações reais +- 🔒 **Foco em Segurança**: Desenvolvido para atender requisitos de segurança empresarial +- 💰 **Custo-Efetivo**: Otimizado para minimizar o uso de tokens e chamadas de API + +## Pronto para começar a construir? + + + + Aprenda a criar fluxos de trabalho estruturados e orientados por eventos com controle preciso de execução. + + + Tutorial passo a passo para criar uma equipe de IA colaborativa que trabalha junto para resolver problemas complexos. + + + + + + Comece a usar o CrewAI em seu ambiente de desenvolvimento. + + + Gere um Flow, execute um crew com um agente e produza um relatório ponta a ponta. + + + Conecte-se com outros desenvolvedores, obtenha ajuda e compartilhe suas experiências com o CrewAI. + + diff --git a/docs/v1.15.13/pt-BR/learn/before-and-after-kickoff-hooks.mdx b/docs/v1.15.13/pt-BR/learn/before-and-after-kickoff-hooks.mdx new file mode 100644 index 0000000000..0855b2abbd --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/before-and-after-kickoff-hooks.mdx @@ -0,0 +1,61 @@ +--- +title: Hooks Antes e Depois do Kickoff +description: Aprenda a usar hooks antes e depois do kickoff em CrewAI +mode: "wide" +--- + +O CrewAI fornece hooks que permitem executar código antes e depois do kickoff de uma crew. Esses hooks são úteis para pré-processar entradas ou pós-processar resultados. + +## Hook Antes do Kickoff + +O hook antes do kickoff é executado antes da crew iniciar suas tarefas. Ele recebe o dicionário de entradas e pode modificá-lo antes de passá-lo para a crew. Você pode usar esse hook para configurar seu ambiente, carregar dados necessários ou pré-processar suas entradas. Isso é útil em cenários onde os dados de entrada podem precisar de enriquecimento ou validação antes de serem processados pela crew. + +Aqui está um exemplo de como definir uma função antes do kickoff em seu `crew.py`: + +```python +from crewai import CrewBase +from crewai.project import before_kickoff + +@CrewBase +class MinhaEquipe: + @before_kickoff + def preparar_dados(self, entradas): + # Pré-processa ou modifica as entradas + entradas['processado'] = True + return entradas + +#... +``` + +Neste exemplo, a função preparar_dados modifica as entradas adicionando um novo par chave-valor indicando que as entradas foram processadas. + +## Hook Depois do Kickoff + +O hook depois do kickoff é executado após a crew completar suas tarefas. Ele recebe o objeto de resultado, que contém as saídas da execução da crew. Este hook é ideal para pós-processar resultados, como log, transformação de dados ou análise adicional. + +Veja como você pode definir uma função depois do kickoff em seu `crew.py`: + +```python +from crewai import CrewBase +from crewai.project import after_kickoff + +@CrewBase +class MinhaEquipe: + @after_kickoff + def registrar_resultados(self, resultado): + # Registra ou modifica os resultados + print("Execução da equipe concluída com resultado:", resultado) + return resultado + +# ... +``` + +Na função `registrar_resultados`, os resultados da execução da crew são simplesmente impressos. Você pode estender isso para realizar operações mais complexas, como enviar notificações ou integrar com outros serviços. + +## Utilizando Ambos os Hooks + +Ambos os hooks podem ser usados juntos para oferecer um processo completo de preparação e finalização na execução da sua crew. Eles são particularmente úteis para manter uma arquitetura de código limpa, separando responsabilidades e melhorando a modularidade das suas implementações com CrewAI. + +## Conclusão + +Os hooks antes e depois do kickoff em CrewAI oferecem formas poderosas de interagir com o ciclo de vida da execução de uma crew. Ao entender e utilizar esses hooks, você pode aumentar significativamente a robustez e flexibilidade dos seus agentes de IA. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/bring-your-own-agent.mdx b/docs/v1.15.13/pt-BR/learn/bring-your-own-agent.mdx new file mode 100644 index 0000000000..2a5d7c5514 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/bring-your-own-agent.mdx @@ -0,0 +1,442 @@ +--- +title: Traga seu próprio agente +description: Aprenda como trazer seus próprios agentes que funcionam dentro de uma Crew. +icon: robots +mode: "wide" +--- + +Interoperabilidade é um conceito fundamental no CrewAI. Este guia mostrará como trazer seus próprios agentes para funcionar dentro de uma Crew. + +## Guia de Adaptação para trazer seus próprios agentes (Agentes Langgraph, Agentes OpenAI, etc...) +Requeremos 3 adaptadores para tornar qualquer agente de diferentes frameworks compatível com uma crew. + +1. BaseAgentAdapter +2. BaseToolAdapter +3. BaseConverter + +## BaseAgentAdapter +Esta classe abstrata define a interface comum e a funcionalidade que todos +os adaptadores de agente devem implementar. Ela estende BaseAgent para manter compatibilidade +com o framework CrewAI, ao mesmo tempo em que adiciona requisitos específicos do adaptador. + +Métodos obrigatórios: + +1. `def configure_tools` +2. `def configure_structured_output` + +## Criando seu próprio Adaptador +Para integrar um agente de um framework diferente (por exemplo, LangGraph, Autogen, OpenAI Assistants) ao CrewAI, você precisa criar um adaptador customizado herdando de `BaseAgentAdapter`. Esse adaptador atua como uma camada de compatibilidade, traduzindo entre as interfaces do CrewAI e os requisitos específicos do seu agente externo. + +Veja como implementar seu adaptador customizado: + +1. **Herdar de `BaseAgentAdapter`**: + ```python + from crewai.agents.agent_adapters.base_agent_adapter import BaseAgentAdapter + from crewai.tools import BaseTool + from typing import List, Optional, Any, Dict + + class MyCustomAgentAdapter(BaseAgentAdapter): + # ... detalhes da implementação ... + ``` + +2. **Implementar `__init__`**: + O construtor deve chamar o construtor da classe pai `super().__init__(**kwargs)` e executar qualquer inicialização específica do seu agente externo. Você pode usar o dicionário opcional `agent_config` passado durante a inicialização do `Agent` do CrewAI para configurar seu adaptador e o agente subjacente. + + ```python + def __init__(self, agent_config: Optional[Dict[str, Any]] = None, **kwargs: Any): + super().__init__(agent_config=agent_config, **kwargs) + # Inicialize seu agente externo aqui, possivelmente usando agent_config + # Exemplo: self.external_agent = initialize_my_agent(agent_config) + print(f"Inicializando MyCustomAgentAdapter com config: {agent_config}") + ``` + +3. **Implementar `configure_tools`**: + Este método abstrato é crucial. Ele recebe uma lista de instâncias de `BaseTool` do CrewAI. Sua implementação deve converter ou adaptar essas ferramentas para o formato esperado pelo seu framework de agente externo. Isso pode envolver encapsulamento, extração de atributos específicos ou registro delas na instância do agente externo. + + ```python + def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None: + if tools: + adapted_tools = [] + for tool in tools: + # Adapte o CrewAI BaseTool para o formato que seu agente espera + # Exemplo: adapted_tool = adapt_to_my_framework(tool) + # adapted_tools.append(adapted_tool) + pass # Substitua pela sua lógica real de adaptação + + # Configure o agente externo com as ferramentas adaptadas + # Exemplo: self.external_agent.set_tools(adapted_tools) + print(f"Configurando ferramentas para MyCustomAgentAdapter: {adapted_tools}") # Placeholder + else: + # Caso nenhum ferramenta seja fornecida + # Exemplo: self.external_agent.set_tools([]) + print("Nenhuma ferramenta fornecida para MyCustomAgentAdapter.") + ``` + +4. **Implementar `configure_structured_output`**: + Esse método é chamado quando o `Agent` do CrewAI é configurado com requisitos de saída estruturada (por exemplo, `output_json` ou `output_pydantic`). Seu adaptador precisa garantir que o agente externo esteja configurado para cumprir esses requisitos. Isso pode envolver definir parâmetros específicos no agente externo ou garantir que seu modelo subjacente suporte o formato solicitado. Se o agente externo não suportar saída estruturada de forma compatível com as expectativas do CrewAI, talvez seja necessário lidar com a conversão ou lançar um erro apropriado. + + ```python + def configure_structured_output(self, structured_output: Any) -> None: + # Configure seu agente externo para produzir saída no formato especificado + # Exemplo: self.external_agent.set_output_format(structured_output) + self.adapted_structured_output = True # Sinaliza que a saída estruturada foi tratada + print(f"Configurando saída estruturada para MyCustomAgentAdapter: {structured_output}") + ``` + +Implementando esses métodos, seu `MyCustomAgentAdapter` permitirá que sua implementação personalizada de agente funcione corretamente dentro de uma crew do CrewAI, interagindo com tarefas e ferramentas de forma transparente. Lembre-se de substituir os comentários e prints de exemplo pela sua lógica real de adaptação específica do framework externo que está integrando. + +## Implementação de BaseToolAdapter +A classe `BaseToolAdapter` é responsável por converter os objetos nativos `BaseTool` do CrewAI em um formato que o seu framework de agente externo possa entender e utilizar. Diferentes frameworks de agentes (como LangGraph, OpenAI Assistants, etc.) possuem suas próprias formas de definir e tratar ferramentas, e o `BaseToolAdapter` age como tradutor. + +Veja como implementar seu adaptador de ferramentas personalizado: + +1. **Herdar de `BaseToolAdapter`**: + ```python + from crewai.agents.agent_adapters.base_tool_adapter import BaseToolAdapter + from crewai.tools import BaseTool + from typing import List, Any + + class MyCustomToolAdapter(BaseToolAdapter): + # ... detalhes da implementação ... + ``` + +2. **Implementar `configure_tools`**: + Este é o método abstrato principal que você deve implementar. Ele recebe uma lista de instâncias de `BaseTool` fornecidas ao agente. Sua tarefa é iterar por essa lista, adaptar cada `BaseTool` para o formato esperado pelo seu framework externo e armazenar as ferramentas convertidas na lista `self.converted_tools` (inicializada no construtor da classe base). + + ```python + def configure_tools(self, tools: List[BaseTool]) -> None: + """Configura e converte ferramentas do CrewAI para a implementação específica.""" + self.converted_tools = [] # Reseta caso seja chamado múltiplas vezes + for tool in tools: + # Sanitizar o nome da ferramenta se necessário pelo framework alvo + sanitized_name = self.sanitize_tool_name(tool.name) + + # --- Sua lógica de conversão aqui --- + # Exemplo: Converter BaseTool para formato de dicionário para LangGraph + # converted_tool = { + # "name": sanitized_name, + # "description": tool.description, + # "parameters": tool.args_schema.schema() if tool.args_schema else {}, + # # Adicione outros campos específicos do framework + # } + + # Exemplo: Converter BaseTool para definição de função OpenAI + # converted_tool = { + # "type": "function", + # "function": { + # "name": sanitized_name, + # "description": tool.description, + # "parameters": tool.args_schema.schema() if tool.args_schema else {"type": "object", "properties": {}}, + # } + # } + + # --- Substitua os exemplos acima pela sua adaptação real --- + converted_tool = self.adapt_tool_to_my_framework(tool, sanitized_name) # Placeholder + + self.converted_tools.append(converted_tool) + print(f"Ferramenta '{tool.name}' adaptada para '{sanitized_name}' em MyCustomToolAdapter") # Placeholder + + print(f"MyCustomToolAdapter terminou de configurar ferramentas: {len(self.converted_tools)} adaptadas.") # Placeholder + + # --- Método auxiliar para adaptação (Exemplo) --- + def adapt_tool_to_my_framework(self, tool: BaseTool, sanitized_name: str) -> Any: + # Substitua pela lógica real para converter um CrewAI BaseTool + # para o formato necessário do framework de agente externo específico. + # Isso pode variar bastante de acordo com o framework. + adapted_representation = { + "framework_specific_name": sanitized_name, + "framework_specific_description": tool.description, + "inputs": tool.args_schema.schema() if tool.args_schema else None, + "implementation_reference": tool.run # Ou conforme o framework precisa chamar + } + # Certifique-se também que a ferramenta funcione tanto síncrona quanto assincronamente + async def async_tool_wrapper(*args, **kwargs): + output = tool.run(*args, **kwargs) + if inspect.isawaitable(output): + return await output + else: + return output + + adapted_tool = MyFrameworkTool( + name=sanitized_name, + description=tool.description, + inputs=tool.args_schema.schema() if tool.args_schema else None, + implementation_reference=async_tool_wrapper + ) + + return adapted_representation + + ``` + +3. **Utilizando o Adaptador**: + Normalmente, você instanciaria seu `MyCustomToolAdapter` dentro do método `configure_tools` do seu `MyCustomAgentAdapter` e o usaria para processar as ferramentas antes de configurar o agente externo. + + ```python + # Dentro de MyCustomAgentAdapter.configure_tools + def configure_tools(self, tools: Optional[List[BaseTool]] = None) -> None: + if tools: + tool_adapter = MyCustomToolAdapter() # Instancia seu adaptador de ferramenta + tool_adapter.configure_tools(tools) # Converte as ferramentas + adapted_tools = tool_adapter.tools() # Obtém as ferramentas convertidas + + # Agora configure seu agente externo com as ferramentas adaptadas + # Exemplo: self.external_agent.set_tools(adapted_tools) + print(f"Configurando agente externo com ferramentas adaptadas: {adapted_tools}") # Placeholder + else: + # Caso sem ferramentas + print("Nenhuma ferramenta fornecida para MyCustomAgentAdapter.") + ``` + +Ao criar um `BaseToolAdapter`, você desacopla a lógica de conversão de ferramenta da adaptação de agente, tornando a integração mais limpa e modular. Lembre-se de substituir os exemplos de placeholder pela lógica de conversão real exigida pelo seu framework externo específico. + +## BaseConverter +O `BaseConverterAdapter` desempenha um papel crucial quando uma `Task` do CrewAI exige que um agente retorne sua saída final em um formato estruturado específico, como JSON ou um modelo Pydantic. Ele faz a ponte entre os requisitos de saída estruturada do CrewAI e as capacidades do seu agente externo. + +Suas responsabilidades principais são: +1. **Configurar o Agente para Saída Estruturada:** Com base nos requisitos da `Task` (`output_json` ou `output_pydantic`), ele instrui o `BaseAgentAdapter` associado (e indiretamente, o agente externo) sobre qual formato é esperado. +2. **Apriorar o Prompt do Sistema:** Ele modifica o prompt do sistema do agente para incluir instruções claras sobre *como* gerar a saída na estrutura exigida. +3. **Pós-processamento do Resultado:** Pega a saída bruta do agente e tenta fazer parsing, validar e formatar conforme a estrutura requerida, retornando por fim uma representação em string (por exemplo, uma string JSON). + +Veja como implementar seu adaptador de conversão customizado: + +1. **Herdar de `BaseConverterAdapter`**: + ```python + from crewai.agents.agent_adapters.base_converter_adapter import BaseConverterAdapter + # Supondo que o seu MyCustomAgentAdapter foi definido + # from .my_custom_agent_adapter import MyCustomAgentAdapter + from crewai.task import Task + from typing import Any + + class MyCustomConverterAdapter(BaseConverterAdapter): + # Armazena o tipo de saída esperado (ex: 'json', 'pydantic', 'text') + _output_type: str = 'text' + _output_schema: Any = None # Armazena o schema JSON ou modelo Pydantic + + # ... detalhes da implementação ... + ``` + +2. **Implementar `__init__`**: + O construtor deve aceitar a instância correspondente de `agent_adapter` com a qual irá trabalhar. + + ```python + def __init__(self, agent_adapter: Any): # Use um type hint específico para seu AgentAdapter + self.agent_adapter = agent_adapter + print(f"Inicializando MyCustomConverterAdapter para o adaptador de agente: {type(agent_adapter).__name__}") + ``` + +3. **Implementar `configure_structured_output`**: + Esse método recebe o objeto `Task` do CrewAI. Você precisa checar os atributos `output_json` e `output_pydantic` da task para determinar a estrutura de saída exigida. Armazene essa informação (por exemplo, em `_output_type` e `_output_schema`) e, potencialmente, chame métodos de configuração no seu `self.agent_adapter` se o agente externo necessitar de um ajuste específico para saída estruturada (algo que pode já ter sido parcialmente feito no `configure_structured_output` do adaptador de agente). + + ```python + def configure_structured_output(self, task: Task) -> None: + """Configura a saída estruturada esperada baseada na task.""" + if task.output_pydantic: + self._output_type = 'pydantic' + self._output_schema = task.output_pydantic + print(f"Converter: Configurado para saída Pydantic: {self._output_schema.__name__}") + elif task.output_json: + self._output_type = 'json' + self._output_schema = task.output_json + print(f"Converter: Configurado para saída JSON com schema: {self._output_schema}") + else: + self._output_type = 'text' + self._output_schema = None + print("Converter: Configurado para saída de texto padrão.") + + # Opcionalmente, informe o agent_adapter se necessário + # self.agent_adapter.set_output_mode(self._output_type, self._output_schema) + ``` + +4. **Implementar `enhance_system_prompt`**: + Este método recebe o prompt base do sistema do agente e deve anexar instruções adaptadas para o `_output_type` e `_output_schema` atualmente configurados. O objetivo é guiar o LLM que alimenta o agente a produzir saída no formato correto. + + ```python + def enhance_system_prompt(self, base_prompt: str) -> str: + """Aprimore o prompt do sistema com instruções de saída estruturada.""" + if self._output_type == 'text': + return base_prompt # Nenhum aprimoramento necessário para texto puro + + instructions = "\n\nSua resposta final DEVE estar formatada como " + if self._output_type == 'json': + schema_str = json.dumps(self._output_schema, indent=2) + instructions += f"um objeto JSON conforme o seguinte schema:\n```json\n{schema_str}\n```" + elif self._output_type == 'pydantic': + schema_str = json.dumps(self._output_schema.model_json_schema(), indent=2) + instructions += f"um objeto JSON conforme o modelo Pydantic '{self._output_schema.__name__}' com o seguinte schema:\n```json\n{schema_str}\n```" + + instructions += "\nGaranta que toda a sua resposta seja APENAS o objeto JSON válido, sem nenhum texto introdutório, explicações ou considerações finais." + + print(f"Converter: Aprimorando prompt para saída {self._output_type}.") + return base_prompt + instructions + ``` + *Nota: O prompt pode precisar de ajustes conforme o agente/LLM usado.* + +5. **Implementar `post_process_result`**: + Esse método recebe a saída em string bruta do agente. Se uma saída estruturada foi solicitada (`json` ou `pydantic`), você deve tentar convertê-la para o formato esperado. Trate erros de parsing caso ocorram (por exemplo, registre-os, tente corrigir, ou lance uma exceção). O método **deve sempre retornar uma string**, mesmo se o formato intermediário seja um dicionário ou objeto Pydantic (por exemplo, serializando novamente para JSON). + + ```python + import json + from pydantic import ValidationError + + def post_process_result(self, result: str) -> str: + """Pós-processa o resultado do agente para garantir que corresponde ao formato esperado.""" + print(f"Converter: Pós-processando resultado para saída {self._output_type}.") + if self._output_type == 'json': + try: + # Tenta fazer parsing e re-serializar para garantir validade e formato consistente + parsed_json = json.loads(result) + # Opcional: Validar contra o schema se for um dicionário JSON schema + # from jsonschema import validate + # validate(instance=parsed_json, schema=self._output_schema) + return json.dumps(parsed_json) + except json.JSONDecodeError as e: + print(f"Erro: Falha ao fazer parsing da saída JSON: {e}\nSaída bruta:\n{result}") + # Trate o erro: retorne bruto, lance exceção, ou tente corrigir + return result # Exemplo: retorna a saída bruta caso falhe + # except Exception as e: # Captura erros de validação se usar jsonschema + # print(f"Erro: saída JSON falhou na validação do schema: {e}\nSaída bruta:\n{result}") + # return result + elif self._output_type == 'pydantic': + try: + # Tenta fazer parsing para o modelo Pydantic + model_instance = self._output_schema.model_validate_json(result) + # Retorna o modelo serializado de volta para JSON + return model_instance.model_dump_json() + except ValidationError as e: + print(f"Erro: Falha ao validar saída Pydantic: {e}\nSaída bruta:\n{result}") + # Trate o erro + return result # Exemplo: retorna a saída bruta caso falhe + except json.JSONDecodeError as e: + print(f"Erro: Falha ao fazer parsing do JSON para o modelo Pydantic: {e}\nSaída bruta:\n{result}") + return result + else: # 'text' + return result # Sem processamento para texto puro + ``` + +Implementando esses métodos, seu `MyCustomConverterAdapter` assegurará que as solicitações de saída estruturada das tarefas do CrewAI sejam corretamente tratadas pelo seu agente externo integrado, aumentando a confiabilidade e a usabilidade do seu agente customizado dentro do framework CrewAI. + +## Adapters prontos para uso + +Fornecemos adapters prontos para uso para os seguintes frameworks: +1. LangGraph +2. Agentes OpenAI + +## Iniciando uma crew com agentes adaptados: + +```python +import json +import os +from typing import List + +from crewai_tools import SerperDevTool +from src.crewai import Agent, Crew, Task +from langchain_openai import ChatOpenAI +from pydantic import BaseModel + +from crewai.agents.agent_adapters.langgraph.langgraph_adapter import ( + LangGraphAgentAdapter, +) +from crewai.agents.agent_adapters.openai_agents.openai_adapter import OpenAIAgentAdapter + +# Agente CrewAI +code_helper_agent = Agent( + role="Code Helper", + goal="Help users solve coding problems effectively and provide clear explanations.", + backstory="You are an experienced programmer with deep knowledge across multiple programming languages and frameworks. You specialize in solving complex coding challenges and explaining solutions clearly.", + allow_delegation=False, + verbose=True, +) +# OpenAI Agent Adapter +link_finder_agent = OpenAIAgentAdapter( + role="Link Finder", + goal="Find the most relevant and high-quality resources for coding tasks.", + backstory="You are a research specialist with a talent for finding the most helpful resources. You're skilled at using search tools to discover documentation, tutorials, and examples that directly address the user's coding needs.", + tools=[SerperDevTool()], + allow_delegation=False, + verbose=True, +) + +# LangGraph Agent Adapter +reporter_agent = LangGraphAgentAdapter( + role="Reporter", + goal="Report the results of the tasks.", + backstory="You are a reporter who reports the results of the other tasks", + llm=ChatOpenAI(model="gpt-4o"), + allow_delegation=True, + verbose=True, +) + + +class Code(BaseModel): + code: str + + +task = Task( + description="Give an answer to the coding question: {task}", + expected_output="A thorough answer to the coding question: {task}", + agent=code_helper_agent, + output_json=Code, +) +task2 = Task( + description="Find links to resources that can help with coding tasks. Use the serper tool to find resources that can help.", + expected_output="A list of links to resources that can help with coding tasks", + agent=link_finder_agent, +) + + +class Report(BaseModel): + code: str + links: List[str] + + +task3 = Task( + description="Report the results of the tasks.", + expected_output="A report of the results of the tasks. this is the code produced and then the links to the resources that can help with the coding task.", + agent=reporter_agent, + output_json=Report, +) +# Usando no CrewAI +crew = Crew( + agents=[code_helper_agent, link_finder_agent, reporter_agent], + tasks=[task, task2, task3], + verbose=True, +) + +result = crew.kickoff( + inputs={"task": "How do you implement an abstract class in python?"} +) + +# Imprima o resultado bruto primeiro +print("Raw result:", result) + +# Lide com o resultado de acordo com seu tipo +if hasattr(result, "json_dict") and result.json_dict: + json_result = result.json_dict + print("\nStructured JSON result:") + print(f"{json.dumps(json_result, indent=2)}") + + # Acesse os campos de forma segura + if isinstance(json_result, dict): + if "code" in json_result: + print("\nCode:") + print( + json_result["code"][:200] + "..." + if len(json_result["code"]) > 200 + else json_result["code"] + ) + + if "links" in json_result: + print("\nLinks:") + for link in json_result["links"][:5]: # Print first 5 links + print(f"- {link}") + if len(json_result["links"]) > 5: + print(f"...and {len(json_result['links']) - 5} more links") +elif hasattr(result, "pydantic") and result.pydantic: + print("\nPydantic model result:") + print(result.pydantic.model_dump_json(indent=2)) +else: + # Fallback para saída bruta + print("\nNo structured result available, using raw output:") + print(result.raw[:500] + "..." if len(result.raw) > 500 else result.raw) + +``` \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/coding-agents.mdx b/docs/v1.15.13/pt-BR/learn/coding-agents.mdx new file mode 100644 index 0000000000..71d82da90d --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/coding-agents.mdx @@ -0,0 +1,96 @@ +--- +title: Agentes de Codificação +description: Aprenda como habilitar seus Agentes CrewAI para escrever e executar código, e explore funcionalidades avançadas para maior potencial. +icon: rectangle-code +mode: "wide" +--- + +## Introdução + +Os Agentes CrewAI agora têm a poderosa capacidade de escrever e executar código, aumentando significativamente suas habilidades de resolução de problemas. Esse recurso é particularmente útil para tarefas que exigem soluções computacionais ou programáticas. + +## Habilitando a Execução de Código + +Para habilitar a execução de código para um agente, defina o parâmetro `allow_code_execution` como `True` ao criar o agente. + +Veja um exemplo: + +```python Code +from crewai import Agent + +coding_agent = Agent( + role="Senior Python Developer", + goal="Craft well-designed and thought-out code", + backstory="You are a senior Python developer with extensive experience in software architecture and best practices.", + allow_code_execution=True +) +``` + + +Observe que o parâmetro `allow_code_execution` é `False` por padrão. + + +## Considerações Importantes + +1. **Seleção de Modelo**: É fortemente recomendado utilizar modelos mais avançados como Claude 3.5 Sonnet e GPT-4 ao habilitar a execução de código. +Esses modelos têm melhor compreensão de conceitos de programação e tendem a gerar códigos mais corretos e eficientes. + +2. **Tratamento de Erros**: O recurso de execução de código inclui tratamento de erros. Se o código executado gerar uma exceção, o agente receberá a mensagem de erro e poderá tentar corrigir o código ou +fornecer soluções alternativas. O parâmetro `max_retry_limit`, que por padrão é 2, controla o número máximo de tentativas para uma tarefa. + +3. **Dependências**: Para usar o recurso de execução de código, é necessário instalar o pacote `crewai_tools`. Caso não esteja instalado, o agente registrará uma mensagem informativa: +"Ferramentas de codificação não disponíveis. Instale crewai_tools." + +## Processo de Execução de Código + +Quando um agente com execução de código habilitada encontra uma tarefa que requer programação: + + + + O agente analisa a tarefa e determina que a execução de código é necessária. + + + Ele formula o código Python necessário para resolver o problema. + + + O código é enviado para a ferramenta interna de execução de código (`CodeInterpreterTool`). + + + O agente interpreta o resultado e o incorpora na sua resposta ou o utiliza para aprofundar a solução do problema. + + + +## Exemplo de Uso + +Veja um exemplo detalhado de como criar um agente com capacidade de execução de código e utilizá-lo em uma tarefa: + +```python Code +from crewai import Agent, Task, Crew + +# Create an agent with code execution enabled +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task that requires code execution +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants.", + agent=coding_agent +) + +# Create a crew and add the task +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +# Execute the crew +result = analysis_crew.kickoff() + +print(result) +``` + +Neste exemplo, o `coding_agent` pode escrever e executar código Python para realizar tarefas de análise de dados. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/conditional-tasks.mdx b/docs/v1.15.13/pt-BR/learn/conditional-tasks.mdx new file mode 100644 index 0000000000..d2f1113db7 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/conditional-tasks.mdx @@ -0,0 +1,90 @@ +--- +title: Tarefas Condicionais +description: Saiba como usar tarefas condicionais em um kickoff do crewAI +icon: diagram-subtask +mode: "wide" +--- + +## Introdução + +As Tarefas Condicionais no crewAI permitem a adaptação dinâmica do fluxo de trabalho com base nos resultados de tarefas anteriores. +Esse recurso poderoso possibilita que crews tomem decisões e executem tarefas seletivamente, aumentando a flexibilidade e a eficiência dos seus processos orientados por IA. + +## Exemplo de Uso + +```python Code +from typing import List +from pydantic import BaseModel +from crewai import Agent, Crew +from crewai.tasks.conditional_task import ConditionalTask +from crewai.tasks.task_output import TaskOutput +from crewai.task import Task +from crewai_tools import SerperDevTool + +# Define a condition function for the conditional task +# If false, the task will be skipped, if true, then execute the task. +def is_data_missing(output: TaskOutput) -> bool: + return len(output.pydantic.events) < 10 # this will skip this task + +# Define the agents +data_fetcher_agent = Agent( + role="Data Fetcher", + goal="Fetch data online using Serper tool", + backstory="Backstory 1", + verbose=True, + tools=[SerperDevTool()] +) + +data_processor_agent = Agent( + role="Data Processor", + goal="Process fetched data", + backstory="Backstory 2", + verbose=True +) + +summary_generator_agent = Agent( + role="Summary Generator", + goal="Generate summary from fetched data", + backstory="Backstory 3", + verbose=True +) + +class EventOutput(BaseModel): + events: List[str] + +task1 = Task( + description="Fetch data about events in San Francisco using Serper tool", + expected_output="List of 10 things to do in SF this week", + agent=data_fetcher_agent, + output_pydantic=EventOutput, +) + +conditional_task = ConditionalTask( + description=""" + Check if data is missing. If we have less than 10 events, + fetch more events using Serper tool so that + we have a total of 10 events in SF this week.. + """, + expected_output="List of 10 Things to do in SF this week", + condition=is_data_missing, + agent=data_processor_agent, +) + +task3 = Task( + description="Generate summary of events in San Francisco from fetched data", + expected_output="A complete report on the customer and their customers and competitors, including their demographics, preferences, market positioning and audience engagement.", + agent=summary_generator_agent, +) + +# Create a crew with the tasks +crew = Crew( + agents=[data_fetcher_agent, data_processor_agent, summary_generator_agent], + tasks=[task1, conditional_task, task3], + verbose=True, + planning=True +) + +# Run the crew +result = crew.kickoff() +print("results", result) +``` \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/create-custom-tools.mdx b/docs/v1.15.13/pt-BR/learn/create-custom-tools.mdx new file mode 100644 index 0000000000..4a09f396d3 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/create-custom-tools.mdx @@ -0,0 +1,124 @@ +--- +title: Criar Ferramentas Personalizadas +description: Guia abrangente sobre como criar, utilizar e gerenciar ferramentas personalizadas dentro do framework CrewAI, incluindo novas funcionalidades e tratamento de erros. +icon: hammer +mode: "wide" +--- + +## Criando e Utilizando Ferramentas no CrewAI + +Este guia traz instruções detalhadas sobre como criar ferramentas personalizadas para o framework CrewAI e como gerenciar e utilizar essas ferramentas de forma eficiente, +incorporando funcionalidades recentes, como delegação de ferramentas, tratamento de erros e chamada dinâmica de ferramentas. Destaca também a importância de ferramentas de colaboração, +permitindo que agentes executem uma ampla gama de ações. + + + **Quer publicar sua ferramenta para a comunidade?** Se você está construindo uma ferramenta que pode beneficiar outros, confira o guia [Publicar Ferramentas Personalizadas](/pt-BR/guides/tools/publish-custom-tools) para aprender como empacotar e distribuir sua ferramenta no PyPI. + + +### Subclassificando `BaseTool` + +Para criar uma ferramenta personalizada, herde de `BaseTool` e defina os atributos necessários, incluindo o `args_schema` para validação de entrada e o método `_run`. + +```python Code +from typing import Type +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class MyToolInput(BaseModel): + """Input schema for MyCustomTool.""" + argument: str = Field(..., description="Description of the argument.") + +class MyCustomTool(BaseTool): + name: str = "Name of my tool" + description: str = "What this tool does. It's vital for effective utilization." + args_schema: Type[BaseModel] = MyToolInput + + def _run(self, argument: str) -> str: + # Your tool's logic here + return "Tool's result" +``` + +### Usando o Decorador `tool` + +Como alternativa, você pode utilizar o decorador de ferramenta `@tool`. Esta abordagem permite definir os atributos e as funcionalidades da ferramenta diretamente em uma função, +oferecendo uma maneira concisa e eficiente de criar ferramentas especializadas de acordo com suas necessidades. + +```python Code +from crewai.tools import tool + +@tool("Tool Name") +def my_simple_tool(question: str) -> str: + """Tool description for clarity.""" + # Tool logic here + return "Tool output" +``` + +### Definindo uma Função de Cache para a Ferramenta + +Para otimizar o desempenho da ferramenta com cache, defina estratégias de cache personalizadas utilizando o atributo `cache_function`. + +```python Code +@tool("Tool with Caching") +def cached_tool(argument: str) -> str: + """Tool functionality description.""" + return "Cacheable result" + +def my_cache_strategy(arguments: dict, result: str) -> bool: + # Define custom caching logic + return True if some_condition else False + +cached_tool.cache_function = my_cache_strategy +``` + +### Criando Ferramentas Assíncronas + +O CrewAI suporta ferramentas assíncronas para operações de I/O não bloqueantes. Isso é útil quando sua ferramenta precisa fazer requisições HTTP, consultas a banco de dados ou outras operações de I/O. + +#### Usando o Decorador `@tool` com Funções Assíncronas + +A maneira mais simples de criar uma ferramenta assíncrona é usando o decorador `@tool` com uma função async: + +```python Code +import aiohttp +from crewai.tools import tool + +@tool("Async Web Fetcher") +async def fetch_webpage(url: str) -> str: + """Fetch content from a webpage asynchronously.""" + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.text() +``` + +#### Subclassificando `BaseTool` com Suporte Assíncrono + +Para maior controle, herde de `BaseTool` e implemente os métodos `_run` (síncrono) e `_arun` (assíncrono): + +```python Code +import requests +import aiohttp +from crewai.tools import BaseTool +from pydantic import BaseModel, Field + +class WebFetcherInput(BaseModel): + """Input schema for WebFetcher.""" + url: str = Field(..., description="The URL to fetch") + +class WebFetcherTool(BaseTool): + name: str = "Web Fetcher" + description: str = "Fetches content from a URL" + args_schema: type[BaseModel] = WebFetcherInput + + def _run(self, url: str) -> str: + """Synchronous implementation.""" + return requests.get(url).text + + async def _arun(self, url: str) -> str: + """Asynchronous implementation for non-blocking I/O.""" + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + return await response.text() +``` + +Seguindo essas orientações e incorporando novas funcionalidades e ferramentas de colaboração nos seus processos de criação e gerenciamento de ferramentas, +você pode aproveitar ao máximo as capacidades do framework CrewAI, aprimorando tanto a experiência de desenvolvimento quanto a eficiência dos seus agentes de IA. diff --git a/docs/v1.15.13/pt-BR/learn/custom-llm.mdx b/docs/v1.15.13/pt-BR/learn/custom-llm.mdx new file mode 100644 index 0000000000..32c6a6689d --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/custom-llm.mdx @@ -0,0 +1,123 @@ +--- +title: Implementação de LLM Personalizada +description: Aprenda a criar implementações personalizadas de LLM no CrewAI. +icon: code +mode: "wide" +--- + +## Visão Geral + +O CrewAI oferece suporte a implementações personalizadas de LLM por meio da classe abstrata `BaseLLM`. Isso permite integrar qualquer provedor de LLM que não tenha suporte nativo no LiteLLM ou implementar mecanismos de autenticação personalizados. + +## Início Rápido + +Aqui está uma implementação mínima de LLM personalizada: + +```python +# (não traduzir blocos de código) +``` + +## Usando Seu LLM Personalizado + +```python +# (não traduzir blocos de código) +``` + +## Métodos Necessários + +### Construtor: `__init__()` + +**Crítico**: Você deve chamar `super().__init__(model, temperature)` com os parâmetros necessários: + +```python +# (não traduzir blocos de código) +``` + +### Método Abstrato: `call()` + +O método `call()` é o núcleo da sua implementação de LLM. Ele deve: + +- Aceitar mensagens (string ou lista de dicionários com 'role' e 'content') +- Retornar uma resposta como string +- Lidar com ferramentas e chamada de funções, se suportado +- Lançar exceções apropriadas para erros + +### Métodos Opcionais + +```python +# (não traduzir blocos de código) +``` + +## Padrões Comuns + +### Tratamento de Erros + +```python +# (não traduzir blocos de código) +``` + +### Autenticação Personalizada + +```python +# (não traduzir blocos de código) +``` + +### Suporte a Stop Words + +O CrewAI adiciona automaticamente `"\nObservation:"` como stop word para controlar o comportamento do agente. Se o seu LLM suporta stop words: + +```python +# (não traduzir blocos de código) +``` + +Se o seu LLM não suporta stop words nativamente: + +```python +# (não traduzir blocos de código) +``` + +## Chamada de Funções + +Se o seu LLM suporta chamada de funções, implemente o fluxo completo: + +```python +# (não traduzir blocos de código) +``` + +## Solução de Problemas + +### Problemas Comuns + +**Erros no Construtor** +```python +# ❌ Errado - parâmetros obrigatórios ausentes +def __init__(self, api_key: str): + super().__init__() + +# ✅ Correto +def __init__(self, model: str, api_key: str, temperature: Optional[float] = None): + super().__init__(model=model, temperature=temperature) +``` + +**Chamada de Funções Não Funciona** +- Certifique-se de que `supports_function_calling()` retorna `True` +- Verifique se você lida com `tool_calls` na resposta +- Assegure-se de que o parâmetro `available_functions` está sendo corretamente utilizado + +**Falhas de Autenticação** +- Verifique o formato e as permissões da chave de API +- Confira o formato do header de autenticação +- Certifique-se de que as URLs dos endpoints estão corretas + +**Erros de Parsing de Resposta** +- Valide a estrutura da resposta antes de acessar campos aninhados +- Trate casos em que o content pode ser None +- Adicione tratamento de erros para respostas malformadas + +## Testando Seu LLM Personalizado + +```python +# (não traduzir blocos de código) +``` + +Este guia cobre o essencial para implementar LLMs personalizados no CrewAI. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/custom-manager-agent.mdx b/docs/v1.15.13/pt-BR/learn/custom-manager-agent.mdx new file mode 100644 index 0000000000..9acefbd05b --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/custom-manager-agent.mdx @@ -0,0 +1,91 @@ +--- +title: Agente Gerente Personalizado +description: Saiba como definir um agente personalizado como gerente no CrewAI, proporcionando mais controle sobre o gerenciamento e a coordenação das tarefas. +icon: user-shield +mode: "wide" +--- + +# Definindo um Agente Específico como Gerente no CrewAI + +O CrewAI permite que usuários definam um agente específico como gerente da crew, oferecendo mais controle sobre o gerenciamento e a coordenação das tarefas. +Esse recurso possibilita a personalização do papel gerencial para se adequar melhor às necessidades do seu projeto. + +## Utilizando o Atributo `manager_agent` + +### Agente Gerente Personalizado + +O atributo `manager_agent` permite que você defina um agente personalizado para gerenciar a crew. Este agente supervisionará todo o processo, garantindo que as tarefas sejam concluídas de forma eficiente e com o mais alto padrão de qualidade. + +### Exemplo + +```python Code +import os +from crewai import Agent, Task, Crew, Process + +# Define your agents +researcher = Agent( + role="Researcher", + goal="Conduct thorough research and analysis on AI and AI agents", + backstory="You're an expert researcher, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently researching for a new client.", + allow_delegation=False, +) + +writer = Agent( + role="Senior Writer", + goal="Create compelling content about AI and AI agents", + backstory="You're a senior writer, specialized in technology, software engineering, AI, and startups. You work as a freelancer and are currently writing content for a new client.", + allow_delegation=False, +) + +# Define your task +task = Task( + description="Generate a list of 5 interesting ideas for an article, then write one captivating paragraph for each idea that showcases the potential of a full article on this topic. Return the list of ideas with their paragraphs and your notes.", + expected_output="5 bullet points, each with a paragraph and accompanying notes.", +) + +# Define the manager agent +manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success. Your role is to coordinate the efforts of the crew members, ensuring that each task is completed on time and to the highest standard.", + allow_delegation=True, +) + +# Instantiate your crew with a custom manager +crew = Crew( + agents=[researcher, writer], + tasks=[task], + manager_agent=manager, + process=Process.hierarchical, +) + +# Start the crew's work +result = crew.kickoff() +``` + +## Benefícios de um Agente Gerente Personalizado + +- **Controle aprimorado**: Adapte a abordagem de gerenciamento para atender às necessidades específicas do seu projeto. +- **Coordenação melhorada**: Assegure uma coordenação e gestão eficiente das tarefas por um agente experiente. +- **Gestão personalizável**: Defina funções e responsabilidades gerenciais que estejam alinhadas aos objetivos do seu projeto. + +## Definindo um Manager LLM + +Se você estiver utilizando o processo hierarchical e não quiser definir um agente gerente personalizado, é possível especificar o modelo de linguagem para o gerente: + +```python Code +from crewai import LLM + +manager_llm = LLM(model="gpt-4o") + +crew = Crew( + agents=[researcher, writer], + tasks=[task], + process=Process.hierarchical, + manager_llm=manager_llm +) +``` + + +É necessário definir `manager_agent` ou `manager_llm` ao utilizar o processo hierarchical. + \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/customizing-agents.mdx b/docs/v1.15.13/pt-BR/learn/customizing-agents.mdx new file mode 100644 index 0000000000..d3df49abcf --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/customizing-agents.mdx @@ -0,0 +1,107 @@ +--- +title: Personalize Agentes +description: Um guia abrangente para adaptar agentes a funções específicas, tarefas e customizações avançadas dentro do framework CrewAI. +icon: user-pen +mode: "wide" +--- + +## Atributos Personalizáveis + +A construção de uma equipe CrewAI eficiente depende da capacidade de adaptar dinamicamente seus agentes de IA para atender aos requisitos únicos de qualquer projeto. Esta seção aborda os atributos fundamentais que você pode personalizar. + +### Principais Atributos para Personalização + +| Atributo | Descrição | +|:------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Role** | Especifica a função do agente dentro da equipe, como 'Analista' ou 'Representante de Atendimento ao Cliente'. | +| **Goal** | Define os objetivos do agente, alinhados à sua função e à missão geral da equipe. | +| **Backstory** | Fornece profundidade à persona do agente, aprimorando motivações e engajamento dentro da equipe. | +| **Tools** *(Opcional)* | Representa as capacidades ou métodos que o agente utiliza para tarefas, desde funções simples até integrações complexas. | +| **Cache** *(Opcional)* | Determina se o agente deve usar cache para o uso de ferramentas. | +| **Max RPM** | Define o número máximo de requisições por minuto (`max_rpm`). Pode ser definido como `None` para requisições ilimitadas a serviços externos. | +| **Verbose** *(Opcional)* | Ativa registros detalhados para depuração e otimização, fornecendo insights sobre os processos de execução. | +| **Allow Delegation** *(Opcional)* | Controla a delegação de tarefas para outros agentes, padrão é `False`. | +| **Max Iter** *(Opcional)* | Limita o número máximo de iterações (`max_iter`) para uma tarefa, prevenindo loops infinitos, com valor padrão de 25. | +| **Max Execution Time** *(Opcional)* | Define o tempo máximo permitido para que o agente complete uma tarefa. | +| **System Template** *(Opcional)* | Define o formato do sistema para o agente. | +| **Prompt Template** *(Opcional)* | Define o formato do prompt para o agente. | +| **Response Template** *(Opcional)* | Define o formato da resposta para o agente. | +| **Use System Prompt** *(Opcional)* | Controla se o agente irá usar um prompt de sistema durante a execução de tarefas. | +| **Respect Context Window** | Ativa uma janela deslizante de contexto por padrão, mantendo o tamanho do contexto. | +| **Max Retry Limit** | Define o número máximo de tentativas (`max_retry_limit`) para um agente em caso de erros. | + +## Opções Avançadas de Personalização + +Além dos atributos básicos, o CrewAI permite customizações mais profundas para aprimorar significativamente o comportamento e as capacidades de um agente. + +### Personalização de Modelo de Linguagem + +Agentes podem ser personalizados com modelos de linguagem específicos (`llm`) e modelos de linguagem com chamada de função (`function_calling_llm`), oferecendo controle avançado sobre o processamento e a tomada de decisão. +É importante notar que definir o `function_calling_llm` permite sobrescrever o modelo padrão de chamada de função da equipe, proporcionando maior grau de personalização. + +## Ajustes de Performance e Depuração + +Ajustar a performance do agente e monitorar suas operações é fundamental para a execução eficiente de tarefas. + +### Modo Verbose e Limite de RPM + +- **Modo Verbose**: Ativa o registro detalhado das ações do agente, útil para depuração e otimização. Especificamente, fornece insights sobre os processos de execução do agente, auxiliando na otimização de performance. +- **Limite de RPM**: Define o número máximo de requisições por minuto (`max_rpm`). Este atributo é opcional e pode ser definido como `None` para não haver limite, permitindo consultas ilimitadas a serviços externos, se necessário. + +### Máximo de Iterações por Execução de Tarefa + +O atributo `max_iter` permite ao usuário definir o número máximo de iterações que um agente pode executar para uma única tarefa, prevenindo loops infinitos ou execuções excessivamente longas. +O valor padrão é 25, fornecendo um equilíbrio entre profundidade e eficiência. Quando o agente chega próximo a esse número, ele tentará entregar a melhor resposta possível. + +## Personalizando Agentes e Ferramentas + +Agentes são personalizados definindo seus atributos e ferramentas durante a inicialização. As ferramentas são críticas para a funcionalidade do agente, permitindo que realizem tarefas especializadas. +O atributo `tools` deve ser um array de ferramentas que o agente pode utilizar, e, por padrão, é inicializado como uma lista vazia. As ferramentas podem ser adicionadas ou modificadas após a criação do agente para se adaptar a novos requisitos. + +```shell +pip install 'crewai[tools]' +``` + +### Exemplo: Atribuindo Ferramentas a um Agente + +```python Code +import os +from crewai import Agent +from crewai_tools import SerperDevTool + +# Defina as chaves de API para inicialização da ferramenta +os.environ["OPENAI_API_KEY"] = "Sua Chave" +os.environ["SERPER_API_KEY"] = "Sua Chave" + +# Inicialize uma ferramenta de busca +search_tool = SerperDevTool() + +# Inicialize o agente com opções avançadas +agent = Agent( + role='Analista de Pesquisa', + goal='Fornecer análises de mercado atualizadas', + backstory='Um analista especialista com olhar atento para tendências de mercado.', + tools=[search_tool], + memory=True, # Ativa memória + verbose=True, + max_rpm=None, # Sem limite de requisições por minuto + max_iter=25, # Valor padrão de máximo de iterações +) +``` + +## Delegação e Autonomia + +Controlar a capacidade de um agente delegar tarefas ou fazer perguntas é fundamental para ajustar sua autonomia e a dinâmica de colaboração dentro do framework CrewAI. Por padrão, +o atributo `allow_delegation` agora é definido como `False`, desabilitando para que agentes busquem assistência ou deleguem tarefas conforme necessário. Esse comportamento padrão pode ser alterado para promover resolução colaborativa de problemas e +eficiência dentro do ecossistema CrewAI. Se necessário, a delegação pode ser ativada para atender requisitos operacionais específicos. + +### Exemplo: Desabilitando Delegação para um Agente + +```python Code +agent = Agent( + role='Redator de Conteúdo', + goal='Escrever conteúdo envolvente sobre tendências de mercado', + backstory='Um redator experiente com expertise em análise de mercado.', + allow_delegation=True # Habilitando delegação +) +``` \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/dalle-image-generation.mdx b/docs/v1.15.13/pt-BR/learn/dalle-image-generation.mdx new file mode 100644 index 0000000000..51b003d723 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/dalle-image-generation.mdx @@ -0,0 +1,74 @@ +--- +title: "Geração de Imagens com DALL-E" +description: "Aprenda a usar o DALL-E para geração de imagens com IA em seus projetos CrewAI" +icon: "image" +mode: "wide" +--- + +O CrewAI oferece integração com o DALL-E da OpenAI, permitindo que seus agentes de IA gerem imagens como parte de suas tarefas. Este guia irá orientá-lo sobre como configurar e utilizar a ferramenta DALL-E em seus projetos CrewAI. + +## Pré-requisitos + +- crewAI instalado (última versão) +- Chave de API OpenAI com acesso ao DALL-E + +## Configurando a Ferramenta DALL-E + + + + ```python + from crewai_tools import DallETool + ``` + + + + ```python + @agent + def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + tools=[SerperDevTool(), DallETool()], # Add DallETool to the list of tools + allow_delegation=False, + verbose=True + ) + ``` + + + +## Utilizando a Ferramenta DALL-E + +Depois de adicionar a ferramenta DALL-E ao seu agente, ele poderá gerar imagens baseadas em prompts de texto. A ferramenta retornará uma URL para a imagem gerada, que pode ser utilizada na resposta do agente ou repassada para outros agentes para processamento adicional. + +### Exemplo de Configuração de Agente + +```yaml +role: > + Pesquisador Sênior de Dados para Perfis do LinkedIn +goal: > + Encontrar perfis detalhados do LinkedIn com base no nome fornecido {name} e domínio {domain} + Gerar uma imagem com o Dall-e baseada no domínio {domain} +backstory: > + Você é um pesquisador experiente com habilidade para encontrar os perfis do LinkedIn mais relevantes. + Conhecido por sua eficiência em navegar no LinkedIn, você se destaca em reunir e apresentar + informações profissionais de forma clara e concisa. +``` + +### Resultado Esperado + +O agente com a ferramenta DALL-E conseguirá gerar a imagem e fornecer uma URL em sua resposta. Você poderá então baixar a imagem. + + + Imagem DALL-E + + +## Boas Práticas + +1. **Seja específico nos prompts de geração de imagem** para obter melhores resultados. +2. **Considere o tempo de geração** - A geração de imagens pode levar algum tempo, então inclua isso no seu planejamento de tarefas. +3. **Siga as políticas de uso** - Sempre cumpra as políticas de uso da OpenAI ao gerar imagens. + +## Solução de Problemas + +1. **Verifique o acesso à API** - Certifique-se de que sua chave de API OpenAI possui acesso ao DALL-E. +2. **Compatibilidade de versões** - Verifique se você está utilizando a versão mais recente do crewAI e crewai-tools. +3. **Configuração da ferramenta** - Confirme que a ferramenta DALL-E foi corretamente adicionada à lista de ferramentas do agente. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/execution-hooks.mdx b/docs/v1.15.13/pt-BR/learn/execution-hooks.mdx new file mode 100644 index 0000000000..0e70edfbd7 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/execution-hooks.mdx @@ -0,0 +1,379 @@ +--- +title: Visão Geral dos Hooks de Execução +description: Entendendo e usando hooks de execução no CrewAI para controle fino sobre operações de agentes +mode: "wide" +--- + +Os Hooks de Execução fornecem controle fino sobre o comportamento em tempo de execução dos seus agentes CrewAI. Diferentemente dos hooks de kickoff que são executados antes e depois da execução da crew, os hooks de execução interceptam operações específicas durante a execução do agente, permitindo que você modifique comportamentos, implemente verificações de segurança e adicione monitoramento abrangente. + +## Tipos de Hooks de Execução + +O CrewAI fornece duas categorias principais de hooks de execução: + +### 1. [Hooks de Chamada LLM](/learn/llm-hooks) + +Controle e monitore interações com o modelo de linguagem: +- **Antes da Chamada LLM**: Modifique prompts, valide entradas, implemente gates de aprovação +- **Depois da Chamada LLM**: Transforme respostas, sanitize saídas, atualize histórico de conversação + +**Casos de Uso:** +- Limitação de iterações +- Rastreamento de custos e monitoramento de uso de tokens +- Sanitização de respostas e filtragem de conteúdo +- Aprovação humana para chamadas LLM +- Adição de diretrizes de segurança ou contexto +- Logging de debug e inspeção de requisição/resposta + +[Ver Documentação de Hooks LLM →](/learn/llm-hooks) + +### 2. [Hooks de Chamada de Ferramenta](/learn/tool-hooks) + +Controle e monitore execução de ferramentas: +- **Antes da Chamada de Ferramenta**: Modifique entradas, valide parâmetros, bloqueie operações perigosas +- **Depois da Chamada de Ferramenta**: Transforme resultados, sanitize saídas, registre detalhes de execução + +**Casos de Uso:** +- Guardrails de segurança para operações destrutivas +- Aprovação humana para ações sensíveis +- Validação e sanitização de entrada +- Cache de resultados e limitação de taxa +- Análise de uso de ferramentas +- Logging de debug e monitoramento + +[Ver Documentação de Hooks de Ferramenta →](/learn/tool-hooks) + +## Métodos de Registro + +### 1. Hooks Baseados em Decoradores (Recomendado) + +A maneira mais limpa e pythônica de registrar hooks: + +```python +from crewai.hooks import before_llm_call, after_llm_call, before_tool_call, after_tool_call + +@before_llm_call +def limit_iterations(context): + """Previne loops infinitos limitando iterações.""" + if context.iterations > 10: + return False # Bloquear execução + return None + +@after_llm_call +def sanitize_response(context): + """Remove dados sensíveis das respostas do LLM.""" + if "API_KEY" in context.response: + return context.response.replace("API_KEY", "[CENSURADO]") + return None + +@before_tool_call +def block_dangerous_tools(context): + """Bloqueia operações destrutivas.""" + if context.tool_name == "delete_database": + return False # Bloquear execução + return None + +@after_tool_call +def log_tool_result(context): + """Registra execução de ferramenta.""" + print(f"Ferramenta {context.tool_name} concluída") + return None +``` + +### 2. Hooks com Escopo de Crew + +Aplica hooks apenas a instâncias específicas de crew: + +```python +from crewai import CrewBase +from crewai.project import crew +from crewai.hooks import before_llm_call_crew, after_tool_call_crew + +@CrewBase +class MyProjCrew: + @before_llm_call_crew + def validate_inputs(self, context): + # Aplica-se apenas a esta crew + print(f"Chamada LLM em {self.__class__.__name__}") + return None + + @after_tool_call_crew + def log_results(self, context): + # Logging específico da crew + print(f"Resultado da ferramenta: {context.tool_result[:50]}...") + return None + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential + ) +``` + +## Fluxo de Execução de Hooks + +### Fluxo de Chamada LLM + +``` +Agente precisa chamar LLM + ↓ +[Hooks Antes da Chamada LLM Executam] + ├→ Hook 1: Validar contagem de iterações + ├→ Hook 2: Adicionar contexto de segurança + └→ Hook 3: Registrar requisição + ↓ +Se algum hook retornar False: + ├→ Bloquear chamada LLM + └→ Lançar ValueError + ↓ +Se todos os hooks retornarem True/None: + ├→ Chamada LLM prossegue + └→ Resposta gerada + ↓ +[Hooks Depois da Chamada LLM Executam] + ├→ Hook 1: Sanitizar resposta + ├→ Hook 2: Registrar resposta + └→ Hook 3: Atualizar métricas + ↓ +Resposta final retornada +``` + +### Fluxo de Chamada de Ferramenta + +``` +Agente precisa executar ferramenta + ↓ +[Hooks Antes da Chamada de Ferramenta Executam] + ├→ Hook 1: Verificar se ferramenta é permitida + ├→ Hook 2: Validar entradas + └→ Hook 3: Solicitar aprovação se necessário + ↓ +Se algum hook retornar False: + ├→ Bloquear execução da ferramenta + └→ Retornar mensagem de erro + ↓ +Se todos os hooks retornarem True/None: + ├→ Execução da ferramenta prossegue + └→ Resultado gerado + ↓ +[Hooks Depois da Chamada de Ferramenta Executam] + ├→ Hook 1: Sanitizar resultado + ├→ Hook 2: Fazer cache do resultado + └→ Hook 3: Registrar métricas + ↓ +Resultado final retornado +``` + +## Objetos de Contexto de Hook + +### LLMCallHookContext + +Fornece acesso ao estado de execução do LLM: + +```python +class LLMCallHookContext: + executor: CrewAgentExecutor # Acesso completo ao executor + messages: list # Lista de mensagens mutável + agent: Agent # Agente atual + task: Task # Tarefa atual + crew: Crew # Instância da crew + llm: BaseLLM # Instância do LLM + iterations: int # Iteração atual + response: str | None # Resposta do LLM (hooks posteriores) +``` + +### ToolCallHookContext + +Fornece acesso ao estado de execução da ferramenta: + +```python +class ToolCallHookContext: + tool_name: str # Ferramenta sendo chamada + tool_input: dict # Parâmetros de entrada mutáveis + tool: CrewStructuredTool # Instância da ferramenta + agent: Agent | None # Agente executando + task: Task | None # Tarefa atual + crew: Crew | None # Instância da crew + tool_result: str | None # Resultado da ferramenta (hooks posteriores) +``` + +## Padrões Comuns + +### Segurança e Validação + +```python +@before_tool_call +def safety_check(context): + """Bloqueia operações destrutivas.""" + dangerous = ['delete_file', 'drop_table', 'system_shutdown'] + if context.tool_name in dangerous: + print(f"🛑 Bloqueado: {context.tool_name}") + return False + return None + +@before_llm_call +def iteration_limit(context): + """Previne loops infinitos.""" + if context.iterations > 15: + print("⛔ Máximo de iterações excedido") + return False + return None +``` + +### Humano no Loop + +```python +@before_tool_call +def require_approval(context): + """Requer aprovação para operações sensíveis.""" + sensitive = ['send_email', 'make_payment', 'post_message'] + + if context.tool_name in sensitive: + response = context.request_human_input( + prompt=f"Aprovar {context.tool_name}?", + default_message="Digite 'sim' para aprovar:" + ) + + if response.lower() != 'sim': + return False + + return None +``` + +### Monitoramento e Análise + +```python +from collections import defaultdict +import time + +metrics = defaultdict(lambda: {'count': 0, 'total_time': 0}) + +@before_tool_call +def start_timer(context): + context.tool_input['_start'] = time.time() + return None + +@after_tool_call +def track_metrics(context): + start = context.tool_input.get('_start', time.time()) + duration = time.time() - start + + metrics[context.tool_name]['count'] += 1 + metrics[context.tool_name]['total_time'] += duration + + return None +``` + +## Gerenciamento de Hooks + +### Limpar Todos os Hooks + +```python +from crewai.hooks import clear_all_global_hooks + +# Limpa todos os hooks de uma vez +result = clear_all_global_hooks() +print(f"Limpou {result['total']} hooks") +``` + +### Limpar Tipos Específicos de Hooks + +```python +from crewai.hooks import ( + clear_before_llm_call_hooks, + clear_after_llm_call_hooks, + clear_before_tool_call_hooks, + clear_after_tool_call_hooks +) + +# Limpar tipos específicos +llm_before_count = clear_before_llm_call_hooks() +tool_after_count = clear_after_tool_call_hooks() +``` + +## Melhores Práticas + +### 1. Mantenha os Hooks Focados +Cada hook deve ter uma responsabilidade única e clara. + +### 2. Trate Erros Graciosamente +```python +@before_llm_call +def safe_hook(context): + try: + if some_condition: + return False + except Exception as e: + print(f"Erro no hook: {e}") + return None # Permitir execução apesar do erro +``` + +### 3. Modifique o Contexto In-Place +```python +# ✅ Correto - modificar in-place +@before_llm_call +def add_context(context): + context.messages.append({"role": "system", "content": "Seja conciso"}) + +# ❌ Errado - substitui referência +@before_llm_call +def wrong_approach(context): + context.messages = [{"role": "system", "content": "Seja conciso"}] +``` + +### 4. Use Type Hints +```python +from crewai.hooks import LLMCallHookContext, ToolCallHookContext + +def my_llm_hook(context: LLMCallHookContext) -> bool | None: + return None + +def my_tool_hook(context: ToolCallHookContext) -> str | None: + return None +``` + +### 5. Limpe em Testes +```python +import pytest +from crewai.hooks import clear_all_global_hooks + +@pytest.fixture(autouse=True) +def clean_hooks(): + """Reseta hooks antes de cada teste.""" + yield + clear_all_global_hooks() +``` + +## Quando Usar Qual Hook + +### Use Hooks LLM Quando: +- Implementar limites de iteração +- Adicionar contexto ou diretrizes de segurança aos prompts +- Rastrear uso de tokens e custos +- Sanitizar ou transformar respostas +- Implementar gates de aprovação para chamadas LLM +- Fazer debug de interações de prompt/resposta + +### Use Hooks de Ferramenta Quando: +- Bloquear operações perigosas ou destrutivas +- Validar entradas de ferramenta antes da execução +- Implementar gates de aprovação para ações sensíveis +- Fazer cache de resultados de ferramenta +- Rastrear uso e performance de ferramentas +- Sanitizar saídas de ferramenta +- Limitar taxa de chamadas de ferramenta + +### Use Ambos Quando: +Construir sistemas abrangentes de observabilidade, segurança ou aprovação que precisam monitorar todas as operações do agente. + +## Documentação Relacionada + +- [Hooks de Chamada LLM →](/learn/llm-hooks) - Documentação detalhada de hooks LLM +- [Hooks de Chamada de Ferramenta →](/learn/tool-hooks) - Documentação detalhada de hooks de ferramenta +- [Hooks Antes e Depois do Kickoff →](/learn/before-and-after-kickoff-hooks) - Hooks do ciclo de vida da crew +- [Humano no Loop →](/learn/human-in-the-loop) - Padrões de entrada humana + +## Conclusão + +Os Hooks de Execução fornecem controle poderoso sobre o comportamento em tempo de execução do agente. Use-os para implementar guardrails de segurança, fluxos de trabalho de aprovação, monitoramento abrangente e lógica de negócio personalizada. Combinados com tratamento adequado de erros, segurança de tipos e considerações de performance, os hooks permitem sistemas de agentes seguros, prontos para produção e observáveis. diff --git a/docs/v1.15.13/pt-BR/learn/force-tool-output-as-result.mdx b/docs/v1.15.13/pt-BR/learn/force-tool-output-as-result.mdx new file mode 100644 index 0000000000..c053c34488 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/force-tool-output-as-result.mdx @@ -0,0 +1,51 @@ +--- +title: Forçar a Saída da Ferramenta como Resultado +description: Aprenda como forçar a saída de uma ferramenta como resultado em uma tarefa de Agent no CrewAI. +icon: wrench-simple +mode: "wide" +--- + +## Introdução + +No CrewAI, você pode forçar a saída de uma ferramenta como o resultado de uma tarefa de um agent. +Esse recurso é útil quando você deseja garantir que a saída da ferramenta seja capturada e retornada como resultado da tarefa, evitando quaisquer modificações pelo agent durante a execução da tarefa. + +## Forçando a Saída da Ferramenta como Resultado + +Para forçar a saída da ferramenta como resultado da tarefa de um agent, você precisa definir o parâmetro `result_as_answer` como `True` ao adicionar uma ferramenta ao agent. +Esse parâmetro garante que a saída da ferramenta seja capturada e retornada como resultado da tarefa, sem qualquer modificação pelo agent. + +Veja um exemplo de como forçar a saída da ferramenta como resultado da tarefa de um agent: + +```python Code +from crewai.agent import Agent +from my_tool import MyCustomTool + +# Create a coding agent with the custom tool +coding_agent = Agent( + role="Data Scientist", + goal="Produce amazing reports on AI", + backstory="You work with data and AI", + tools=[MyCustomTool(result_as_answer=True)], + ) + +# Assuming the tool's execution and result population occurs within the system +task_result = coding_agent.execute_task(task) +``` + +## Fluxo de Trabalho em Ação + + + + O agent executa a tarefa utilizando a ferramenta fornecida. + + + A ferramenta gera a saída, que é capturada como resultado da tarefa. + + + O agent pode refletir e aprender com a ferramenta, mas a saída não é modificada. + + + A saída da ferramenta é retornada como resultado da tarefa sem quaisquer modificações. + + \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/hierarchical-process.mdx b/docs/v1.15.13/pt-BR/learn/hierarchical-process.mdx new file mode 100644 index 0000000000..d7985f5d23 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/hierarchical-process.mdx @@ -0,0 +1,112 @@ +--- +title: Processo Hierárquico +description: Um guia abrangente para compreender e aplicar o processo hierárquico em seus projetos CrewAI, atualizado para refletir as práticas de codificação e funcionalidades mais recentes. +icon: sitemap +mode: "wide" +--- + +## Introdução + +O processo hierárquico no CrewAI introduz uma abordagem estruturada para a gestão de tarefas, simulando hierarquias organizacionais tradicionais para uma delegação e execução eficiente de tarefas. +Esse fluxo de trabalho sistemático melhora os resultados do projeto ao garantir que as tarefas sejam tratadas com máxima eficiência e precisão. + + + O processo hierárquico foi projetado para alavancar modelos avançados como o GPT-4, otimizando o uso de tokens enquanto lida com tarefas complexas de forma mais eficiente. + + +## Visão Geral do Processo Hierárquico + +Por padrão, as tarefas no CrewAI são gerenciadas por meio de um processo sequencial. No entanto, adotar uma abordagem hierárquica permite uma hierarquia clara na gestão de tarefas, +onde um agente 'gerente' coordena o fluxo de trabalho, delega tarefas e valida os resultados para uma execução eficaz e simplificada. Esse agente gerente pode agora ser +criado automaticamente pelo CrewAI ou explicitamente definido pelo usuário. + +### Principais Características + +- **Delegação de Tarefas**: Um agente gerente distribui tarefas entre os membros da crew com base em seus papéis e capacidades. +- **Validação de Resultados**: O gerente avalia os resultados para garantir que atendam aos padrões exigidos. +- **Fluxo de Trabalho Eficiente**: Emula estruturas corporativas, oferecendo uma abordagem organizada para a gestão de tarefas. +- **Manipulação de System Prompt**: Opcionalmente, especifique se o sistema deve usar prompts predefinidos. +- **Controle de Stop Words**: Opcionalmente, especifique se stop words devem ser usadas, oferecendo suporte a diversos modelos, incluindo os modelos o1. +- **Respeito à Context Window**: Priorização de contexto relevante ativando o respeito à context window, que agora é o comportamento padrão. +- **Controle de Delegação**: A delegação agora está desativada por padrão para dar controle explícito ao usuário. +- **Máximo de Requisições por Minuto**: Opção configurável para definir o número máximo de requisições por minuto. +- **Máximo de Iterações**: Limitação do número máximo de iterações até a obtenção de uma resposta final. + +## Implementando o Processo Hierárquico + +Para utilizar o processo hierárquico, é essencial definir explicitamente o atributo de processo como `Process.hierarchical`, já que o comportamento padrão é `Process.sequential`. +Defina uma crew com um gerente designado e estabeleça uma cadeia de comando clara. + + + Atribua ferramentas no nível do agente para facilitar a delegação e execução de tarefas pelos agentes designados sob a orientação do gerente. + Ferramentas também podem ser especificadas no nível da tarefa, para um controle preciso sobre a disponibilidade de ferramentas durante a execução das tarefas. + + + + Configurar o parâmetro `manager_llm` é fundamental para o processo hierárquico. + O sistema exige a configuração de um LLM do gerente para funcionar corretamente, garantindo tomadas de decisão personalizadas. + + +```python Code +from crewai import Crew, Process, Agent + +# Agents are defined with attributes for backstory, cache, and verbose mode +researcher = Agent( + role='Researcher', + goal='Conduct in-depth analysis', + backstory='Experienced data analyst with a knack for uncovering hidden trends.', +) +writer = Agent( + role='Writer', + goal='Create engaging content', + backstory='Creative writer passionate about storytelling in technical domains.', +) + +# Establishing the crew with a hierarchical process and additional configurations +project_crew = Crew( + tasks=[...], # Tasks to be delegated and executed under the manager's supervision + agents=[researcher, writer], + manager_llm="gpt-4o", # Specify which LLM the manager should use + process=Process.hierarchical, + planning=True, +) +``` + +### Usando um Agente Gerente Personalizado + +Alternativamente, você pode criar um agente gerente personalizado com atributos específicos adaptados às necessidades de gestão do seu projeto. Isso oferece maior controle sobre o comportamento e as capacidades do gerente. + +```python +# Define a custom manager agent +manager = Agent( + role="Project Manager", + goal="Efficiently manage the crew and ensure high-quality task completion", + backstory="You're an experienced project manager, skilled in overseeing complex projects and guiding teams to success.", + allow_delegation=True, +) + +# Use the custom manager in your crew +project_crew = Crew( + tasks=[...], + agents=[researcher, writer], + manager_agent=manager, # Use your custom manager agent + process=Process.hierarchical, + planning=True, +) +``` + + + Para mais detalhes sobre a criação e personalização de um agente gerente, confira a [documentação do Custom Manager Agent](/pt-BR/learn/custom-manager-agent). + + + +### Fluxo de Trabalho na Prática + +1. **Atribuição de Tarefas**: O gerente atribui as tarefas estrategicamente, considerando as capacidades de cada agente e as ferramentas disponíveis. +2. **Execução e Revisão**: Os agentes concluem suas tarefas com a opção de execução assíncrona e funções de callback para fluxos de trabalho otimizados. +3. **Progresso Sequencial das Tarefas**: Apesar de ser um processo hierárquico, as tarefas seguem uma ordem lógica para um progresso fluido, facilitado pela supervisão do gerente. + +## Conclusão + +Adotar o processo hierárquico no CrewAI, com as configurações corretas e o entendimento das capacidades do sistema, facilita uma abordagem organizada e eficiente para o gerenciamento de projetos. +Aproveite os recursos avançados e as personalizações para ajustar o fluxo de trabalho conforme suas necessidades, garantindo a execução ideal das tarefas e o sucesso do projeto. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/human-feedback-in-flows.mdx b/docs/v1.15.13/pt-BR/learn/human-feedback-in-flows.mdx new file mode 100644 index 0000000000..ad4d068cd0 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/human-feedback-in-flows.mdx @@ -0,0 +1,697 @@ +--- +title: Feedback Humano em Flows +description: Aprenda como integrar feedback humano diretamente nos seus CrewAI Flows usando o decorador @human_feedback +icon: user-check +mode: "wide" +--- + +## Visão Geral + + +O decorador `@human_feedback` requer **CrewAI versão 1.8.0 ou superior**. Certifique-se de atualizar sua instalação antes de usar este recurso. + + +O decorador `@human_feedback` permite fluxos de trabalho human-in-the-loop (HITL) diretamente nos CrewAI Flows. Ele permite pausar a execução do flow, apresentar a saída para um humano revisar, coletar seu feedback e, opcionalmente, rotear para diferentes listeners com base no resultado do feedback. + +Isso é particularmente valioso para: + +- **Garantia de qualidade**: Revisar conteúdo gerado por IA antes de ser usado downstream +- **Portões de decisão**: Deixar humanos tomarem decisões críticas em fluxos automatizados +- **Fluxos de aprovação**: Implementar padrões de aprovar/rejeitar/revisar +- **Refinamento interativo**: Coletar feedback para melhorar saídas iterativamente + +```mermaid +flowchart LR + A[Método do Flow] --> B[Saída Gerada] + B --> C[Humano Revisa] + C --> D{Feedback} + D -->|emit especificado| E[LLM Mapeia para Outcome] + D -->|sem emit| F[HumanFeedbackResult] + E --> G["@listen('approved')"] + E --> H["@listen('rejected')"] + F --> I[Próximo Listener] +``` + +## Início Rápido + +Aqui está a maneira mais simples de adicionar feedback humano a um flow: + +```python Code +from crewai.flow.flow import Flow, start, listen +from crewai.flow.human_feedback import human_feedback + +class SimpleReviewFlow(Flow): + @start() + @human_feedback(message="Por favor, revise este conteúdo:") + def generate_content(self): + return "Este é um conteúdo gerado por IA que precisa de revisão." + + @listen(generate_content) + def process_feedback(self, result): + print(f"Conteúdo: {result.output}") + print(f"Humano disse: {result.feedback}") + +flow = SimpleReviewFlow() +flow.kickoff() +``` + +Quando este flow é executado, ele irá: +1. Executar `generate_content` e retornar a string +2. Exibir a saída para o usuário com a mensagem de solicitação +3. Aguardar o usuário digitar o feedback (ou pressionar Enter para pular) +4. Passar um objeto `HumanFeedbackResult` para `process_feedback` + +## O Decorador @human_feedback + +### Parâmetros + +| Parâmetro | Tipo | Obrigatório | Descrição | +|-----------|------|-------------|-----------| +| `message` | `str` | Sim | A mensagem mostrada ao humano junto com a saída do método | +| `emit` | `Sequence[str]` | Não | Lista de possíveis outcomes. O feedback é mapeado para um destes, que dispara decoradores `@listen` | +| `llm` | `str \| BaseLLM` | Quando `emit` especificado | LLM usado para interpretar o feedback e mapear para um outcome | +| `default_outcome` | `str` | Não | Outcome a usar se nenhum feedback for fornecido. Deve estar em `emit` | +| `metadata` | `dict` | Não | Dados adicionais para integrações enterprise | +| `provider` | `HumanFeedbackProvider` | Não | Provider customizado para feedback assíncrono/não-bloqueante. Veja [Feedback Humano Assíncrono](#feedback-humano-assíncrono-não-bloqueante) | +| `learn` | `bool` | Não | Habilitar aprendizado HITL: destila lições do feedback e pré-revisa saídas futuras. Padrão `False`. Veja [Aprendendo com Feedback](#aprendendo-com-feedback) | +| `learn_limit` | `int` | Não | Máximo de lições passadas para recuperar na pré-revisão. Padrão `5` | + +### Uso Básico (Sem Roteamento) + +Quando você não especifica `emit`, o decorador simplesmente coleta o feedback e passa um `HumanFeedbackResult` para o próximo listener: + +```python Code +@start() +@human_feedback(message="O que você acha desta análise?") +def analyze_data(self): + return "Resultados da análise: Receita aumentou 15%, custos diminuíram 8%" + +@listen(analyze_data) +def handle_feedback(self, result): + # result é um HumanFeedbackResult + print(f"Análise: {result.output}") + print(f"Feedback: {result.feedback}") +``` + +### Roteamento com emit + +Quando você especifica `emit`, o decorador se torna um roteador. O feedback livre do humano é interpretado por um LLM e mapeado para um dos outcomes especificados: + +```python Code +from crewai.flow.flow import Flow, start, listen, or_ +from crewai.flow.human_feedback import human_feedback + +class ReviewFlow(Flow): + @start() + def generate_content(self): + return "Rascunho do post do blog aqui..." + + @human_feedback( + message="Você aprova este conteúdo para publicação?", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + @listen(or_("generate_content", "needs_revision")) + def review_content(self): + return "Rascunho do post do blog aqui..." + + @listen("approved") + def publish(self, result): + print(f"Publicando! Usuário disse: {result.feedback}") + + @listen("rejected") + def discard(self, result): + print(f"Descartando. Motivo: {result.feedback}") +``` + +Quando o humano diz algo como "precisa de mais detalhes", o LLM mapeia para `"needs_revision"`, que dispara `review_content` novamente via `or_()` — criando um loop de revisão. O loop continua até que o outcome seja `"approved"` ou `"rejected"`. + + +O LLM usa saídas estruturadas (function calling) quando disponível para garantir que a resposta seja um dos seus outcomes especificados. Isso torna o roteamento confiável e previsível. + + + +Um método `@start()` só executa uma vez no início do flow. Se você precisa de um loop de revisão, separe o método start do método de revisão e use `@listen(or_("trigger", "revision_outcome"))` no método de revisão para habilitar o self-loop. + + +## HumanFeedbackResult + +O dataclass `HumanFeedbackResult` contém todas as informações sobre uma interação de feedback humano: + +```python Code +from crewai.flow.human_feedback import HumanFeedbackResult + +@dataclass +class HumanFeedbackResult: + output: Any # A saída original do método mostrada ao humano + feedback: str # O texto bruto do feedback do humano + outcome: str | None # O outcome mapeado (se emit foi especificado) + timestamp: datetime # Quando o feedback foi recebido + method_name: str # Nome do método decorado + metadata: dict # Qualquer metadata passado ao decorador +``` + +### Acessando em Listeners + +Quando um listener é disparado por um método `@human_feedback` com `emit`, ele recebe o `HumanFeedbackResult`: + +```python Code +@listen("approved") +def on_approval(self, result: HumanFeedbackResult): + print(f"Saída original: {result.output}") + print(f"Feedback do usuário: {result.feedback}") + print(f"Outcome: {result.outcome}") # "approved" + print(f"Recebido em: {result.timestamp}") +``` + +## Acessando o Histórico de Feedback + +A classe `Flow` fornece dois atributos para acessar o feedback humano: + +### last_human_feedback + +Retorna o `HumanFeedbackResult` mais recente: + +```python Code +@listen(some_method) +def check_feedback(self): + if self.last_human_feedback: + print(f"Último feedback: {self.last_human_feedback.feedback}") +``` + +### human_feedback_history + +Uma lista de todos os objetos `HumanFeedbackResult` coletados durante o flow: + +```python Code +@listen(final_step) +def summarize(self): + print(f"Total de feedbacks coletados: {len(self.human_feedback_history)}") + for i, fb in enumerate(self.human_feedback_history): + print(f"{i+1}. {fb.method_name}: {fb.outcome or 'sem roteamento'}") +``` + + +Cada `HumanFeedbackResult` é adicionado a `human_feedback_history`, então múltiplos passos de feedback não sobrescrevem uns aos outros. Use esta lista para acessar todo o feedback coletado durante o flow. + + +## Exemplo Completo: Fluxo de Aprovação de Conteúdo + +Aqui está um exemplo completo implementando um fluxo de revisão e aprovação de conteúdo: + + + +```python Code +from crewai.flow.flow import Flow, start, listen, or_ +from crewai.flow.human_feedback import human_feedback, HumanFeedbackResult +from pydantic import BaseModel + + +class ContentState(BaseModel): + draft: str = "" + revision_count: int = 0 + status: str = "pending" + + +class ContentApprovalFlow(Flow[ContentState]): + """Um flow que gera conteúdo e faz loop até o humano aprovar.""" + + @start() + def generate_draft(self): + self.state.draft = "# IA Segura\n\nEste é um rascunho sobre IA Segura..." + return self.state.draft + + @human_feedback( + message="Por favor, revise este rascunho. Aprove, rejeite ou descreva o que precisa mudar:", + emit=["approved", "rejected", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", + ) + @listen(or_("generate_draft", "needs_revision")) + def review_draft(self): + self.state.revision_count += 1 + return f"{self.state.draft} (v{self.state.revision_count})" + + @listen("approved") + def publish_content(self, result: HumanFeedbackResult): + self.state.status = "published" + print(f"Conteúdo aprovado e publicado! Revisor disse: {result.feedback}") + return "published" + + @listen("rejected") + def handle_rejection(self, result: HumanFeedbackResult): + self.state.status = "rejected" + print(f"Conteúdo rejeitado. Motivo: {result.feedback}") + return "rejected" + + +flow = ContentApprovalFlow() +result = flow.kickoff() +print(f"\nFlow finalizado. Status: {flow.state.status}, Revisões: {flow.state.revision_count}") +``` + +```text Output +================================================== +OUTPUT FOR REVIEW: +================================================== +# IA Segura + +Este é um rascunho sobre IA Segura... (v1) +================================================== + +Por favor, revise este rascunho. Aprove, rejeite ou descreva o que precisa mudar: +(Press Enter to skip, or type your feedback) + +Your feedback: Preciso de mais detalhes sobre segurança em IA. + +================================================== +OUTPUT FOR REVIEW: +================================================== +# IA Segura + +Este é um rascunho sobre IA Segura... (v2) +================================================== + +Por favor, revise este rascunho. Aprove, rejeite ou descreva o que precisa mudar: +(Press Enter to skip, or type your feedback) + +Your feedback: Parece bom, aprovado! + +Conteúdo aprovado e publicado! Revisor disse: Parece bom, aprovado! + +Flow finalizado. Status: published, Revisões: 2 +``` + + + +## Combinando com Outros Decoradores + +O decorador `@human_feedback` funciona com `@start()`, `@listen()` e `or_()`. Ambas as ordens de decoradores funcionam — o framework propaga atributos em ambas as direções — mas os padrões recomendados são: + +```python Code +# Revisão única no início do flow (sem self-loop) +@start() +@human_feedback(message="Revise isto:", emit=["approved", "rejected"], llm="gpt-4o-mini") +def my_start_method(self): + return "content" + +# Revisão linear em um listener (sem self-loop) +@listen(other_method) +@human_feedback(message="Revise isto também:", emit=["good", "bad"], llm="gpt-4o-mini") +def my_listener(self, data): + return f"processed: {data}" + +# Self-loop: revisão que pode voltar para revisões +@human_feedback(message="Aprovar ou revisar?", emit=["approved", "revise"], llm="gpt-4o-mini") +@listen(or_("upstream_method", "revise")) +def review_with_loop(self): + return "content for review" +``` + +### Padrão de self-loop + +Para criar um loop de revisão, o método de revisão deve escutar **ambos** um gatilho upstream e seu próprio outcome de revisão usando `or_()`: + +```python Code +@start() +def generate(self): + return "initial draft" + +@human_feedback( + message="Aprovar ou solicitar alterações?", + emit=["revise", "approved"], + llm="gpt-4o-mini", + default_outcome="approved", +) +@listen(or_("generate", "revise")) +def review(self): + return "content" + +@listen("approved") +def publish(self): + return "published" +``` + +Quando o outcome é `"revise"`, o flow roteia de volta para `review` (porque ele escuta `"revise"` via `or_()`). Quando o outcome é `"approved"`, o flow continua para `publish`. Isso funciona porque o engine de flow isenta roteadores da regra "fire once", permitindo que eles re-executem em cada iteração do loop. + +### Roteadores encadeados + +Um listener disparado pelo outcome de um roteador pode ser ele mesmo um roteador: + +```python Code +@start() +@human_feedback(message="Primeira revisão:", emit=["approved", "rejected"], llm="gpt-4o-mini") +def draft(self): + return "draft content" + +@listen("approved") +@human_feedback(message="Revisão final:", emit=["publish", "revise"], llm="gpt-4o-mini") +def final_review(self, prev): + return "final content" + +@listen("publish") +def on_publish(self, prev): + return "published" +``` + +### Limitações + +- **Métodos `@start()` executam uma vez**: Um método `@start()` não pode fazer self-loop. Se você precisa de um ciclo de revisão, use um método `@start()` separado como ponto de entrada e coloque o `@human_feedback` em um método `@listen()`. +- **Sem `@start()` + `@listen()` no mesmo método**: Esta é uma restrição do framework de Flow. Um método é ou um ponto de início ou um listener, não ambos. + +## Melhores Práticas + +### 1. Escreva Mensagens de Solicitação Claras + +O parâmetro `message` é o que o humano vê. Torne-o acionável: + +```python Code +# ✅ Bom - claro e acionável +@human_feedback(message="Este resumo captura com precisão os pontos-chave? Responda 'sim' ou explique o que está faltando:") + +# ❌ Ruim - vago +@human_feedback(message="Revise isto:") +``` + +### 2. Escolha Outcomes Significativos + +Ao usar `emit`, escolha outcomes que mapeiem naturalmente para respostas humanas: + +```python Code +# ✅ Bom - outcomes em linguagem natural +emit=["approved", "rejected", "needs_more_detail"] + +# ❌ Ruim - técnico ou pouco claro +emit=["state_1", "state_2", "state_3"] +``` + +### 3. Sempre Forneça um Outcome Padrão + +Use `default_outcome` para lidar com casos onde usuários pressionam Enter sem digitar: + +```python Code +@human_feedback( + message="Aprovar? (pressione Enter para solicitar revisão)", + emit=["approved", "needs_revision"], + llm="gpt-4o-mini", + default_outcome="needs_revision", # Padrão seguro +) +``` + +### 4. Use o Histórico de Feedback para Trilhas de Auditoria + +Acesse `human_feedback_history` para criar logs de auditoria: + +```python Code +@listen(final_step) +def create_audit_log(self): + log = [] + for fb in self.human_feedback_history: + log.append({ + "step": fb.method_name, + "outcome": fb.outcome, + "feedback": fb.feedback, + "timestamp": fb.timestamp.isoformat(), + }) + return log +``` + +### 5. Trate Feedback Roteado e Não Roteado + +Ao projetar flows, considere se você precisa de roteamento: + +| Cenário | Use | +|---------|-----| +| Revisão simples, só precisa do texto do feedback | Sem `emit` | +| Precisa ramificar para caminhos diferentes baseado na resposta | Use `emit` | +| Portões de aprovação com aprovar/rejeitar/revisar | Use `emit` | +| Coletando comentários apenas para logging | Sem `emit` | + +## Feedback Humano Assíncrono (Não-Bloqueante - Human in the loop) + +Por padrão, `@human_feedback` bloqueia a execução aguardando entrada no console. Para aplicações de produção, você pode precisar de feedback **assíncrono/não-bloqueante** que se integre com sistemas externos como Slack, email, webhooks ou APIs. + +### A Abstração de Provider + +Use o parâmetro `provider` para especificar uma estratégia customizada de coleta de feedback: + +```python Code +from crewai.flow import Flow, start, human_feedback, HumanFeedbackProvider, HumanFeedbackPending, PendingFeedbackContext + +class WebhookProvider(HumanFeedbackProvider): + """Provider que pausa o flow e aguarda callback de webhook.""" + + def __init__(self, webhook_url: str): + self.webhook_url = webhook_url + + def request_feedback(self, context: PendingFeedbackContext, flow: Flow) -> str: + # Notifica sistema externo (ex: envia mensagem Slack, cria ticket) + self.send_notification(context) + + # Pausa execução - framework cuida da persistência automaticamente + raise HumanFeedbackPending( + context=context, + callback_info={"webhook_url": f"{self.webhook_url}/{context.flow_id}"} + ) + +class ReviewFlow(Flow): + @start() + @human_feedback( + message="Revise este conteúdo:", + emit=["approved", "rejected"], + llm="gpt-4o-mini", + provider=WebhookProvider("https://myapp.com/api"), + ) + def generate_content(self): + return "Conteúdo gerado por IA..." + + @listen("approved") + def publish(self, result): + return "Publicado!" +``` + + +O framework de flow **persiste automaticamente o estado** quando `HumanFeedbackPending` é lançado. Seu provider só precisa notificar o sistema externo e lançar a exceção—não são necessárias chamadas manuais de persistência. + + +### Tratando Flows Pausados + +Ao usar um provider assíncrono, `kickoff()` retorna um objeto `HumanFeedbackPending` em vez de lançar uma exceção: + +```python Code +flow = ReviewFlow() +result = flow.kickoff() + +if isinstance(result, HumanFeedbackPending): + # Flow está pausado, estado é automaticamente persistido + print(f"Aguardando feedback em: {result.callback_info['webhook_url']}") + print(f"Flow ID: {result.context.flow_id}") +else: + # Conclusão normal + print(f"Flow concluído: {result}") +``` + +### Retomando um Flow Pausado + +Quando o feedback chega (ex: via webhook), retome o flow: + +```python Code +# Handler síncrono: +def handle_feedback_webhook(flow_id: str, feedback: str): + flow = ReviewFlow.from_pending(flow_id) + result = flow.resume(feedback) + return result + +# Handler assíncrono (FastAPI, aiohttp, etc.): +async def handle_feedback_webhook(flow_id: str, feedback: str): + flow = ReviewFlow.from_pending(flow_id) + result = await flow.resume_async(feedback) + return result +``` + +### Tipos Principais + +| Tipo | Descrição | +|------|-----------| +| `HumanFeedbackProvider` | Protocolo para providers de feedback customizados | +| `PendingFeedbackContext` | Contém todas as informações necessárias para retomar um flow pausado | +| `HumanFeedbackPending` | Retornado por `kickoff()` quando o flow está pausado para feedback | +| `ConsoleProvider` | Provider padrão de entrada bloqueante no console | + +### PendingFeedbackContext + +O contexto contém tudo necessário para retomar: + +```python Code +@dataclass +class PendingFeedbackContext: + flow_id: str # Identificador único desta execução de flow + flow_class: str # Nome qualificado completo da classe + method_name: str # Método que disparou o feedback + method_output: Any # Saída mostrada ao humano + message: str # A mensagem de solicitação + emit: list[str] | None # Outcomes possíveis para roteamento + default_outcome: str | None + metadata: dict # Metadata customizado + llm: str | None # LLM para mapeamento de outcome + requested_at: datetime +``` + +### Exemplo Completo de Flow Assíncrono + +```python Code +from crewai.flow import ( + Flow, start, listen, human_feedback, + HumanFeedbackProvider, HumanFeedbackPending, PendingFeedbackContext +) + +class SlackNotificationProvider(HumanFeedbackProvider): + """Provider que envia notificações Slack e pausa para feedback assíncrono.""" + + def __init__(self, channel: str): + self.channel = channel + + def request_feedback(self, context: PendingFeedbackContext, flow: Flow) -> str: + # Envia notificação Slack (implemente você mesmo) + slack_thread_id = self.post_to_slack( + channel=self.channel, + message=f"Revisão necessária:\n\n{context.method_output}\n\n{context.message}", + ) + + # Pausa execução - framework cuida da persistência automaticamente + raise HumanFeedbackPending( + context=context, + callback_info={ + "slack_channel": self.channel, + "thread_id": slack_thread_id, + } + ) + +class ContentPipeline(Flow): + @start() + @human_feedback( + message="Aprova este conteúdo para publicação?", + emit=["approved", "rejected"], + llm="gpt-4o-mini", + default_outcome="rejected", + provider=SlackNotificationProvider("#content-reviews"), + ) + def generate_content(self): + return "Conteúdo de blog post gerado por IA..." + + @listen("approved") + def publish(self, result): + print(f"Publicando! Revisor disse: {result.feedback}") + return {"status": "published"} + + @listen("rejected") + def archive(self, result): + print(f"Arquivado. Motivo: {result.feedback}") + return {"status": "archived"} + + +# Iniciando o flow (vai pausar e aguardar resposta do Slack) +def start_content_pipeline(): + flow = ContentPipeline() + result = flow.kickoff() + + if isinstance(result, HumanFeedbackPending): + return {"status": "pending", "flow_id": result.context.flow_id} + + return result + + +# Retomando quando webhook do Slack dispara (handler síncrono) +def on_slack_feedback(flow_id: str, slack_message: str): + flow = ContentPipeline.from_pending(flow_id) + result = flow.resume(slack_message) + return result + + +# Se seu handler é assíncrono (FastAPI, aiohttp, Slack Bolt async, etc.) +async def on_slack_feedback_async(flow_id: str, slack_message: str): + flow = ContentPipeline.from_pending(flow_id) + result = await flow.resume_async(slack_message) + return result +``` + + +Se você está usando um framework web assíncrono (FastAPI, aiohttp, Slack Bolt modo async), use `await flow.resume_async()` em vez de `flow.resume()`. Chamar `resume()` de dentro de um event loop em execução vai lançar um `RuntimeError`. + + +### Melhores Práticas para Feedback Assíncrono + +1. **Verifique o tipo de retorno**: `kickoff()` retorna `HumanFeedbackPending` quando pausado—não precisa de try/except +2. **Use o método resume correto**: Use `resume()` em código síncrono, `await resume_async()` em código assíncrono +3. **Armazene informações de callback**: Use `callback_info` para armazenar URLs de webhook, IDs de tickets, etc. +4. **Implemente idempotência**: Seu handler de resume deve ser idempotente por segurança +5. **Persistência automática**: O estado é automaticamente salvo quando `HumanFeedbackPending` é lançado e usa `SQLiteFlowPersistence` por padrão +6. **Persistência customizada**: Passe uma instância de persistência customizada para `from_pending()` se necessário + +## Aprendendo com Feedback + +O parâmetro `learn=True` habilita um ciclo de feedback entre revisores humanos e o sistema de memória. Quando habilitado, o sistema melhora progressivamente suas saídas aprendendo com correções humanas anteriores. + +### Como Funciona + +1. **Após o feedback**: O LLM extrai lições generalizáveis da saída + feedback e as armazena na memória com `source="hitl"`. Se o feedback for apenas aprovação (ex: "parece bom"), nada é armazenado. +2. **Antes da próxima revisão**: Lições HITL passadas são recuperadas da memória e aplicadas pelo LLM para melhorar a saída antes que o humano a veja. + +Com o tempo, o humano vê saídas pré-revisadas progressivamente melhores porque cada correção informa revisões futuras. + +### Exemplo + +```python Code +class ArticleReviewFlow(Flow): + @start() + def generate_article(self): + return self.crew.kickoff(inputs={"topic": "AI Safety"}).raw + + @human_feedback( + message="Revise este rascunho do artigo:", + emit=["approved", "needs_revision"], + llm="gpt-4o-mini", + learn=True, # enable HITL learning + ) + @listen(or_("generate_article", "needs_revision")) + def review_article(self): + return self.last_human_feedback.output if self.last_human_feedback else "article draft" + + @listen("approved") + def publish(self): + print(f"Publishing: {self.last_human_feedback.output}") +``` + +**Primeira execução**: O humano vê a saída bruta e diz "Sempre inclua citações para afirmações factuais." A lição é destilada e armazenada na memória. + +**Segunda execução**: O sistema recupera a lição sobre citações, pré-revisa a saída para adicionar citações e então mostra a versão melhorada. O trabalho do humano muda de "corrigir tudo" para "identificar o que o sistema deixou passar." + +### Configuração + +| Parâmetro | Padrão | Descrição | +|-----------|--------|-----------| +| `learn` | `False` | Habilitar aprendizado HITL | +| `learn_limit` | `5` | Máximo de lições passadas para recuperar na pré-revisão | + +### Decisões de Design Principais + +- **Mesmo LLM para tudo**: O parâmetro `llm` no decorador é compartilhado pelo mapeamento de outcome, destilação de lições e pré-revisão. Não é necessário configurar múltiplos modelos. +- **Saída estruturada**: Tanto a destilação quanto a pré-revisão usam function calling com modelos Pydantic quando o LLM suporta, com fallback para parsing de texto caso contrário. +- **Armazenamento não-bloqueante**: Lições são armazenadas via `remember_many()` que executa em uma thread em segundo plano -- o flow continua imediatamente. +- **Degradação graciosa**: Se o LLM falhar durante a destilação, nada é armazenado. Se falhar durante a pré-revisão, a saída bruta é mostrada. Nenhuma falha bloqueia o flow. +- **Sem escopo/categorias necessários**: Ao armazenar lições, apenas `source` é passado. O pipeline de codificação infere escopo, categorias e importância automaticamente. + + +`learn=True` requer que o Flow tenha memória disponível. Flows obtêm memória automaticamente por padrão, mas se você a desabilitou com `_skip_auto_memory`, o aprendizado HITL será silenciosamente ignorado. + + + +## Documentação Relacionada + +- [Visão Geral de Flows](/pt-BR/concepts/flows) - Aprenda sobre CrewAI Flows +- [Gerenciamento de Estado em Flows](/pt-BR/guides/flows/mastering-flow-state) - Gerenciando estado em flows +- [Persistência de Flows](/pt-BR/concepts/flows#persistence) - Persistindo estado de flows +- [Roteamento com @router](/pt-BR/concepts/flows#router) - Mais sobre roteamento condicional +- [Input Humano na Execução](/pt-BR/learn/human-input-on-execution) - Input humano no nível de task +- [Memória](/pt-BR/concepts/memory) - O sistema unificado de memória usado pelo aprendizado HITL diff --git a/docs/v1.15.13/pt-BR/learn/human-in-the-loop.mdx b/docs/v1.15.13/pt-BR/learn/human-in-the-loop.mdx new file mode 100644 index 0000000000..ab59c87f48 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/human-in-the-loop.mdx @@ -0,0 +1,120 @@ +--- +title: "Workflows Human-in-the-Loop (HITL)" +description: "Aprenda como implementar workflows Human-in-the-Loop na CrewAI para aprimorar a tomada de decisões" +icon: "user-check" +mode: "wide" +--- + +Human-in-the-Loop (HITL) é uma abordagem poderosa que combina a inteligência artificial com a experiência humana para aprimorar a tomada de decisões e melhorar os resultados das tarefas. CrewAI oferece várias maneiras de implementar HITL dependendo das suas necessidades. + +## Escolhendo Sua Abordagem HITL + +CrewAI oferece duas abordagens principais para implementar workflows human-in-the-loop: + +| Abordagem | Melhor Para | Integração | Versão | +|----------|----------|-------------|---------| +| **Baseada em Flow** (decorador `@human_feedback`) | Desenvolvimento local, revisão via console, workflows síncronos | [Feedback Humano em Flows](/pt-BR/learn/human-feedback-in-flows) | **1.8.0+** | +| **Baseada em Webhook** (Enterprise) | Deployments em produção, workflows assíncronos, integrações externas (Slack, Teams, etc.) | Este guia | - | + + +Se você está construindo flows e deseja adicionar etapas de revisão humana com roteamento baseado em feedback, confira o guia [Feedback Humano em Flows](/pt-BR/learn/human-feedback-in-flows) para o decorador `@human_feedback`. + + +## Configurando Workflows HITL Baseados em Webhook + + + + Configure sua tarefa com a entrada humana habilitada: + + Entrada Humana Crew + + + + + Ao iniciar seu crew, inclua uma URL de webhook para entrada humana: + + URL do Webhook Crew + + + + + Assim que o crew concluir a tarefa que requer entrada humana, você receberá uma notificação de webhook contendo: + - Execution ID + - Task ID + - Task output + + + + O sistema irá pausar no estado `Pending Human Input`. Revise cuidadosamente o resultado da tarefa. + + + + Chame o endpoint de retomada do seu crew com as seguintes informações: + + Endpoint de Retomada Crew + + + + **Crítico: URLs de Webhook Devem Ser Fornecidas Novamente**: + Você **deve** fornecer as mesmas URLs de webhook (`taskWebhookUrl`, `stepWebhookUrl`, `crewWebhookUrl`) na chamada de resume que você usou na chamada de kickoff. As configurações de webhook **NÃO** são automaticamente transferidas do kickoff - elas devem ser explicitamente incluídas na solicitação de resume para continuar recebendo notificações de conclusão de tarefa, etapas do agente e conclusão do crew. + + + Exemplo de chamada resume com webhooks: + ```bash + curl -X POST {BASE_URL}/resume \ + -H "Authorization: Bearer YOUR_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "execution_id": "abcd1234-5678-90ef-ghij-klmnopqrstuv", + "task_id": "research_task", + "human_feedback": "Ótimo trabalho! Por favor, adicione mais detalhes.", + "is_approve": true, + "taskWebhookUrl": "https://your-server.com/webhooks/task", + "stepWebhookUrl": "https://your-server.com/webhooks/step", + "crewWebhookUrl": "https://your-server.com/webhooks/crew" + }' + ``` + + + **Impacto do Feedback na Execução da Tarefa**: + É fundamental ter cuidado ao fornecer feedback, pois todo o conteúdo do feedback será incorporado como contexto adicional para execuções futuras da tarefa. + + Isso significa: + - Todas as informações do seu feedback passam a fazer parte do contexto da tarefa. + - Detalhes irrelevantes podem influenciar negativamente. + - Feedback conciso e relevante ajuda a manter o foco e a eficiência da tarefa. + - Sempre revise seu feedback cuidadosamente antes de enviar para garantir que contenha apenas informações pertinentes que irão guiar positivamente a execução da tarefa. + + + Se você fornecer um feedback negativo: + - O crew irá tentar novamente a tarefa com o contexto adicionado do seu feedback. + - Você receberá outra notificação de webhook para nova revisão. + - Repita os passos 4-6 até ficar satisfeito. + + + + Quando você enviar um feedback positivo, a execução prosseguirá para as próximas etapas. + + + +## Melhores Práticas + +- **Seja Específico**: Forneça feedback claro e acionável que trate diretamente da tarefa em questão +- **Mantenha-se Relevante**: Inclua apenas informações que ajudem a melhorar a execução da tarefa +- **Seja Ágil**: Responda rapidamente às solicitações HITL para evitar atrasos no fluxo +- **Reveja Cuidadosamente**: Verifique seu feedback antes de enviar para garantir a precisão + +## Casos de Uso Comuns + +Workflows HITL são particularmente valiosos para: +- Garantia de qualidade e validação +- Cenários de tomada de decisão complexa +- Operações sensíveis ou de alto risco +- Tarefas criativas que requerem julgamento humano +- Revisões de conformidade e regulamentação + +## Recursos Enterprise + + + 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 →](https://docs-platform.crewai.com/platform/pt-BR/features/flow-hitl-management) + diff --git a/docs/v1.15.13/pt-BR/learn/human-input-on-execution.mdx b/docs/v1.15.13/pt-BR/learn/human-input-on-execution.mdx new file mode 100644 index 0000000000..44305127d2 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/human-input-on-execution.mdx @@ -0,0 +1,99 @@ +--- +title: Input Humano na Execução +description: Integrando o CrewAI com input humano durante a execução em processos complexos de tomada de decisão e aproveitando ao máximo todos os atributos e ferramentas do agente. +icon: user-plus +mode: "wide" +--- + +## Input humano na execução dos agentes + +O input humano é fundamental em vários cenários de execução de agentes, permitindo que os agentes solicitem informações adicionais ou esclarecimentos quando necessário. +Esse recurso é especialmente útil em processos complexos de tomada de decisão ou quando os agentes precisam de mais detalhes para concluir uma tarefa de forma eficaz. + +## Usando input humano com CrewAI + +Para integrar input humano durante a execução do agente, defina o parâmetro `human_input` na definição da tarefa. Quando ativado, o agente solicitará informações ao usuário antes de fornecer sua resposta final. +Esse input pode oferecer contexto extra, esclarecer ambiguidades ou validar a saída produzida pelo agente. + +### Exemplo: + +```shell +pip install crewai +``` + +```python Code +import os +from crewai import Agent, Task, Crew +from crewai_tools import SerperDevTool + +os.environ["SERPER_API_KEY"] = "Your Key" # serper.dev API key +os.environ["OPENAI_API_KEY"] = "Your Key" + +# Loading Tools +search_tool = SerperDevTool() + +# Define your agents with roles, goals, tools, and additional attributes +researcher = Agent( + role='Senior Research Analyst', + goal='Uncover cutting-edge developments in AI and data science', + backstory=( + "You are a Senior Research Analyst at a leading tech think tank. " + "Your expertise lies in identifying emerging trends and technologies in AI and data science. " + "You have a knack for dissecting complex data and presenting actionable insights." + ), + verbose=True, + allow_delegation=False, + tools=[search_tool] +) +writer = Agent( + role='Tech Content Strategist', + goal='Craft compelling content on tech advancements', + backstory=( + "You are a renowned Tech Content Strategist, known for your insightful and engaging articles on technology and innovation. " + "With a deep understanding of the tech industry, you transform complex concepts into compelling narratives." + ), + verbose=True, + allow_delegation=True, + tools=[search_tool], + cache=False, # Disable cache for this agent +) + +# Create tasks for your agents +task1 = Task( + description=( + "Conduct a comprehensive analysis of the latest advancements in AI in 2025. " + "Identify key trends, breakthrough technologies, and potential industry impacts. " + "Compile your findings in a detailed report. " + "Make sure to check with a human if the draft is good before finalizing your answer." + ), + expected_output='A comprehensive full report on the latest AI advancements in 2025, leave nothing out', + agent=researcher, + human_input=True +) + +task2 = Task( + description=( + "Using the insights from the researcher\'s report, develop an engaging blog post that highlights the most significant AI advancements. " + "Your post should be informative yet accessible, catering to a tech-savvy audience. " + "Aim for a narrative that captures the essence of these breakthroughs and their implications for the future." + ), + expected_output='A compelling 3 paragraphs blog post formatted as markdown about the latest AI advancements in 2025', + agent=writer, + human_input=True +) + +# Instantiate your crew with a sequential process +crew = Crew( + agents=[researcher, writer], + tasks=[task1, task2], + verbose=True, + memory=True, + planning=True # Enable planning feature for the crew +) + +# Get your crew to work! +result = crew.kickoff() + +print("######################") +print(result) +``` diff --git a/docs/v1.15.13/pt-BR/learn/kickoff-async.mdx b/docs/v1.15.13/pt-BR/learn/kickoff-async.mdx new file mode 100644 index 0000000000..c1bf0e93c0 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/kickoff-async.mdx @@ -0,0 +1,306 @@ +--- +title: Inicie uma Crew de Forma Assíncrona +description: Inicie uma Crew de Forma Assíncrona +icon: rocket-launch +mode: "wide" +--- + +## Introdução + +A CrewAI oferece a capacidade de iniciar uma crew de forma assíncrona, permitindo que você comece a execução da crew de maneira não bloqueante. +Esse recurso é especialmente útil quando você deseja executar múltiplas crews simultaneamente ou quando precisa realizar outras tarefas enquanto a crew está em execução. + +O CrewAI oferece duas abordagens para execução assíncrona: + +| Método | Tipo | Descrição | +|--------|------|-------------| +| `akickoff()` | Async nativo | Async/await verdadeiro em toda a cadeia de execução | +| `kickoff_async()` | Baseado em thread | Envolve execução síncrona em `asyncio.to_thread` | + + +Para cargas de trabalho de alta concorrência, `akickoff()` é recomendado pois usa async nativo para execução de tasks, operações de memória e recuperação de conhecimento. + + +## Execução Async Nativa com `akickoff()` + +O método `akickoff()` fornece execução async nativa verdadeira, usando async/await em toda a cadeia de execução, incluindo execução de tasks, operações de memória e consultas de conhecimento. + +### Assinatura do Método + +```python Code +async def akickoff(self, inputs: dict) -> CrewOutput: +``` + +### Parâmetros + +- `inputs` (dict): Um dicionário contendo os dados de entrada necessários para as tarefas. + +### Retorno + +- `CrewOutput`: Um objeto que representa o resultado da execução da crew. + +### Exemplo: Execução Async Nativa de Crew + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +# Criar um agente +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Criar uma tarefa +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +# Criar uma crew +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +# Execução async nativa +async def main(): + result = await analysis_crew.akickoff(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + +asyncio.run(main()) +``` + +### Exemplo: Múltiplas Crews Async Nativas + +Execute múltiplas crews concorrentemente usando `asyncio.gather()` com async nativo: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +task_1 = Task( + description="Analyze the first dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +task_2 = Task( + description="Analyze the second dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +crew_1 = Crew(agents=[coding_agent], tasks=[task_1]) +crew_2 = Crew(agents=[coding_agent], tasks=[task_2]) + +async def main(): + results = await asyncio.gather( + crew_1.akickoff(inputs={"ages": [25, 30, 35, 40, 45]}), + crew_2.akickoff(inputs={"ages": [20, 22, 24, 28, 30]}) + ) + + for i, result in enumerate(results, 1): + print(f"Crew {i} Result:", result) + +asyncio.run(main()) +``` + +### Exemplo: Async Nativo para Múltiplas Entradas + +Use `akickoff_for_each()` para executar sua crew contra múltiplas entradas concorrentemente com async nativo: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the dataset and calculate the average age. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +async def main(): + datasets = [ + {"ages": [25, 30, 35, 40, 45]}, + {"ages": [20, 22, 24, 28, 30]}, + {"ages": [30, 35, 40, 45, 50]} + ] + + results = await analysis_crew.akickoff_for_each(datasets) + + for i, result in enumerate(results, 1): + print(f"Dataset {i} Result:", result) + +asyncio.run(main()) +``` + +## Async Baseado em Thread com `kickoff_async()` + +O método `kickoff_async()` fornece execução async envolvendo o `kickoff()` síncrono em uma thread. Isso é útil para integração async mais simples ou compatibilidade retroativa. + +### Assinatura do Método + +```python Code +async def kickoff_async(self, inputs: dict) -> CrewOutput: +``` + +### Parâmetros + +- `inputs` (dict): Um dicionário contendo os dados de entrada necessários para as tarefas. + +### Retorno + +- `CrewOutput`: Um objeto que representa o resultado da execução da crew. + +### Exemplo: Execução Async Baseada em Thread + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] +) + +async def async_crew_execution(): + result = await analysis_crew.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + +asyncio.run(async_crew_execution()) +``` + +### Exemplo: Múltiplas Crews Async Baseadas em Thread + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +task_1 = Task( + description="Analyze the first dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +task_2 = Task( + description="Analyze the second dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age of the participants." +) + +crew_1 = Crew(agents=[coding_agent], tasks=[task_1]) +crew_2 = Crew(agents=[coding_agent], tasks=[task_2]) + +async def async_multiple_crews(): + result_1 = crew_1.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + result_2 = crew_2.kickoff_async(inputs={"ages": [20, 22, 24, 28, 30]}) + + results = await asyncio.gather(result_1, result_2) + + for i, result in enumerate(results, 1): + print(f"Crew {i} Result:", result) + +asyncio.run(async_multiple_crews()) +``` + +## Streaming Assíncrono + +Ambos os métodos async suportam streaming quando `stream=True` está definido na crew: + +```python Code +import asyncio +from crewai import Crew, Agent, Task + +agent = Agent( + role="Researcher", + goal="Research and summarize topics", + backstory="You are an expert researcher." +) + +task = Task( + description="Research the topic: {topic}", + agent=agent, + expected_output="A comprehensive summary of the topic." +) + +crew = Crew( + agents=[agent], + tasks=[task], + stream=True # Habilitar streaming +) + +async def main(): + streaming_output = await crew.akickoff(inputs={"topic": "AI trends in 2024"}) + + # Iteração async sobre chunks de streaming + async for chunk in streaming_output: + print(f"Chunk: {chunk.content}") + + # Acessar resultado final após streaming completar + result = streaming_output.result + print(f"Final result: {result.raw}") + +asyncio.run(main()) +``` + +## Possíveis Casos de Uso + +- **Geração Paralela de Conteúdo**: Inicie múltiplas crews independentes de forma assíncrona, cada uma responsável por gerar conteúdo sobre temas diferentes. Por exemplo, uma crew pode pesquisar e redigir um artigo sobre tendências em IA, enquanto outra gera posts para redes sociais sobre o lançamento de um novo produto. + +- **Tarefas Conjuntas de Pesquisa de Mercado**: Lance múltiplas crews de forma assíncrona para realizar pesquisas de mercado em paralelo. Uma crew pode analisar tendências do setor, outra examinar estratégias de concorrentes e ainda outra avaliar o sentimento do consumidor. + +- **Módulos Independentes de Planejamento de Viagem**: Execute crews separadas para planejar diferentes aspectos de uma viagem de forma independente. Uma crew pode cuidar das opções de voo, outra das acomodações e uma terceira do planejamento das atividades. + +## Escolhendo entre `akickoff()` e `kickoff_async()` + +| Recurso | `akickoff()` | `kickoff_async()` | +|---------|--------------|-------------------| +| Modelo de execução | Async/await nativo | Wrapper baseado em thread | +| Execução de tasks | Async com `aexecute_sync()` | Síncrono em thread pool | +| Operações de memória | Async | Síncrono em thread pool | +| Recuperação de conhecimento | Async | Síncrono em thread pool | +| Melhor para | Alta concorrência, cargas I/O-bound | Integração async simples | +| Suporte a streaming | Sim | Sim | diff --git a/docs/v1.15.13/pt-BR/learn/kickoff-for-each.mdx b/docs/v1.15.13/pt-BR/learn/kickoff-for-each.mdx new file mode 100644 index 0000000000..698ae0f8c9 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/kickoff-for-each.mdx @@ -0,0 +1,54 @@ +--- +title: Kickoff Crew para Cada +description: Kickoff Crew para Cada Item em uma Lista +icon: at +mode: "wide" +--- + +## Introdução + +A CrewAI oferece a capacidade de iniciar um crew para cada item em uma lista, permitindo que você execute o crew para cada item da lista. +Esse recurso é particularmente útil quando é necessário realizar o mesmo conjunto de tarefas para vários itens. + +## Iniciando um Crew para Cada Item + +Para iniciar um crew para cada item em uma lista, utilize o método `kickoff_for_each()`. +Esse método executa o crew para cada item da lista, permitindo o processamento eficiente de múltiplos itens. + +Veja um exemplo de como iniciar um crew para cada item em uma lista: + +```python Code +from crewai import Crew, Agent, Task + +# Create an agent with code execution enabled +coding_agent = Agent( + role="Python Data Analyst", + goal="Analyze data and provide insights using Python", + backstory="You are an experienced data analyst with strong Python skills.", + allow_code_execution=True +) + +# Create a task that requires code execution +data_analysis_task = Task( + description="Analyze the given dataset and calculate the average age of participants. Ages: {ages}", + agent=coding_agent, + expected_output="The average age calculated from the dataset" +) + +# Create a crew and add the task +analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task], + verbose=True, + memory=False +) + +datasets = [ + { "ages": [25, 30, 35, 40, 45] }, + { "ages": [20, 25, 30, 35, 40] }, + { "ages": [30, 35, 40, 45, 50] } +] + +# Execute the crew +result = analysis_crew.kickoff_for_each(inputs=datasets) +``` \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/llm-connections.mdx b/docs/v1.15.13/pt-BR/learn/llm-connections.mdx new file mode 100644 index 0000000000..6c09e7c976 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/llm-connections.mdx @@ -0,0 +1,213 @@ +--- +title: Conecte-se a qualquer LLM +description: Guia abrangente sobre como integrar o CrewAI a diversos Large Language Models (LLMs) usando o LiteLLM, incluindo provedores compatíveis e opções de configuração. +icon: brain-circuit +mode: "wide" +--- + +## Conecte o CrewAI a LLMs + +O CrewAI conecta-se a LLMs por meio de integrações nativas via SDK para os provedores mais populares (OpenAI, Anthropic, Google Gemini, Azure e AWS Bedrock), e usa o LiteLLM como alternativa flexível para todos os demais provedores. + + + Por padrão, o CrewAI usa o modelo `gpt-4o-mini`. Isso é determinado pela variável de ambiente `OPENAI_MODEL_NAME`, que tem como padrão "gpt-4o-mini" se não for definida. + Você pode facilmente configurar seus agentes para usar um modelo ou provedor diferente, conforme descrito neste guia. + + +## Provedores Compatíveis + +O LiteLLM oferece suporte a uma ampla gama de provedores, incluindo, mas não se limitando a: + +- OpenAI +- Anthropic +- Google (Vertex AI, Gemini) +- Azure OpenAI +- AWS (Bedrock, SageMaker) +- Cohere +- VoyageAI +- Hugging Face +- Ollama +- Mistral AI +- Replicate +- Together AI +- AI21 +- Cloudflare Workers AI +- DeepInfra +- Groq +- SambaNova +- [NVIDIA NIMs](https://docs.api.nvidia.com/nim/reference/models-1) +- E muitos outros! + +Para uma lista completa e sempre atualizada dos provedores suportados, consulte a [documentação de Provedores do LiteLLM](https://docs.litellm.ai/docs/providers). + + + Para usar qualquer provedor não coberto por uma integração nativa, adicione o LiteLLM como dependência ao seu projeto: + ```bash + uv add 'crewai[litellm]' + ``` + Provedores nativos (OpenAI, Anthropic, Google Gemini, Azure, AWS Bedrock) usam seus próprios extras de SDK — consulte os [Exemplos de Configuração de Provedores](/pt-BR/concepts/llms#exemplos-de-configuração-de-provedores). + + +## Alterando a LLM + +Para utilizar uma LLM diferente com seus agentes CrewAI, você tem várias opções: + + + + Passe o nome do modelo como uma string ao inicializar o agente: + + ```python Code + from crewai import Agent + + # Usando o GPT-4 da OpenAI + openai_agent = Agent( + role='OpenAI Expert', + goal='Provide insights using GPT-4', + backstory="An AI assistant powered by OpenAI's latest model.", + llm='gpt-4' + ) + + # Usando o Claude da Anthropic + claude_agent = Agent( + role='Anthropic Expert', + goal='Analyze data using Claude', + backstory="An AI assistant leveraging Anthropic's language model.", + llm='claude-2' + ) + ``` + + + + Para uma configuração mais detalhada, utilize a classe LLM: + + ```python Code + from crewai import Agent, LLM + + llm = LLM( + model="gpt-4", + temperature=0.7, + base_url="https://api.openai.com/v1", + api_key="your-api-key-here" + ) + + agent = Agent( + role='Customized LLM Expert', + goal='Provide tailored responses', + backstory="An AI assistant with custom LLM settings.", + llm=llm + ) + ``` + + + + +## Opções de Configuração + +Ao configurar uma LLM para o seu agente, você tem acesso a uma variedade de parâmetros: + +| Parâmetro | Tipo | Descrição | +|:----------|:-----:|:-------------| +| **model** | `str` | O nome do modelo a ser utilizado (ex.: "gpt-4", "claude-2") | +| **temperature** | `float` | Controla o grau de aleatoriedade nas respostas (0.0 a 1.0) | +| **max_tokens** | `int` | Número máximo de tokens a serem gerados | +| **top_p** | `float` | Controla a diversidade das respostas (0.0 a 1.0) | +| **frequency_penalty** | `float` | Penaliza novos tokens com base na frequência em que já apareceram no texto | +| **presence_penalty** | `float` | Penaliza novos tokens com base na presença deles no texto até o momento | +| **stop** | `str`, `List[str]` | Sequência(s) que interrompem a geração do texto | +| **base_url** | `str` | URL base do endpoint da API | +| **api_key** | `str` | Sua chave de API para autenticação | + +Para uma lista completa de parâmetros e suas respectivas descrições, consulte a documentação da classe LLM. + +## Conectando-se a LLMs Compatíveis com OpenAI + +Você pode se conectar a LLMs compatíveis com a OpenAI usando variáveis de ambiente ou definindo atributos específicos na classe LLM: + + + + + ```python Generic + import os + + os.environ["OPENAI_API_KEY"] = "your-api-key" + os.environ["OPENAI_API_BASE"] = "https://api.your-provider.com/v1" + os.environ["OPENAI_MODEL_NAME"] = "your-model-name" + ``` + + ```python Google + import os + + # Exemplo usando a API compatível com OpenAI do Gemini. + os.environ["OPENAI_API_KEY"] = "your-gemini-key" # Deve começar com AIza... + os.environ["OPENAI_API_BASE"] = "https://generativelanguage.googleapis.com/v1beta/openai/" + os.environ["OPENAI_MODEL_NAME"] = "openai/gemini-2.0-flash" # Adicione aqui seu modelo do Gemini, sob openai/ + ``` + + + + + ```python Generic + llm = LLM( + model="custom-model-name", + api_key="your-api-key", + base_url="https://api.your-provider.com/v1" + ) + agent = Agent(llm=llm, ...) + ``` + + ```python Google + # Exemplo usando a API compatível com OpenAI do Gemini + llm = LLM( + model="openai/gemini-2.0-flash", + base_url="https://generativelanguage.googleapis.com/v1beta/openai/", + api_key="your-gemini-key", # Deve começar com AIza... + ) + agent = Agent(llm=llm, ...) + ``` + + + + +## Utilizando Modelos Locais com Ollama + +Para modelos locais como os oferecidos pelo Ollama: + + + + [Clique aqui para baixar e instalar o Ollama](https://ollama.com/download) + + + Por exemplo, execute `ollama pull llama3.2` para baixar o modelo. + + + + ```python Code + agent = Agent( + role='Local AI Expert', + goal='Process information using a local model', + backstory="An AI assistant running on local hardware.", + llm=LLM(model="ollama/llama3.2", base_url="http://localhost:11434") + ) + ``` + + + + +## Alterando a URL Base da API + +Você pode alterar a URL base da API para qualquer provedor de LLM definindo o parâmetro `base_url`: + +```python Code +llm = LLM( + model="custom-model-name", + base_url="https://api.your-provider.com/v1", + api_key="your-api-key" +) +agent = Agent(llm=llm, ...) +``` + +Isso é particularmente útil ao trabalhar com APIs compatíveis com a OpenAI ou quando você precisa especificar um endpoint diferente para o provedor escolhido. + +## Conclusão + +Ao utilizar o LiteLLM, o CrewAI oferece integração transparente com uma vasta gama de LLMs. Essa flexibilidade permite que você escolha o modelo mais adequado para sua necessidade específica, seja priorizando desempenho, custo-benefício ou implantação local. Lembre-se de consultar a [documentação do LiteLLM](https://docs.litellm.ai/docs/) para obter as informações mais atualizadas sobre modelos suportados e opções de configuração. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/llm-hooks.mdx b/docs/v1.15.13/pt-BR/learn/llm-hooks.mdx new file mode 100644 index 0000000000..9122d0d328 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/llm-hooks.mdx @@ -0,0 +1,388 @@ +--- +title: Hooks de Chamada LLM +description: Aprenda a usar hooks de chamada LLM para interceptar, modificar e controlar interações com modelos de linguagem no CrewAI +mode: "wide" +--- + +Os Hooks de Chamada LLM fornecem controle fino sobre interações com modelos de linguagem durante a execução do agente. Esses hooks permitem interceptar chamadas LLM, modificar prompts, transformar respostas, implementar gates de aprovação e adicionar logging ou monitoramento personalizado. + +## Visão Geral + +Os hooks LLM são executados em dois pontos críticos: +- **Antes da Chamada LLM**: Modificar mensagens, validar entradas ou bloquear execução +- **Depois da Chamada LLM**: Transformar respostas, sanitizar saídas ou modificar histórico de conversação + +## Tipos de Hook + +### Hooks Antes da Chamada LLM + +Executados antes de cada chamada LLM, esses hooks podem: +- Inspecionar e modificar mensagens enviadas ao LLM +- Bloquear execução LLM com base em condições +- Implementar limitação de taxa ou gates de aprovação +- Adicionar contexto ou mensagens do sistema +- Registrar detalhes da requisição + +**Assinatura:** +```python +def before_hook(context: LLMCallHookContext) -> bool | None: + # Retorne False para bloquear execução + # Retorne True ou None para permitir execução + ... +``` + +### Hooks Depois da Chamada LLM + +Executados depois de cada chamada LLM, esses hooks podem: +- Modificar ou sanitizar respostas do LLM +- Adicionar metadados ou formatação +- Registrar detalhes da resposta +- Atualizar histórico de conversação +- Implementar filtragem de conteúdo + +**Assinatura:** +```python +def after_hook(context: LLMCallHookContext) -> str | None: + # Retorne string de resposta modificada + # Retorne None para manter resposta original + ... +``` + +## Contexto do Hook LLM + +O objeto `LLMCallHookContext` fornece acesso abrangente ao estado de execução: + +```python +class LLMCallHookContext: + executor: CrewAgentExecutor # Referência completa ao executor + messages: list # Lista de mensagens mutável + agent: Agent # Agente atual + task: Task # Tarefa atual + crew: Crew # Instância da crew + llm: BaseLLM # Instância do LLM + iterations: int # Contagem de iteração atual + response: str | None # Resposta do LLM (apenas hooks posteriores) +``` + +### Modificando Mensagens + +**Importante:** Sempre modifique mensagens in-place: + +```python +# ✅ Correto - modificar in-place +def add_context(context: LLMCallHookContext) -> None: + context.messages.append({"role": "system", "content": "Seja conciso"}) + +# ❌ Errado - substitui referência da lista +def wrong_approach(context: LLMCallHookContext) -> None: + context.messages = [{"role": "system", "content": "Seja conciso"}] +``` + +## Métodos de Registro + +### 1. Registro Baseado em Decoradores (Recomendado) + +Use decoradores para sintaxe mais limpa: + +```python +from crewai.hooks import before_llm_call, after_llm_call + +@before_llm_call +def validate_iteration_count(context): + """Valida a contagem de iterações.""" + if context.iterations > 10: + print("⚠️ Máximo de iterações excedido") + return False # Bloquear execução + return None + +@after_llm_call +def sanitize_response(context): + """Remove dados sensíveis.""" + if context.response and "API_KEY" in context.response: + return context.response.replace("API_KEY", "[CENSURADO]") + return None +``` + +### 2. Hooks com Escopo de Crew + +Registre hooks para uma instância específica de crew: + +```python +from crewai import CrewBase +from crewai.project import crew +from crewai.hooks import before_llm_call_crew, after_llm_call_crew + +@CrewBase +class MyProjCrew: + @before_llm_call_crew + def validate_inputs(self, context): + # Aplica-se apenas a esta crew + if context.iterations == 0: + print(f"Iniciando tarefa: {context.task.description}") + return None + + @after_llm_call_crew + def log_responses(self, context): + # Logging específico da crew + print(f"Comprimento da resposta: {len(context.response)}") + return None + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +## Casos de Uso Comuns + +### 1. Limitação de Iterações + +```python +@before_llm_call +def limit_iterations(context: LLMCallHookContext) -> bool | None: + """Previne loops infinitos limitando iterações.""" + max_iterations = 15 + if context.iterations > max_iterations: + print(f"⛔ Bloqueado: Excedeu {max_iterations} iterações") + return False # Bloquear execução + return None +``` + +### 2. Gate de Aprovação Humana + +```python +@before_llm_call +def require_approval(context: LLMCallHookContext) -> bool | None: + """Requer aprovação após certas iterações.""" + if context.iterations > 5: + response = context.request_human_input( + prompt=f"Iteração {context.iterations}: Aprovar chamada LLM?", + default_message="Pressione Enter para aprovar, ou digite 'não' para bloquear:" + ) + if response.lower() == "não": + print("🚫 Chamada LLM bloqueada pelo usuário") + return False + return None +``` + +### 3. Adicionando Contexto do Sistema + +```python +@before_llm_call +def add_guardrails(context: LLMCallHookContext) -> None: + """Adiciona diretrizes de segurança a cada chamada LLM.""" + context.messages.append({ + "role": "system", + "content": "Garanta que as respostas sejam factuais e cite fontes quando possível." + }) + return None +``` + +### 4. Sanitização de Resposta + +```python +@after_llm_call +def sanitize_sensitive_data(context: LLMCallHookContext) -> str | None: + """Remove padrões sensíveis.""" + if not context.response: + return None + + import re + sanitized = context.response + sanitized = re.sub(r'\b\d{3}\.\d{3}\.\d{3}-\d{2}\b', '[CPF-CENSURADO]', sanitized) + sanitized = re.sub(r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', '[CARTÃO-CENSURADO]', sanitized) + + return sanitized +``` + +### 5. Rastreamento de Custos + +```python +import tiktoken + +@before_llm_call +def track_token_usage(context: LLMCallHookContext) -> None: + """Rastreia tokens de entrada.""" + encoding = tiktoken.get_encoding("cl100k_base") + total_tokens = sum( + len(encoding.encode(msg.get("content", ""))) + for msg in context.messages + ) + print(f"📊 Tokens de entrada: ~{total_tokens}") + return None + +@after_llm_call +def track_response_tokens(context: LLMCallHookContext) -> None: + """Rastreia tokens de resposta.""" + if context.response: + encoding = tiktoken.get_encoding("cl100k_base") + tokens = len(encoding.encode(context.response)) + print(f"📊 Tokens de resposta: ~{tokens}") + return None +``` + +### 6. Logging de Debug + +```python +@before_llm_call +def debug_request(context: LLMCallHookContext) -> None: + """Debug de requisição LLM.""" + print(f""" + 🔍 Debug de Chamada LLM: + - Agente: {context.agent.role} + - Tarefa: {context.task.description[:50]}... + - Iteração: {context.iterations} + - Contagem de Mensagens: {len(context.messages)} + - Última Mensagem: {context.messages[-1] if context.messages else 'Nenhuma'} + """) + return None + +@after_llm_call +def debug_response(context: LLMCallHookContext) -> None: + """Debug de resposta LLM.""" + if context.response: + print(f"✅ Preview da Resposta: {context.response[:100]}...") + return None +``` + +## Gerenciamento de Hooks + +### Desregistrando Hooks + +```python +from crewai.hooks import ( + unregister_before_llm_call_hook, + unregister_after_llm_call_hook +) + +# Desregistrar hook específico +def my_hook(context): + ... + +register_before_llm_call_hook(my_hook) +# Mais tarde... +unregister_before_llm_call_hook(my_hook) # Retorna True se encontrado +``` + +### Limpando Hooks + +```python +from crewai.hooks import ( + clear_before_llm_call_hooks, + clear_after_llm_call_hooks, + clear_all_llm_call_hooks +) + +# Limpar tipo específico de hook +count = clear_before_llm_call_hooks() +print(f"Limpou {count} hooks antes") + +# Limpar todos os hooks LLM +before_count, after_count = clear_all_llm_call_hooks() +print(f"Limpou {before_count} hooks antes e {after_count} hooks depois") +``` + +## Padrões Avançados + +### Execução Condicional de Hook + +```python +@before_llm_call +def conditional_blocking(context: LLMCallHookContext) -> bool | None: + """Bloqueia apenas em condições específicas.""" + # Bloquear apenas para agentes específicos + if context.agent.role == "researcher" and context.iterations > 10: + return False + + # Bloquear apenas para tarefas específicas + if "sensível" in context.task.description.lower() and context.iterations > 5: + return False + + return None +``` + +### Modificações com Consciência de Contexto + +```python +@before_llm_call +def adaptive_prompting(context: LLMCallHookContext) -> None: + """Adiciona contexto diferente baseado na iteração.""" + if context.iterations == 0: + context.messages.append({ + "role": "system", + "content": "Comece com uma visão geral de alto nível." + }) + elif context.iterations > 3: + context.messages.append({ + "role": "system", + "content": "Foque em detalhes específicos e forneça exemplos." + }) + return None +``` + +## Melhores Práticas + +1. **Mantenha Hooks Focados**: Cada hook deve ter uma responsabilidade única +2. **Evite Computação Pesada**: Hooks executam em cada chamada LLM +3. **Trate Erros Graciosamente**: Use try-except para prevenir falhas de hooks +4. **Use Type Hints**: Aproveite `LLMCallHookContext` para melhor suporte IDE +5. **Documente Comportamento do Hook**: Especialmente para condições de bloqueio +6. **Teste Hooks Independentemente**: Teste unitário de hooks antes de usar em produção +7. **Limpe Hooks em Testes**: Use `clear_all_llm_call_hooks()` entre execuções de teste +8. **Modifique In-Place**: Sempre modifique `context.messages` in-place, nunca substitua + +## Tratamento de Erros + +```python +@before_llm_call +def safe_hook(context: LLMCallHookContext) -> bool | None: + try: + # Sua lógica de hook + if some_condition: + return False + except Exception as e: + print(f"⚠️ Erro no hook: {e}") + # Decida: permitir ou bloquear em erro + return None # Permitir execução apesar do erro +``` + +## Segurança de Tipos + +```python +from crewai.hooks import LLMCallHookContext, BeforeLLMCallHookType, AfterLLMCallHookType + +# Anotações de tipo explícitas +def my_before_hook(context: LLMCallHookContext) -> bool | None: + return None + +def my_after_hook(context: LLMCallHookContext) -> str | None: + return None + +# Registro type-safe +register_before_llm_call_hook(my_before_hook) +register_after_llm_call_hook(my_after_hook) +``` + +## Solução de Problemas + +### Hook Não Está Executando +- Verifique se o hook está registrado antes da execução da crew +- Verifique se hook anterior retornou `False` (bloqueia hooks subsequentes) +- Garanta que assinatura do hook corresponda ao tipo esperado + +### Modificações de Mensagem Não Persistem +- Use modificações in-place: `context.messages.append()` +- Não substitua a lista: `context.messages = []` + +### Modificações de Resposta Não Funcionam +- Retorne a string modificada dos hooks posteriores +- Retornar `None` mantém a resposta original + +## Conclusão + +Os Hooks de Chamada LLM fornecem capacidades poderosas para controlar e monitorar interações com modelos de linguagem no CrewAI. Use-os para implementar guardrails de segurança, gates de aprovação, logging, rastreamento de custos e sanitização de respostas. Combinados com tratamento adequado de erros e segurança de tipos, os hooks permitem sistemas de agentes robustos e prontos para produção. + diff --git a/docs/v1.15.13/pt-BR/learn/llm-selection-guide.mdx b/docs/v1.15.13/pt-BR/learn/llm-selection-guide.mdx new file mode 100644 index 0000000000..01587c37ee --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/llm-selection-guide.mdx @@ -0,0 +1,815 @@ +--- +title: "Guia Estratégico de Seleção de LLMs" +description: "Framework estratégico para escolher o LLM certo para seus agentes CrewAI e escrever definições eficazes de tarefas e agentes" +icon: "brain-circuit" +mode: "wide" +--- + +## A Abordagem CrewAI para Seleção de LLMs + +Em vez de recomendações prescritivas de modelos, defendemos um **framework de pensamento** que ajude você a tomar decisões informadas com base no seu caso de uso, restrições e requisitos específicos. O cenário de LLMs evolui rapidamente, com novos modelos surgindo regularmente e os existentes sendo atualizados frequentemente. O que mais importa é desenvolver uma abordagem sistemática de avaliação que permaneça relevante independentemente dos modelos disponíveis no momento. + + + Este guia foca em pensamento estratégico em vez de recomendações de modelos + específicos, já que o cenário dos LLMs evolui rapidamente. + + +## Framework de Decisão Rápida + + + + Comece entendendo profundamente o que suas tarefas realmente exigem. + Considere a complexidade cognitiva envolvida, a profundidade de raciocínio + necessária, o formato dos resultados esperados e a quantidade de contexto + que o modelo precisará processar. Essa análise fundamental guiará todas as + decisões seguintes. + + + Assim que você compreende seus requisitos, mapeie-os para as forças dos + modelos. Diferentes famílias de modelos se destacam em diferentes tipos de + trabalho; alguns são otimizados para raciocínio e análise, outros para + criatividade e geração de conteúdo, e outros para velocidade e eficiência. + + + Leve em conta suas reais restrições operacionais, incluindo limitações + orçamentárias, requisitos de latência, necessidades de privacidade de dados + e capacidades de infraestrutura. O melhor modelo teoricamente pode não ser a + melhor escolha prática para sua situação. + + + Comece com modelos confiáveis e bem conhecidos e otimize com base no + desempenho real no seu caso de uso. Os resultados práticos frequentemente + diferem dos benchmarks teóricos, então testes empíricos são cruciais. + + + +## Framework Central de Seleção + +### a. Pensamento Orientado à Tarefa + +O passo mais crítico na seleção de LLMs é entender o que sua tarefa realmente exige. Frequentemente, equipes escolhem modelos com base em reputação geral ou pontuações de benchmark, sem analisar cuidadosamente suas necessidades específicas. Essa abordagem leva tanto ao superdimensionamento de tarefas simples usando modelos caros e complexos quanto à subutilização em tarefas sofisticadas com modelos sem as capacidades necessárias. + + + + - **Tarefas Simples** representam a maioria do trabalho diário de IA e incluem seguir instruções básicas, processar dados simples e formatação elementar. Estas tarefas geralmente têm entradas e saídas claras, com mínima ambiguidade. A carga cognitiva é baixa e o modelo precisa apenas seguir instruções explícitas, não realizar raciocínio complexo. + + - **Tarefas Complexas** exigem raciocínio de múltiplas etapas, pensamento estratégico e a capacidade de lidar com informações ambíguas ou incompletas. Podem envolver análise de múltiplas fontes de dados, desenvolvimento de estratégias abrangentes ou resolução de problemas que precisam ser decompostos em componentes menores. O modelo deve manter o contexto ao longo de várias etapas de raciocínio e frequentemente precisa inferir informações não explicitamente declaradas. + + - **Tarefas Criativas** exigem um tipo diferente de capacidade cognitiva, focada em gerar conteúdo novo, envolvente e adequado ao contexto. Isso inclui storytelling, criação de textos de marketing e solução criativa de problemas. O modelo deve compreender nuances, tom e público, produzindo conteúdo autêntico e envolvente, não apenas fórmulas. + + + + + - **Dados Estruturados** exigem precisão e consistência na adesão ao formato. Ao trabalhar com JSON, XML ou formatos de banco de dados, o modelo deve produzir saídas sintaticamente corretas, que possam ser processadas programaticamente. Essas tarefas possuem requisitos rígidos de validação e pouca tolerância a erros de formato, tornando a confiabilidade mais importante que a criatividade. + + - **Conteúdo Criativo** requer equilíbrio entre competência técnica e criatividade. O modelo precisa compreender o público, tom e voz da marca, ao mesmo tempo em que produz conteúdo que engaja leitores e atinge objetivos comunicativos específicos. A qualidade aqui é mais subjetiva e exige modelos capazes de adaptar o estilo de escrita a diferentes contextos e propósitos. + + - **Conteúdo Técnico** situa-se entre dados estruturados e conteúdo criativo, demandando precisão e clareza. Documentação, geração de código e análises técnicas precisam ser exatas e completas, mas ainda assim acessíveis ao público-alvo. O modelo deve entender conceitos técnicos complexos e comunicá-los de forma eficaz. + + + + + - **Contexto Curto** envolve tarefas imediatas e focalizadas, onde o modelo processa informações limitadas rapidamente. São interações transacionais em que velocidade e eficiência importam mais do que compreensão profunda. O modelo não precisa manter histórico extenso ou processar grandes documentos. + + - **Contexto Longo** é necessário ao lidar com documentos substanciais, conversas extensas ou tarefas complexas de múltiplas partes. O modelo precisa manter coerência ao longo de milhares de tokens, referenciando informações anteriores com precisão. Essencial para análise de documentos, pesquisa abrangente e sistemas de diálogo sofisticados. + + - **Contexto Muito Longo** ultrapassa os limites do possível hoje, com processamento de documentos massivos, síntese de pesquisas extensas ou interações multi-sessão. São casos que exigem modelos projetados especificamente para lidar com contexto estendido e envolvem trade-offs entre extensão e velocidade. + + + + +### b. Mapeamento de Capacidades do Modelo + +Entender as capacidades dos modelos exige ir além do marketing e dos benchmarks, analisando forças e limitações fundamentais das arquiteturas e métodos de treinamento. + + + + Modelos de raciocínio formam uma categoria especializada, projetada para tarefas de pensamento complexo e de múltiplas etapas. Eles se destacam na resolução de problemas que requerem análise cuidadosa, planejamento estratégico ou decomposição sistemática. Normalmente aplicam técnicas como chain-of-thought ou tree-of-thought para conduzir o raciocínio passo a passo. + + O ponto forte é manter consistência lógica em cadeias longas de raciocínio e decompor problemas complexos em partes gerenciáveis. São especialmente valiosos para planejamento estratégico, análise complexa e situações onde a qualidade do raciocínio importa mais que a velocidade. + + Entretanto, há trade-offs em termos de custo e velocidade. Podem ser menos adequados para tarefas criativas ou operações simples, onde suas capacidades avançadas não são necessárias. Considere-os quando as tarefas realmente se beneficiarem dessa análise detalhada. + + + + + Modelos de uso geral oferecem uma abordagem equilibrada, com desempenho sólido em uma ampla gama de tarefas, sem especialização extrema. São treinados em conjuntos de dados diversificados e otimizados para versatilidade. + + A principal vantagem é a confiabilidade previsível em diversos trabalhos: pesquisa, análise, criação de conteúdo, processamento de dados. São ótimas opções iniciais para equipes que buscam consistência ao lidar com fluxos variados. + + Embora não atinjam picos de desempenho como modelos especializados, oferecem simplicidade operacional e baixa complexidade na gestão. São o melhor ponto de partida para novos projetos, permitindo descobertas de necessidades antes de avançar para otimizações. + + + + + Modelos rápidos e eficientes priorizam velocidade, custo e eficiência de recursos, em vez de raciocínio sofisticado. São otimizados para cenários de alto volume onde respostas rápidas e baixos custos são mais importantes que compreensão ou criatividade profunda. + + Brilham em operações rotineiras, processamento simples de dados, chamadas de funções e tarefas de alto volume. Aplicações que processam muitos pedidos rapidamente ou operam sob restrições orçamentárias se beneficiam desses modelos. + + O ponto crucial é garantir que suas capacidades atendam às exigências da tarefa. Podem não atender tarefas que exijam entendimento profundo, raciocínio complexo ou geração de conteúdo sofisticado. São ideais para tarefas rotineiras bem definidas. + + + + + Modelos criativos são otimizados para geração de conteúdo, qualidade de escrita e pensamento inovador. Excelentes na compreensão de nuances, tom e estilo, produzindo conteúdo envolvente e natural. + + O ponto forte está em adaptar o estilo para diferentes públicos, manter voz e tom consistentes e engajar leitores. Performam melhor em storytelling, textos publicitários, comunicações de marca e outras tarefas com criatividade como foco. + + Ao selecionar esses modelos, considere não apenas a habilidade de gerar texto, mas a compreensão de público, contexto e objetivo. Os melhores modelos criativos adaptam a saída à voz da marca, diferentes segmentos e mantêm consistência em peças longas. + + + + + Modelos open source oferecem vantagens em controle de custos, potencial de customização, privacidade de dados e flexibilidade de deployment. Podem ser rodados localmente ou em infraestrutura própria, dando controle total sobre dados e comportamento. + + Os principais benefícios incluem eliminação de custos por token, possibilidade de fine-tuning, privacidade total e independência de fornecedores externos. Perfeitos para organizações com necessidade de privacidade, orçamento limitado ou desejo de customização. + + Contudo, requerem maior expertise técnica para implantar e manter. Considere custos de infraestrutura, complexidade de gestão e esforços contínuos de atualização e otimização ao avaliar modelos open source. O custo total pode ser maior que o de alternativas em nuvem devido a esse overhead. + + + + +## Padrões Estratégicos de Configuração + +### a. Abordagem Multi-Modelo + + + Use diferentes modelos para diferentes propósitos dentro da mesma crew para + otimizar desempenho e custos. + + +As implementações CrewAI mais sofisticadas empregam múltiplos modelos estrategicamente, designando-os conforme as funções e necessidades dos agentes. Assim, é possível otimizar desempenho e custos usando o modelo mais adequado para cada tipo de tarefa. + +Agentes de planejamento se beneficiam de modelos de raciocínio para pensamento estratégico e análise multi-etapas. Esses agentes funcionam como o "cérebro" da operação. Agentes de conteúdo têm melhor desempenho com modelos criativos focados em qualidade de escrita e engajamento. Agentes de processamento, responsáveis por operações rotineiras, podem usar modelos eficientes priorizando velocidade. + +**Exemplo: Crew de Pesquisa e Análise** + +```python +from crewai import Agent, Task, Crew, LLM + +# Modelo de raciocínio para planejamento estratégico +manager_llm = LLM(model="gemini-2.5-flash-preview-05-20", temperature=0.1) + +# Modelo criativo para gerar conteúdo +content_llm = LLM(model="claude-3-5-sonnet-20241022", temperature=0.7) + +# Modelo eficiente para processamento de dados +processing_llm = LLM(model="gpt-4o-mini", temperature=0) + +research_manager = Agent( + role="Research Strategy Manager", + goal="Develop comprehensive research strategies and coordinate team efforts", + backstory="Expert research strategist with deep analytical capabilities", + llm=manager_llm, # Modelo de alto nível para raciocínio complexo + verbose=True +) + +content_writer = Agent( + role="Research Content Writer", + goal="Transform research findings into compelling, well-structured reports", + backstory="Skilled writer who excels at making complex topics accessible", + llm=content_llm, # Modelo criativo para conteúdo envolvente + verbose=True +) + +data_processor = Agent( + role="Data Analysis Specialist", + goal="Extract and organize key data points from research sources", + backstory="Detail-oriented analyst focused on accuracy and efficiency", + llm=processing_llm, # Modelo rápido para tarefas rotineiras + verbose=True +) + +crew = Crew( + agents=[research_manager, content_writer, data_processor], + tasks=[...], # Suas tarefas específicas + manager_llm=manager_llm, # Manager usa o modelo de raciocínio + verbose=True +) +``` + +O segredo do sucesso na implementação multi-modelo está em entender como os agentes interagem e garantir que as capacidades dos modelos estejam alinhadas às responsabilidades. Isso exige planejamento estratégico, mas traz ganhos significativos em qualidade dos resultados e eficiência operacional. + +### b. Seleção Específica por Componente + + + + O manager LLM desempenha papel central em fluxos hierárquicos CrewAI, coordenando agentes e tarefas. Este modelo precisa se destacar em delegação, priorização de tarefas e manutenção de contexto em várias operações simultâneas. + + LLMs de manager eficazes exigem forte raciocínio para delegar bem, desempenho consistente para coordenar previsivelmente e excelente gestão de contexto para acompanhar o estado dos agentes. O modelo deve entender capacidades e limitações dos agentes enquanto otimiza a alocação de tarefas. + + O custo é especialmente relevante, já que este LLM participa de todas as operações. O modelo precisa entregar capacidades suficientes, sem o preço premium de opções sofisticadas demais, buscando sempre o equilíbrio entre performance e valor. + + + + + LLMs de function calling gerenciam o uso de ferramentas por todos os agentes, sendo críticos em crews que dependem fortemente de APIs externas e ferramentas. Devem ser precisos na extração de parâmetros e no processamento das respostas. + + As características mais importantes são precisão e confiabilidade, não criatividade ou raciocínio avançado. O modelo deve extrair parâmetros corretos de comandos em linguagem natural consistentemente e processar respostas de ferramentas adequadamente. Velocidade também importa, pois o uso de ferramentas pode envolver múltiplas idas e vindas de informação. + + Muitas equipes descobrem que modelos especializados em function calling ou de uso geral com forte suporte a ferramentas funcionam melhor do que modelos criativos ou de raciocínio nesse papel. O fundamental é assegurar que o modelo consiga converter instruções em chamadas estruturadas sem falhas. + + + + + Agentes individuais podem sobrescrever o LLM do nível da crew quando suas necessidades diferem significativamente das do restante. Isso permite otimização pontual, mantendo a simplicidade operacional para os demais agentes. + + Considere sobrescritas quando a função do agente exige capacidades distintas. Por exemplo, um agente de redação criativa pode se beneficiar de um LLM otimizado para geração de conteúdo, enquanto um analista de dados pode preferir um modelo voltado ao raciocínio. + + O desafio é balancear otimização com complexidade operacional. Cada modelo adicional aumenta a complexidade de deployment, monitoramento e custos. Foque em sobrescritas apenas quando a melhoria justificar essa complexidade. + + + + +## Framework de Definição de Tarefas + +### a. Foque em Clareza, Não em Complexidade + +Definir bem as tarefas é frequentemente mais importante do que a seleção do modelo no resultado gerado pelos agentes CrewAI. Tarefas bem formuladas orientam claramente mesmo modelos simples a terem bom desempenho. Já tarefas mal definidas prejudicam até os modelos mais avançados. + + + + As melhores descrições de tarefas equilibram detalhamento e clareza. Devem definir o objetivo de forma clara e sem ambiguidade, além de explicar o método a ser usado com detalhes que permitam ao agente agir corretamente. + + Descrições eficazes incluem contexto relevante e restrições, ajudando o agente a entender o propósito maior e quaisquer limitações. Divida trabalhos complexos em etapas gerenciáveis em vez de objetivos genéricos e sobrecarregados. + + Erros comuns incluem objetivos vagos, falta de contexto, critérios de sucesso mal definidos ou mistura de tarefas totalmente distintas em um mesmo texto. O objetivo é passar informação suficiente para o sucesso, mas mantendo foco no resultado claro. + + + + + As diretrizes da saída esperada funcionam como contrato entre definição de tarefa e agente, especificando claramente o que deve ser entregue e como será avaliado. Elas abrangem formato, estrutura e elementos essenciais. + + As melhores diretrizes incluem exemplos concretos de indicadores de qualidade e critérios claros de conclusão, de modo que agente e revisores humanos possam avaliar o resultado facilmente. Isso reduz ambiguidades e garante resultados consistentes. + + Evite descrições genéricas que serviriam para qualquer tarefa, ausência de especificações de formato, padrões vagos ou falta de exemplos/modelos que ajudem o agente a entender as expectativas. + + + + +### b. Estratégia de Sequenciamento de Tarefas + + + + Dependências são essenciais quando as tarefas se baseiam em resultados prévios, informações fluem de uma tarefa para outra, ou a qualidade depende da conclusão de fases anteriores. Assim, cada tarefa recebe o contexto correto para o sucesso. + + Para implementar bem, use o parâmetro de contexto para encadear tarefas, desenvolvendo gradualmente a complexidade. Cada tarefa deve gerar saídas que alimentam as próximas. O objetivo é manter um fluxo lógico entre as tarefas dependentes, evitando gargalos desnecessários. + + Funciona melhor quando há progressão lógica evidente e quando a saída de uma tarefa realmente agrega valor nas etapas seguintes. Cuidado com os gargalos; foque nas dependências essenciais. + + + + + A execução paralela é valiosa quando as tarefas são independentes, o tempo é crítico ou há expertise distintas que não exigem coordenação. Pode reduzir drasticamente o tempo total, permitindo que agentes especializados atuem simultaneamente. + + Para isso, identifique tarefas realmente independentes, agrupe fluxos de trabalho distintos e planeje a integração dos resultados posteriormente. O ponto-chave é garantir que tarefas paralelas não gerem conflitos ou redundâncias. + + Considere o paralelo em múltiplos fluxos independentes, diferentes tipos de análise autônoma, ou criação de conteúdo que pode ser feita ao mesmo tempo. Mas atente-se à alocação de recursos, evitando sobrecarga de modelos ou estouro no orçamento. + + + + +## Otimizando a Configuração dos Agentes para Desempenho de LLMs + +### a. Seleção de LLM Guiada pelo Papel + + + Funções genéricas de agentes tornam impossível escolher o LLM certo. Funções + específicas permitem otimização do modelo conforme a função. + + +A especificidade das funções dos agentes determina quais capacidades de LLM mais importam para alto desempenho, criando oportunidade estratégica de alinhar forças do modelo ao papel do agente. + +**Impacto de Funções Genéricas vs. Específicas:** + +Ao definir funções, pense no conhecimento do domínio, estilo de trabalho e frameworks decisórios mais valiosos para o tipo de tarefa do agente. Quanto mais específica e contextualizada a função, melhor o modelo incorporará esse papel. + +```python +# ✅ Função específica - requisitos claros de LLM +specific_agent = Agent( + role="SaaS Revenue Operations Analyst", # Expertise de domínio clara + goal="Analyze recurring revenue metrics and identify growth opportunities", + backstory="Specialist in SaaS business models with deep understanding of ARR, churn, and expansion revenue", + llm=LLM(model="gpt-4o") # Raciocínio justificado para análise complexa +) +``` + +**Estratégia de Mapeamento de Função para Modelo:** + +- **"Research Analyst"** → Modelo de raciocínio (GPT-4o, Claude Sonnet) para análise complexa +- **"Content Editor"** → Modelo criativo (Claude, GPT-4o) para qualidade de escrita +- **"Data Processor"** → Modelo eficiente (GPT-4o-mini, Gemini Flash) para tarefas estruturadas +- **"API Coordinator"** → Modelo otimizado para function calling (GPT-4o, Claude) para uso de ferramentas + +### b. Backstory como Amplificador de Contexto do Modelo + + + Backstories estratégicos maximizam a eficácia do LLM ao contextualizar as + respostas de forma que prompts genéricos não conseguem. + + +Um bom backstory transforma a escolha do LLM de genérica a especializada. Isso é crucial para otimizar custos: um modelo eficiente com contexto certo pode superar um premium sem contexto. + +**Exemplo de Performance Guiada por Contexto:** + +```python +# Contexto amplifica a efetividade do modelo +domain_expert = Agent( + role="B2B SaaS Marketing Strategist", + goal="Develop comprehensive go-to-market strategies for enterprise software", + backstory=""" + You have 10+ years of experience scaling B2B SaaS companies from Series A to IPO. + You understand the nuances of enterprise sales cycles, the importance of product-market + fit in different verticals, and how to balance growth metrics with unit economics. + You've worked with companies like Salesforce, HubSpot, and emerging unicorns, giving + you perspective on both established and disruptive go-to-market strategies. + """, + llm=LLM(model="claude-3-5-sonnet", temperature=0.3) # Criatividade balanceada com conhecimento de domínio +) + +# Esse contexto faz o Claude agir como especialista do setor +# Sem isso, mesmo ele entregaria respostas genéricas +``` + +**Elementos de Backstory que Potencializam a Performance de LLMs:** + +- **Experiência de Domínio**: "10+ anos em vendas enterprise SaaS" +- **Expertise Específica**: "Especialista em due diligence técnica para Série B+" +- **Estilo de Trabalho**: "Decisões orientadas a dados, documentação clara" +- **Padrões de Qualidade**: "Sempre cita fontes e mostra análise detalhada" + +### c. Otimização Holística de Agente + LLM + +As configurações mais eficazes criam sinergia entre função específica, profundidade do backstory e escolha do LLM. Cada elemento reforça o outro para maximizar rendimento. + +**Framework de Otimização:** + +```python +# Exemplo: Agente de Documentação Técnica +tech_writer = Agent( + role="API Documentation Specialist", + goal="Create comprehensive, developer-friendly API documentation", + backstory=""" + You're a technical writer with 8+ years documenting REST APIs, GraphQL endpoints, + and SDK integration guides. You've worked with developer tools companies and + understand what developers need: clear examples, comprehensive error handling, + and practical use cases. You prioritize accuracy and usability over marketing fluff. + """, + llm=LLM( + model="claude-3-5-sonnet", + temperature=0.1 + ), + tools=[code_analyzer_tool, api_scanner_tool], + verbose=True +) +``` + +**Checklist de Alinhamento:** + +- ✅ **Função Específica**: Domínio e responsabilidades claras +- ✅ **Correspondência do LLM**: Forças do modelo conectadas à função +- ✅ **Profundidade do Backstory**: Contexto de domínio disponível pro modelo +- ✅ **Integração de Ferramentas**: Ferramentas fortalecem a função do agente +- ✅ **Ajuste de Parâmetros**: Temperatura e configs otimizadas para a função + +O segredo é criar agentes onde cada configuração reforça sua estratégia de escolha do LLM, maximizando rendimento e otimizando custos. + +## Checklist Prático de Implementação + +Em vez de repetir o framework estratégico, segue um checklist tático para implementar as decisões de seleção de LLM em CrewAI: + + + + **O que analisar:** + - Todos os agentes usam o mesmo LLM por padrão? + - Quais agentes lidam com tarefas mais complexas? + - Quais agentes só processam ou formatam dados? + - Algum agente depende fortemente de ferramentas? + + **Ação**: Documente funções dos agentes e identifique oportunidades de otimização. + + + + + **Defina sua Base:** + ```python + # Comece com um padrão confiável para a crew + default_crew_llm = LLM(model="gpt-4o-mini") # Base econômica + + crew = Crew( + agents=[...], + tasks=[...], + memory=True + ) + ``` + + **Ação**: Defina o LLM padrão da crew antes de otimizar agentes individuais. + + + + + **Identifique e Aprimore Agentes-Chave:** + ```python + # Agentes gerenciadores ou de coordenação + manager_agent = Agent( + role="Project Manager", + llm=LLM(model="gemini-2.5-flash-preview-05-20"), + # ... demais configs + ) + + # Agentes criativos ou customer-facing + content_agent = Agent( + role="Content Creator", + llm=LLM(model="claude-3-5-sonnet"), + # ... demais configs + ) + ``` + + **Ação**: Faça upgrade dos 20% dos agentes que tratam 80% da complexidade. + + + + + **Após colocar os agentes em produção:** + - Use [CrewAI AMP platform](https://app.crewai.com) para testar seleções de modelo A/B + - Execute múltiplas iterações com inputs reais para medir consistência e performance + - Compare custo vs performance na configuração otimizada + - Compartilhe resultados com o time para tomada coletiva de decisão + + **Ação**: Substitua achismos por validação com dados reais usando a plataforma de testes. + + + + +### Quando Usar Tipos Diferentes de Modelos + + + + Modelos de raciocínio tornam-se essenciais quando tarefas exigem pensamento lógico genuíno em múltiplas etapas, planejamento estratégico ou decisões complexas beneficiadas por análise sistemática. Brilham na decomposição de problemas e análise estruturada, não no simples seguimento de padrões. + + Considere-os para desenvolvimento de estratégias de negócios, análise de dados combinados de múltiplas fontes, resolução de problemas dependente de etapas sucessivas e planejamento estratégico envolvendo múltiplas variáveis. + + Entretanto, esses modelos são mais caros e lentos, devendo ser reservados para tarefas onde suas capacidades agregam valor real — evite usá-los apenas para operações simples. + + + + + Modelos criativos são valiosos quando a principal entrega é geração de conteúdo e a qualidade, estilo e engajamento desse conteúdo impactam o sucesso. Se destacam quando redação e estilo importam, ideação criativa é necessária, ou voz de marca é fundamental. + + Use-os em redação de posts, criação de artigos, textos de marketing com viés persuasivo, storytelling e comunicações da marca. Costumam captar nuances e contexto melhor do que generalistas. + + Podem ser menos adequados para tarefas técnicas ou analíticas, onde precisão supera criatividade. Use-os quando aspectos comunicativos são fatores críticos de sucesso. + + + + + Modelos eficientes são ideais para operações frequentes e rotineiras, onde velocidade e custo são prioridade. Trabalham melhor em tarefas com parâmetros bem definidos, sem necessidade de raciocínio avançado ou criatividade. + + Considere-os para processamento e transformação de dados, formatação simples, chamadas de funções (function calling) e operações em alto volume onde custo importa mais. + + O ponto crítico é verificar adequação à tarefa. Funcionam para muitos fluxos rotineiros, mas podem falhar se a tarefa exigir compreensão técnica ou raciocínio. + + + + + Modelos open source são atraentes quando há restrição orçamentária, necessidade de privacidade, personalização especial ou exigência de deployment local. + + Considere para ferramentas internas de empresas, aplicações sensíveis, projetos onde não é possível usar APIs externas, casos com orçamento apertado ou requisitos de customização. + + Mas lembre-se: exigem mais expertise, manutenção e investimentos em infraestrutura. Avalie o custo total da operação ao avaliar esses modelos. + + + + +## Armadilhas Comuns na Seleção de Modelos CrewAI + + + + **O problema**: Usar o mesmo LLM para todos os agentes, independentemente das funções. Prática padrão, mas raramente ótima. + + **Exemplo real**: Usar GPT-4o tanto para planejamento estratégico quanto para extração simples de dados. O manager precisa do raciocínio premium, mas o extrator poderia usar o GPT-4o-mini, muito mais barato. + + **Solução CrewAI**: Configure modelos específicos por agente: + ```python + # Agente estratégico recebe modelo premium + manager = Agent(role="Strategy Manager", llm=LLM(model="gpt-4o")) + + # Agente de processamento recebe modelo eficiente + processor = Agent(role="Data Processor", llm=LLM(model="gpt-4o-mini")) + ``` + + + + + **O problema**: Não entender como funciona a hierarquia LLM da CrewAI — configurações conflitam entre crew, manager e agentes. + + **Exemplo real**: Configurar crew com Claude, mas agentes com GPT, gerando comportamento inconsistente e trocas desnecessárias. + + **Solução CrewAI**: Planeje a hierarquia estrategicamente: + ```python + crew = Crew( + agents=[agent1, agent2], + tasks=[task1, task2], + manager_llm=LLM(model="gpt-4o"), + process=Process.hierarchical + ) + + # Agentes herdam o LLM da crew, salvo sobrescrita + agent1 = Agent(llm=LLM(model="claude-3-5-sonnet")) + ``` + + + + + **O problema**: Escolher modelos pela capacidade geral e ignorar o desempenho em function calling em workflows intensivos em ferramentas. + + **Exemplo real**: Selecionar modelo criativo para agente que só precisa chamar APIs e processar dados estruturados, resultando em má extração de parâmetros. + + **Solução CrewAI**: Priorize desempenho em function calling para agentes que usam ferramentas: + ```python + # Para agentes com muitas ferramentas + tool_agent = Agent( + role="API Integration Specialist", + tools=[search_tool, api_tool, data_tool], + llm=LLM(model="gpt-4o"), + # OU + llm=LLM(model="claude-3-5-sonnet") + ) + ``` + + + + + **O problema**: Decidir configurações complexas de modelo com base em hipóteses não validadas nos fluxos e tarefas reais CrewAI. + + **Exemplo real**: Implementar lógica elaborada de troca de modelo por tipo de tarefa sem testar se os ganhos compensam a complexidade. + + **Solução CrewAI**: Comece simples e otimize baseado em dados reais: + ```python + # Comece assim + crew = Crew(agents=[...], tasks=[...], llm=LLM(model="gpt-4o-mini")) + + # Teste a performance e só depois otimize agentes específicos + # Use testes Enterprise para validar melhorias + ``` + + + + + **O problema**: Não considerar como janela de contexto dos modelos interage com memória e compartilhamento de contexto entre agentes CrewAI. + + **Exemplo real**: Usar modelo de contexto curto para agentes que precisam manter histórico ao longo de múltiplas iterações ou equipes com comunicação extensiva agent-to-agent. + + **Solução CrewAI**: Alinhe capacidades de contexto ao padrão de comunicação da crew. + + + + +## Estratégia de Teste e Iteração + + + + Comece com modelos de uso geral, confiáveis e amplamente suportados. Isso + estabelece base estável para entender necessidades e expectativas de + desempenho antes de otimizar para demandas especializadas. + + + Desenvolva métricas alinhadas ao seu caso de uso e metas de negócio, não + apenas benchmarks gerais. Foque na mensuração de resultados relevantes ao + seu sucesso. + + + Faça mudanças baseadas no desempenho observado no seu contexto, não apenas + considerações teóricas ou recomendações genéricas. O desempenho prático + costuma ser bem diferente dos benchmarks. + + + Avalie todo custo de operação, incluindo modelo, tempo de desenvolvimento, + manutenção e complexidade. O modelo mais barato por token pode não ser o + mais econômico ao considerar todos os fatores. + + + + + Foque em entender seus requisitos primeiro, e então escolha modelos que melhor + correspondam a essas necessidades. O melhor LLM é aquele que consistentemente + entrega os resultados esperados dentro das suas restrições. + + +### Validação de Modelos em Nível Enterprise + +Para equipes sérias sobre otimização, a **plataforma CrewAI AMP** oferece testes sofisticados que vão além do CLI. Ela permite avaliação completa para decisões orientadas por dados na estratégia de LLM. + + + ![Enterprise Testing Interface](/images/enterprise/enterprise-testing.png) + + +**Funcionalidades Avançadas de Teste:** + +- **Comparação Multi-Modelo**: Teste diversos LLMs simultaneamente nas mesmas tarefas e entradas. Compare desempenho entre GPT-4o, Claude, Llama, Groq, Cerebras, e outros líderes em paralelo para identificar a melhor opção para você. + +- **Rigor Estatístico**: Configure múltiplas iterações com inputs consistentes para medir confiabilidade e variação no desempenho. Assim, identifica modelos que performam bem e de modo consistente. + +- **Validação no Mundo Real**: Use os inputs e cenários reais da sua crew, e não apenas benchmarks sintéticos. A plataforma permite testar no contexto da sua indústria, empresa e casos de uso. + +- **Analytics Completo**: Acesse métricas detalhadas de desempenho, tempos de execução e análise de custos para todos os modelos testados. Decisões baseadas em dados reais, não apenas reputação. + +- **Colaboração em Equipe**: Compartilhe resultados e análises com seu time, favorecendo decisões coletivas e estratégias alinhadas. + +Acesse [app.crewai.com](https://app.crewai.com) para começar! + + + A plataforma Enterprise transforma a seleção de modelos de um "palpite" para + um processo orientado por dados, permitindo validar os princípios deste guia + com seus próprios casos de uso. + + +## Resumo dos Princípios-Chave + + + + Escolha os modelos pelo que sua tarefa realmente requer, não por reputação ou capacidades teóricas. + + +{" "} + + Alinhe forças do modelo a papéis e responsabilidades dos agentes para melhor + desempenho. + + +{" "} + + Mantenha uma estratégia coerente de seleção de modelos em fluxos e componentes + relacionados. + + +{" "} + + Valide escolhas em uso real, não apenas em benchmarks. + + +{" "} + + Comece simples e otimize com base na performance e necessidade práticas. + + + + Equilibre performance requerida, custo e complexidade. + + + + + Lembre-se: o melhor LLM é o que entrega consistentemente os resultados de que + você precisa dentro de suas restrições. Conheça seu requisito primeiro, depois + selecione o modelo mais adequado. + + +## Panorama Atual dos Modelos (Junho/2025) + + + **Retrato do Momento**: Os rankings a seguir representam o estado da arte em + Junho de 2025, compilados do [LMSys Arena](https://arena.lmsys.org/), + [Artificial Analysis](https://artificialanalysis.ai/) e outros benchmarks + líderes. Performance, disponibilidade e preço mudam rapidamente. Sempre valide + com seus dados e casos reais. + + +### Principais Modelos por Categoria + +As tabelas abaixo mostram uma amostra dos modelos de maior destaque em cada categoria, junto de orientação sobre aplicação em agentes CrewAI: + + + Estas tabelas exibem apenas alguns modelos líderes por categoria. Existem + muitos outros excelentes. O objetivo é ilustrar exemplos de capacidades + buscadas em vez de apresentar um catálogo completo. + + + + + **Melhores para LLMs Manager e Análises Complexas** + + | Modelo | Score de Inteligência | Custo ($/M tokens) | Velocidade | Melhor Uso em CrewAI | + |:------|:---------------------|:-------------------|:-----------|:--------------------| + | **o3** | 70 | $17.50 | Rápido | Manager LLM para coordenação multi-agente | + | **Gemini 2.5 Pro** | 69 | $3.44 | Rápido | Agentes de planejamento estratégico, coordenação de pesquisa | + | **DeepSeek R1** | 68 | $0.96 | Moderada | Raciocínio com bom custo-benefício | + | **Claude 4 Sonnet** | 53 | $6.00 | Rápido | Agentes de análise que precisam de nuance | + | **Qwen3 235B (Reasoning)** | 62 | $2.63 | Moderada | Alternativa open source para raciocínio | + + Esses modelos se destacam em raciocínio multi-etapas e são ideais para agentes que desenvolvem estratégias, coordenam outros agentes ou analisam informações complexas. + + + + + **Melhores para Desenvolvimento e Workflows com Ferramentas** + + | Modelo | Performance em Coding | Tool Use Score | Custo ($/M tokens) | Melhor Uso em CrewAI | + |:--------|:---------------------|:--------------|:-------------------|:--------------------| + | **Claude 4 Sonnet** | Excelente | 72.7% | $6.00 | Agente principal de código/documentação técnica | + | **Claude 4 Opus** | Excelente | 72.5% | $30.00 | Arquitetura complexa, code review | + | **DeepSeek V3** | Muito bom | Alto | $0.48 | Coding econômico para desenvolvimentos rotineiros | + | **Qwen2.5 Coder 32B** | Muito bom | Médio | $0.15 | Agente de código econômico | + | **Llama 3.1 405B** | Bom | 81.1% | $3.50 | LLM para function calling em workflows intensivos em ferramentas | + + Otimizados para geração de código, debugging e solução técnica, ideais para equipes de desenvolvimento. + + + + + **Melhores para Operações em Massa e Aplicações em Tempo Real** + + | Modelo | Velocidade (tokens/s) | Latência (TTFT) | Custo ($/M tokens) | Melhor Uso em CrewAI | + |:-------|:---------------------|:----------------|:-------------------|:---------------------| + | **Llama 4 Scout** | 2.600 | 0.33s | $0.27 | Agentes de processamento de alto volume | + | **Gemini 2.5 Flash** | 376 | 0.30s | $0.26 | Agentes de resposta em tempo real | + | **DeepSeek R1 Distill** | 383 | Variável | $0.04 | Processamento rápido de baixo custo | + | **Llama 3.3 70B** | 2.500 | 0.52s | $0.60 | Equilíbrio entre velocidade e capacidade | + | **Nova Micro** | Alto | 0.30s | $0.04 | Execução rápida de tarefas simples | + + Priorizam velocidade e eficiência, perfeitos para agentes em operações de rotina ou resposta ágil. **Dica:** Usar provedores de inference rápidos como Groq potencializa open source como Llama. + + + + + **Melhores Modelos Coringa para Crews Diversos** + + | Modelo | Score Global | Versatilidade | Custo ($/M tokens) | Melhor Uso em CrewAI | + |:------------|:--------------|:-------------|:-------------------|:--------------------| + | **GPT-4.1** | 53 | Excelente | $3.50 | LLM generalista para equipes variadas | + | **Claude 3.7 Sonnet** | 48 | Muito boa | $6.00 | Raciocínio e criatividade balanceados | + | **Gemini 2.0 Flash** | 48 | Boa | $0.17 | Generalista de bom custo benefício | + | **Llama 4 Maverick** | 51 | Boa | $0.37 | Open source para usos gerais | + | **Qwen3 32B** | 44 | Boa | $1.23 | Versatilidade econômica | + + Oferecem bom desempenho geral, adequados para crews com demandas amplas. + + + + +### Framework de Seleção para Modelos Atuais + + + + **Priorizando performance**: Use modelos topo de linha como **o3**, **Gemini 2.5 Pro** ou **Claude 4 Sonnet** para managers e agentes críticos. Excelentes em raciocínio e coordenação, porém mais caros. + + **Estratégia**: Implemente abordagem multi-modelo, reservando premium para raciocínio estratégico e eficientes para operações rotineiras. + + + + + **Foco no orçamento**: Foque em modelos como **DeepSeek R1**, **Llama 4 Scout** ou **Gemini 2.0 Flash**, que trazem ótimo desempenho com investimento reduzido. + + **Estratégia**: Use modelos econômicos para maioria dos agentes, reservando premium apenas para funções críticas. + + + + + **Para expertise específica**: Escolha modelos otimizados para seu principal caso de uso: **Claude 4** em código, **Gemini 2.5 Pro** em pesquisa, **Llama 405B** em function calling. + + **Estratégia**: Selecione conforme a principal função da crew, garantindo alinhamento de capacidade e modelo. + + + + + **Para operações sensíveis**: Avalie modelos open source como **Llama 4** series, **DeepSeek V3** ou **Qwen3** para deployment privado, mantendo performance competitiva. + + **Estratégia**: Use open source em infraestrutura própria e aceite possíveis trade-offs por controle dos dados. + + + + +### Considerações-Chave na Seleção de Modelos + +- **Tendências de Performance**: O cenário atual mostra competição forte entre modelos de raciocínio (o3, Gemini 2.5 Pro) e equilibrados (Claude 4, GPT-4.1). Modelos como DeepSeek R1 entregam excelente custo/performance. +- **Trade-off Velocidade x Inteligência**: Modelos como Llama 4 Scout priorizam velocidade (2.600 tokens/s) e inteligência razoável, enquanto outros como o3 maximizam raciocínio em detrimento de velocidade/preço. +- **Viabilidade Open Source**: A distância entre open source e proprietários diminui a cada mês, com Llama 4 Maverick e DeepSeek V3 entregando performance competitiva a preços atrativos. Inferência rápida via Groq maximiza custo-benefício nesses casos. + + + **Testes são essenciais**: Rankings servem de orientação geral, mas seu caso + de uso, prompt e critério podem gerar resultados distintos. Sempre teste + modelos candidatos com suas tarefas e dados reais antes de decidir. + + +### Estratégia Prática de Implementação + + + + Inicie com opções consagradas como **GPT-4.1**, **Claude 3.7 Sonnet** ou **Gemini 2.0 Flash**, que oferecem bom desempenho e ampla validação. + + + + Descubra se sua crew possui requisitos específicos (código, raciocínio, + velocidade) que justifiquem modelos como **Claude 4 Sonnet** para + desenvolvimento ou **o3** para análise. Para aplicações críticas em + velocidade, considere Groq aliado à seleção do modelo. + + + + Use modelos diferentes para agentes distintos conforme o papel. Modelos de + alta capacidade para managers e tarefas complexas, eficientes para rotinas. + + + + Acompanhe métricas relevantes ao seu caso e esteja pronto para ajustar modelos conforme lançamentos ou mudanças de preços. + + diff --git a/docs/v1.15.13/pt-BR/learn/multimodal-agents.mdx b/docs/v1.15.13/pt-BR/learn/multimodal-agents.mdx new file mode 100644 index 0000000000..cf238a2bd5 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/multimodal-agents.mdx @@ -0,0 +1,141 @@ +--- +title: Usando Agentes Multimodais +description: Aprenda como habilitar e usar capacidades multimodais em seus agentes para processar imagens e outros conteúdos não textuais dentro do framework CrewAI. +icon: video +mode: "wide" +--- + +## Usando Agentes Multimodais + +O CrewAI suporta agentes multimodais que podem processar tanto conteúdo textual quanto não textual, como imagens. Este guia mostrará como habilitar e utilizar capacidades multimodais em seus agentes. + +### Habilitando Capacidades Multimodais + +Para criar um agente multimodal, basta definir o parâmetro `multimodal` como `True` ao inicializar seu agente: + +```python +from crewai import Agent + +agent = Agent( + role="Image Analyst", + goal="Analyze and extract insights from images", + backstory="An expert in visual content interpretation with years of experience in image analysis", + multimodal=True # This enables multimodal capabilities +) +``` + +Ao definir `multimodal=True`, o agente é automaticamente configurado com as ferramentas necessárias para lidar com conteúdo não textual, incluindo a `AddImageTool`. + +### Trabalhando com Imagens + +O agente multimodal vem pré-configurado com a `AddImageTool`, permitindo que ele processe imagens. Não é necessário adicionar esta ferramenta manualmente – ela é automaticamente incluída ao habilitar capacidades multimodais. + +Aqui está um exemplo completo mostrando como usar um agente multimodal para analisar uma imagem: + +```python +from crewai import Agent, Task, Crew + +# Create a multimodal agent +image_analyst = Agent( + role="Product Analyst", + goal="Analyze product images and provide detailed descriptions", + backstory="Expert in visual product analysis with deep knowledge of design and features", + multimodal=True +) + +# Create a task for image analysis +task = Task( + description="Analyze the product image at https://example.com/product.jpg and provide a detailed description", + expected_output="A detailed description of the product image", + agent=image_analyst +) + +# Create and run the crew +crew = Crew( + agents=[image_analyst], + tasks=[task] +) + +result = crew.kickoff() +``` + +### Uso Avançado com Contexto + +Você pode fornecer contexto adicional ou perguntas específicas sobre a imagem ao criar tarefas para agentes multimodais. A descrição da tarefa pode incluir aspectos específicos nos quais você deseja que o agente foque: + +```python +from crewai import Agent, Task, Crew + +# Create a multimodal agent for detailed analysis +expert_analyst = Agent( + role="Visual Quality Inspector", + goal="Perform detailed quality analysis of product images", + backstory="Senior quality control expert with expertise in visual inspection", + multimodal=True # AddImageTool is automatically included +) + +# Create a task with specific analysis requirements +inspection_task = Task( + description=""" + Analyze the product image at https://example.com/product.jpg with focus on: + 1. Quality of materials + 2. Manufacturing defects + 3. Compliance with standards + Provide a detailed report highlighting any issues found. + """, + expected_output="A detailed report highlighting any issues found", + agent=expert_analyst +) + +# Create and run the crew +crew = Crew( + agents=[expert_analyst], + tasks=[inspection_task] +) + +result = crew.kickoff() +``` + +### Detalhes da Ferramenta + +Ao trabalhar com agentes multimodais, a `AddImageTool` é automaticamente configurada com o seguinte esquema: + +```python +class AddImageToolSchema: + image_url: str # Required: The URL or path of the image to process + action: Optional[str] = None # Optional: Additional context or specific questions about the image +``` + +O agente multimodal irá automaticamente realizar o processamento de imagens por meio de suas ferramentas internas, permitindo que ele: +- Acesse imagens via URLs ou caminhos de arquivos locais +- Processe o conteúdo da imagem com contexto opcional ou perguntas específicas +- Forneça análises e insights com base nas informações visuais e requisitos da tarefa + +### Boas Práticas + +Ao trabalhar com agentes multimodais, tenha em mente as seguintes boas práticas: + +1. **Acesso à Imagem** + - Certifique-se de que suas imagens estejam acessíveis via URLs alcançáveis pelo agente + - Para imagens locais, considere hospedá-las temporariamente ou utilize caminhos absolutos + - Verifique se as URLs das imagens são válidas e acessíveis antes de rodar as tarefas + +2. **Descrição da Tarefa** + - Seja específico sobre quais aspectos da imagem você deseja que o agente analise + - Inclua perguntas ou requisitos claros na descrição da tarefa + - Considere usar o parâmetro opcional `action` para uma análise focada + +3. **Gerenciamento de Recursos** + - O processamento de imagens pode exigir mais recursos computacionais do que tarefas apenas textuais + - Alguns modelos de linguagem podem exigir codificação em base64 para dados de imagem + - Considere o processamento em lote para múltiplas imagens visando otimizar o desempenho + +4. **Configuração do Ambiente** + - Verifique se seu ambiente possui as dependências necessárias para processamento de imagens + - Certifique-se de que seu modelo de linguagem suporta capacidades multimodais + - Teste primeiro com imagens pequenas para validar sua configuração + +5. **Tratamento de Erros** + - Implemente tratamento apropriado para falhas no carregamento de imagens + - Tenha estratégias de contingência para casos onde o processamento de imagens falhar + - Monitore e registre operações de processamento de imagens para depuração \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/overview.mdx b/docs/v1.15.13/pt-BR/learn/overview.mdx new file mode 100644 index 0000000000..cf97165428 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/overview.mdx @@ -0,0 +1,159 @@ +--- +title: "Visão Geral" +description: "Aprenda como construir, personalizar e otimizar suas aplicações CrewAI com guias e tutoriais completos" +icon: "face-smile" +mode: "wide" +--- + +## Aprenda CrewAI + +Esta seção fornece guias e tutoriais completos para ajudar você a dominar o CrewAI, desde conceitos básicos até técnicas avançadas. Seja você iniciante ou esteja buscando otimizar suas implementações existentes, estes recursos o guiarão por todos os aspectos da construção de workflows poderosos de agentes de IA. + +## Guias de Introdução + +### Conceitos Centrais + + + Aprenda a executar tarefas em ordem sequencial para workflows estruturados. + + + + Implemente execução hierárquica de tarefas com agentes gerentes supervisionando workflows. + + + + Crie workflows dinâmicos com execução condicional de tarefas baseada em resultados. + + + + Execute crews de forma assíncrona para melhorar desempenho e concorrência. + + + +### Desenvolvimento de Agentes + + + Aprenda como personalizar o comportamento, funções e capacidades dos agentes. + + + + Construa agentes que podem escrever, executar e depurar código automaticamente. + + + + Crie agentes capazes de processar texto, imagens e outros tipos de mídia. + + + + Implemente agentes gerentes personalizados para workflows hierárquicos complexos. + + + +## Funcionalidades Avançadas + +### Controle de Workflow + + + Integre supervisão e intervenção humana aos workflows dos agentes. + + + + Permita entrada humana durante a execução de tarefas para tomada de decisões dinâmicas. + + + + Refaça e retome tarefas a partir de execuções anteriores de crews. + + + + Execute crews múltiplas vezes com diferentes entradas de maneira eficiente. + + + +### Personalização & Integração + + + Integre modelos de linguagem personalizados e provedores ao CrewAI. + + + + Configure e gerencie conexões com vários provedores de LLM. + + + + Construa ferramentas personalizadas para estender as capacidades dos agentes. + + + + Use anotações Python para um código mais limpo e fácil de manter. + + + +## Aplicações Especializadas + +### Conteúdo & Mídia + + + Gere imagens utilizando a integração DALL-E com seus agentes. + + + + Integre agentes e modelos já existentes aos workflows do CrewAI. + + + +### Gerenciamento de Ferramentas + + + Configure ferramentas para retornarem sua saída diretamente como resultado da tarefa. + + + +## Recomendações de Rotas de Aprendizagem + +### Para Iniciantes +1. Comece pelo **Processo Sequencial** para entender a execução básica de workflows +2. Aprenda **Personalizando Agentes** para criar configurações de agentes eficazes +3. Explore **Criar Ferramentas Personalizadas** para estender funcionalidades +4. Experimente **Humano no Loop** para workflows interativos + +### Para Usuários Intermediários +1. Domine **Processo Hierárquico** para sistemas multiagente complexos +2. Implemente **Tarefas Condicionais** para workflows dinâmicos +3. Utilize **Kickoff Assíncrono** para otimizar desempenho +4. Integre **LLM Personalizado** para modelos especializados + +### Para Usuários Avançados +1. Construa **Agentes Multimodais** para processamento complexo de mídias +2. Crie **Agentes Gerentes Personalizados** para orquestração sofisticada +3. Implemente **Traga Seu Próprio Agente** para sistemas híbridos +4. Use **Repetir Tarefas** para recuperação de erros robusta + +## Melhores Práticas + +### Desenvolvimento +- **Comece Simples**: Inicie com workflows sequenciais básicos antes de adicionar complexidade +- **Teste de Forma Incremental**: Teste cada componente antes de integrar em sistemas maiores +- **Use Anotações**: Aproveite as anotações Python para código mais limpo e sustentável +- **Ferramentas Personalizadas**: Crie ferramentas reutilizáveis que possam ser compartilhadas entre diferentes agentes + +### Produção +- **Tratamento de Erros**: Implemente mecanismos robustos de tratamento e recuperação de erros +- **Desempenho**: Utilize execução assíncrona e otimize chamadas a LLM para melhor desempenho +- **Monitoramento**: Integre ferramentas de observabilidade para acompanhar o desempenho dos agentes +- **Supervisão Humana**: Inclua checkpoints humanos para decisões críticas + +### Otimização +- **Gestão de Recursos**: Monitore e otimize o uso de tokens e custos de API +- **Design de Workflow**: Elabore workflows que minimizem chamadas desnecessárias ao LLM +- **Eficiência das Ferramentas**: Crie ferramentas eficientes que ofereçam máximo valor com o mínimo de overhead +- **Aprimoramento Iterativo**: Use feedback e métricas para melhorar continuamente o desempenho dos agentes + +## Obtendo Ajuda + +- **Documentação**: Cada guia inclui exemplos detalhados e explicações +- **Comunidade**: Participe do [Fórum CrewAI](https://community.crewai.com) para discussões e suporte +- **Exemplos**: Consulte a seção de Exemplos para implementações completas e funcionais +- **Suporte**: Entre em contato via [support@crewai.com](mailto:support@crewai.com) para assistência técnica + +Comece pelos guias que atendem às suas necessidades atuais e, gradualmente, explore tópicos mais avançados conforme você se sentir confortável com os fundamentos. diff --git a/docs/v1.15.13/pt-BR/learn/replay-tasks-from-latest-crew-kickoff.mdx b/docs/v1.15.13/pt-BR/learn/replay-tasks-from-latest-crew-kickoff.mdx new file mode 100644 index 0000000000..624a991d46 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/replay-tasks-from-latest-crew-kickoff.mdx @@ -0,0 +1,79 @@ +--- +title: Reexecutar Tarefas a partir do Último Crew Kickoff +description: Reexecute tarefas a partir do último crew.kickoff(...) +icon: arrow-right +mode: "wide" +--- + +## Introdução + +O CrewAI oferece a capacidade de reexecutar uma tarefa especificada a partir do último crew kickoff. Esse recurso é particularmente útil quando você concluiu um kickoff e deseja tentar novamente determinadas tarefas, ou não precisa buscar dados novamente porque seus agentes já possuem o contexto salvo da execução do kickoff, sendo necessário apenas reexecutar as tarefas desejadas. + + + Você deve executar `crew.kickoff()` antes de poder reexecutar uma tarefa. + Atualmente, apenas o kickoff mais recente é suportado, então se você utilizar `kickoff_for_each`, será possível reexecutar apenas a partir da execução de crew mais recente. + + +Aqui está um exemplo de como reexecutar a partir de uma tarefa: + +### Reexecutando a partir de uma Tarefa Específica Usando o CLI + +Para utilizar o recurso de reexecução, siga estes passos: + + + + + + Para visualizar os task_ids do último kickoff, utilize: + + ```shell + crewai log-tasks-outputs + ``` + + Após identificar o `task_id` que deseja reexecutar, utilize: + + ```shell + crewai replay -t + ``` + + + + + Certifique-se de que o `crewai` está instalado e devidamente configurado no seu ambiente de desenvolvimento. + + +### Reexecutando uma Tarefa Programaticamente + +Para reexecutar uma tarefa programaticamente, siga os passos abaixo: + + + + Especifique o `task_id` e os parâmetros de entrada para o processo de reexecução. + + + Execute o comando de reexecução dentro de um bloco try-except para lidar com possíveis erros. + + ```python Code + def replay(): + """ + Replay the crew execution from a specific task. + """ + task_id = '' + inputs = {"topic": "CrewAI Training"} # This is optional; you can pass in the inputs you want to replay; otherwise, it uses the previous kickoff's inputs. + try: + YourCrewName_Crew().crew().replay(task_id=task_id, inputs=inputs) + + except subprocess.CalledProcessError as e: + raise Exception(f"An error occurred while replaying the crew: {e}") + + except Exception as e: + raise Exception(f"An unexpected error occurred: {e}") + ``` + + + + +## Conclusão + +Com as melhorias acima e funcionalidades detalhadas, a reexecução de tarefas específicas no CrewAI ficou mais eficiente e robusta. +Certifique-se de seguir exatamente os comandos e passos para aproveitar ao máximo esses recursos. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/sequential-process.mdx b/docs/v1.15.13/pt-BR/learn/sequential-process.mdx new file mode 100644 index 0000000000..92851d31af --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/sequential-process.mdx @@ -0,0 +1,128 @@ +--- +title: Processos Sequenciais +description: Um guia abrangente para utilizar os processos sequenciais na execução de tarefas em projetos CrewAI. +icon: forward +mode: "wide" +--- + +## Introdução + +O CrewAI oferece uma estrutura flexível para execução de tarefas de maneira estruturada, suportando tanto processos sequenciais quanto hierárquicos. +Este guia descreve como implementar esses processos de forma eficaz para garantir execução eficiente das tarefas e a conclusão do projeto. + +## Visão Geral do Processo Sequencial + +O processo sequencial garante que as tarefas sejam executadas uma após a outra, seguindo um progresso linear. +Essa abordagem é ideal para projetos nos quais as tarefas precisam ser concluídas em uma ordem específica. + +### Principais Características + +- **Fluxo Linear de Tarefas**: Garante o progresso ordenado ao tratar tarefas em uma sequência pré-determinada. +- **Simplicidade**: Melhor opção para projetos com tarefas claras e passo a passo. +- **Fácil Monitoramento**: Facilita o acompanhamento da conclusão das tarefas e do progresso do projeto. + +## Implementando o Processo Sequencial + +Para utilizar o processo sequencial, monte sua crew e defina as tarefas na ordem em que devem ser executadas. + +```python Code +from crewai import Crew, Process, Agent, Task, TaskOutput, CrewOutput + +# Define your agents +researcher = Agent( + role='Researcher', + goal='Conduct foundational research', + backstory='An experienced researcher with a passion for uncovering insights' +) +analyst = Agent( + role='Data Analyst', + goal='Analyze research findings', + backstory='A meticulous analyst with a knack for uncovering patterns' +) +writer = Agent( + role='Writer', + goal='Draft the final report', + backstory='A skilled writer with a talent for crafting compelling narratives' +) + +# Define your tasks +research_task = Task( + description='Gather relevant data...', + agent=researcher, + expected_output='Raw Data' +) +analysis_task = Task( + description='Analyze the data...', + agent=analyst, + expected_output='Data Insights' +) +writing_task = Task( + description='Compose the report...', + agent=writer, + expected_output='Final Report' +) + +# Form the crew with a sequential process +report_crew = Crew( + agents=[researcher, analyst, writer], + tasks=[research_task, analysis_task, writing_task], + process=Process.sequential +) + +# Execute the crew +result = report_crew.kickoff() + +# Accessing the type-safe output +task_output: TaskOutput = result.tasks[0].output +crew_output: CrewOutput = result.output +``` + +### Nota: + +Cada tarefa em um processo sequencial **deve** ter um agente atribuído. Certifique-se de que todo `Task` inclua um parâmetro `agent`. + +### Fluxo de Trabalho em Ação + +1. **Tarefa Inicial**: Em um processo sequencial, o primeiro agente conclui sua tarefa e sinaliza a finalização. +2. **Tarefas Subsequentes**: Os agentes assumem suas tarefas conforme o tipo de processo, com os resultados das tarefas anteriores ou diretrizes orientando sua execução. +3. **Finalização**: O processo é concluído assim que a última tarefa é executada, levando à conclusão do projeto. + +## Funcionalidades Avançadas + +### Delegação de Tarefas + +Em processos sequenciais, se um agente possui `allow_delegation` definido como `True`, ele pode delegar tarefas para outros agentes na crew. +Esse recurso é configurado automaticamente quando há múltiplos agentes na crew. + +### Execução Assíncrona + +As tarefas podem ser executadas de forma assíncrona, permitindo processamento paralelo quando apropriado. +Para criar uma tarefa assíncrona, defina `async_execution=True` ao criar a tarefa. + +### Memória e Cache + +O CrewAI suporta recursos de memória e cache: + +- **Memória**: Habilite definindo `memory=True` ao criar a Crew. Isso permite aos agentes reter informações entre as tarefas. +- **Cache**: Por padrão, o cache está habilitado. Defina `cache=False` para desativá-lo. + +### Callbacks + +Você pode definir callbacks tanto no nível da tarefa quanto no nível de etapa: + +- `task_callback`: Executado após a conclusão de cada tarefa. +- `step_callback`: Executado após cada etapa na execução de um agente. + +### Métricas de Uso + +O CrewAI rastreia o uso de tokens em todas as tarefas e agentes. Você pode acessar essas métricas após a execução. + +## Melhores Práticas para Processos Sequenciais + +1. **A Ordem Importa**: Organize as tarefas em uma sequência lógica, onde cada uma aproveite o resultado da anterior. +2. **Descrições Claras de Tarefas**: Forneça descrições detalhadas para cada tarefa, orientando os agentes de forma eficaz. +3. **Seleção Apropriada de Agentes**: Relacione as habilidades e funções dos agentes às necessidades de cada tarefa. +4. **Use o Contexto**: Aproveite o contexto das tarefas anteriores para informar as seguintes. + +Esta documentação atualizada garante que os detalhes reflitam com precisão as últimas mudanças no código e descreve claramente como aproveitar novos recursos e configurações. +O conteúdo foi mantido simples e direto para garantir fácil compreensão. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/streaming-crew-execution.mdx b/docs/v1.15.13/pt-BR/learn/streaming-crew-execution.mdx new file mode 100644 index 0000000000..4a3df07efe --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/streaming-crew-execution.mdx @@ -0,0 +1,384 @@ +--- +title: Streaming na Execução da Crew +description: Transmita saída em tempo real da execução da sua crew no CrewAI +icon: wave-pulse +mode: "wide" +--- + +## Introdução + +O CrewAI fornece a capacidade de transmitir saída em tempo real durante a execução da crew, permitindo que você exiba resultados conforme são gerados, em vez de esperar que todo o processo seja concluído. Este recurso é particularmente útil para construir aplicações interativas, fornecer feedback ao usuário e monitorar processos de longa duração. + +## Como o Streaming Funciona + +Quando o streaming está ativado, o CrewAI captura respostas do LLM e chamadas de ferramentas conforme acontecem, empacotando-as em chunks estruturados que incluem contexto sobre qual task e agent está executando. Você pode iterar sobre esses chunks em tempo real e acessar o resultado final quando a execução for concluída. + +## Ativando o Streaming + +Para ativar o streaming, defina o parâmetro `stream` como `True` ao criar sua crew: + +```python Code +from crewai import Agent, Crew, Task + +# Crie seus agentes e tasks +researcher = Agent( + role="Research Analyst", + goal="Gather comprehensive information on topics", + backstory="You are an experienced researcher with excellent analytical skills.", +) + +task = Task( + description="Research the latest developments in AI", + expected_output="A detailed report on recent AI advancements", + agent=researcher, +) + +# Ativar streaming +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True # Ativar saída em streaming +) +``` + +## Streaming Síncrono + +Quando você chama `kickoff()` em uma crew com streaming ativado, ele retorna um objeto `CrewStreamingOutput` que você pode iterar para receber chunks conforme chegam: + +```python Code +# Iniciar execução com streaming +streaming = crew.kickoff(inputs={"topic": "artificial intelligence"}) + +# Iterar sobre chunks conforme chegam +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# Acessar o resultado final após o streaming completar +result = streaming.result +print(f"\n\nSaída final: {result.raw}") +``` + +### Informações do Chunk de Stream + +Cada chunk fornece contexto rico sobre a execução: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +for chunk in streaming: + print(f"Task: {chunk.task_name} (índice {chunk.task_index})") + print(f"Agent: {chunk.agent_role}") + print(f"Content: {chunk.content}") + print(f"Type: {chunk.chunk_type}") # TEXT ou TOOL_CALL + if chunk.tool_call: + print(f"Tool: {chunk.tool_call.tool_name}") + print(f"Arguments: {chunk.tool_call.arguments}") +``` + +### Acessando Resultados do Streaming + +O objeto `CrewStreamingOutput` fornece várias propriedades úteis: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +# Iterar e coletar chunks +for chunk in streaming: + print(chunk.content, end="", flush=True) + +# Após a iteração completar +print(f"\nCompletado: {streaming.is_completed}") +print(f"Texto completo: {streaming.get_full_text()}") +print(f"Todos os chunks: {len(streaming.chunks)}") +print(f"Resultado final: {streaming.result.raw}") +``` + +## Streaming Assíncrono + +Para aplicações assíncronas, você pode usar `akickoff()` (async nativo) ou `kickoff_async()` (baseado em threads) com iteração assíncrona: + +### Async Nativo com `akickoff()` + +O método `akickoff()` fornece execução async nativa verdadeira em toda a cadeia: + +```python Code +import asyncio + +async def stream_crew(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + # Iniciar streaming async nativo + streaming = await crew.akickoff(inputs={"topic": "AI"}) + + # Iteração assíncrona sobre chunks + async for chunk in streaming: + print(chunk.content, end="", flush=True) + + # Acessar resultado final + result = streaming.result + print(f"\n\nSaída final: {result.raw}") + +asyncio.run(stream_crew()) +``` + +### Async Baseado em Threads com `kickoff_async()` + +Para integração async mais simples ou compatibilidade retroativa: + +```python Code +import asyncio + +async def stream_crew(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + # Iniciar streaming async baseado em threads + streaming = await crew.kickoff_async(inputs={"topic": "AI"}) + + # Iteração assíncrona sobre chunks + async for chunk in streaming: + print(chunk.content, end="", flush=True) + + # Acessar resultado final + result = streaming.result + print(f"\n\nSaída final: {result.raw}") + +asyncio.run(stream_crew()) +``` + + +Para cargas de trabalho de alta concorrência, `akickoff()` é recomendado pois usa async nativo para execução de tasks, operações de memória e recuperação de conhecimento. Consulte o guia [Iniciar Crew de Forma Assíncrona](/pt-BR/learn/kickoff-async) para mais detalhes. + + +## Streaming com kickoff_for_each + +Ao executar uma crew para múltiplas entradas com `kickoff_for_each()`, o streaming funciona de forma diferente dependendo se você usa síncrono ou assíncrono: + +### kickoff_for_each Síncrono + +Com `kickoff_for_each()` síncrono, você obtém uma lista de objetos `CrewStreamingOutput`, um para cada entrada: + +```python Code +crew = Crew( + agents=[researcher], + tasks=[task], + stream=True +) + +inputs_list = [ + {"topic": "AI in healthcare"}, + {"topic": "AI in finance"} +] + +# Retorna lista de saídas de streaming +streaming_outputs = crew.kickoff_for_each(inputs=inputs_list) + +# Iterar sobre cada saída de streaming +for i, streaming in enumerate(streaming_outputs): + print(f"\n=== Entrada {i + 1} ===") + for chunk in streaming: + print(chunk.content, end="", flush=True) + + result = streaming.result + print(f"\n\nResultado {i + 1}: {result.raw}") +``` + +### kickoff_for_each_async Assíncrono + +Com `kickoff_for_each_async()` assíncrono, você obtém um único `CrewStreamingOutput` que produz chunks de todas as crews conforme chegam concorrentemente: + +```python Code +import asyncio + +async def stream_multiple_crews(): + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True + ) + + inputs_list = [ + {"topic": "AI in healthcare"}, + {"topic": "AI in finance"} + ] + + # Retorna saída de streaming única para todas as crews + streaming = await crew.kickoff_for_each_async(inputs=inputs_list) + + # Chunks de todas as crews chegam conforme são gerados + async for chunk in streaming: + print(f"[{chunk.task_name}] {chunk.content}", end="", flush=True) + + # Acessar todos os resultados + results = streaming.results # Lista de objetos CrewOutput + for i, result in enumerate(results): + print(f"\n\nResultado {i + 1}: {result.raw}") + +asyncio.run(stream_multiple_crews()) +``` + +## Tipos de Chunk de Stream + +Chunks podem ser de diferentes tipos, indicados pelo campo `chunk_type`: + +### Chunks TEXT + +Conteúdo de texto padrão de respostas do LLM: + +```python Code +for chunk in streaming: + if chunk.chunk_type == StreamChunkType.TEXT: + print(chunk.content, end="", flush=True) +``` + +### Chunks TOOL_CALL + +Informações sobre chamadas de ferramentas sendo feitas: + +```python Code +for chunk in streaming: + if chunk.chunk_type == StreamChunkType.TOOL_CALL: + print(f"\nChamando ferramenta: {chunk.tool_call.tool_name}") + print(f"Argumentos: {chunk.tool_call.arguments}") +``` + +## Exemplo Prático: Construindo uma UI com Streaming + +Aqui está um exemplo completo mostrando como construir uma aplicação interativa com streaming: + +```python Code +import asyncio +from crewai import Agent, Crew, Task +from crewai.types.streaming import StreamChunkType + +async def interactive_research(): + # Criar crew com streaming ativado + researcher = Agent( + role="Research Analyst", + goal="Provide detailed analysis on any topic", + backstory="You are an expert researcher with broad knowledge.", + ) + + task = Task( + description="Research and analyze: {topic}", + expected_output="A comprehensive analysis with key insights", + agent=researcher, + ) + + crew = Crew( + agents=[researcher], + tasks=[task], + stream=True, + verbose=False + ) + + # Obter entrada do usuário + topic = input("Digite um tópico para pesquisar: ") + + print(f"\n{'='*60}") + print(f"Pesquisando: {topic}") + print(f"{'='*60}\n") + + # Iniciar execução com streaming + streaming = await crew.kickoff_async(inputs={"topic": topic}) + + current_task = "" + async for chunk in streaming: + # Mostrar transições de task + if chunk.task_name != current_task: + current_task = chunk.task_name + print(f"\n[{chunk.agent_role}] Trabalhando em: {chunk.task_name}") + print("-" * 60) + + # Exibir chunks de texto + if chunk.chunk_type == StreamChunkType.TEXT: + print(chunk.content, end="", flush=True) + + # Exibir chamadas de ferramentas + elif chunk.chunk_type == StreamChunkType.TOOL_CALL and chunk.tool_call: + print(f"\n🔧 Usando ferramenta: {chunk.tool_call.tool_name}") + + # Mostrar resultado final + result = streaming.result + print(f"\n\n{'='*60}") + print("Análise Completa!") + print(f"{'='*60}") + print(f"\nUso de Tokens: {result.token_usage}") + +asyncio.run(interactive_research()) +``` + +## Casos de Uso + +O streaming é particularmente valioso para: + +- **Aplicações Interativas**: Fornecer feedback em tempo real aos usuários enquanto os agentes trabalham +- **Tasks de Longa Duração**: Mostrar progresso para pesquisa, análise ou geração de conteúdo +- **Depuração e Monitoramento**: Observar comportamento e tomada de decisão dos agentes em tempo real +- **Experiência do Usuário**: Reduzir latência percebida mostrando resultados incrementais +- **Dashboards ao Vivo**: Construir interfaces de monitoramento que exibem status de execução da crew + +## Cancelamento e Limpeza de Recursos + +`CrewStreamingOutput` suporta cancelamento gracioso para que o trabalho em andamento pare imediatamente quando o consumidor desconecta. + +### Gerenciador de Contexto Assíncrono + +```python Code +streaming = await crew.akickoff(inputs={"topic": "AI"}) + +async with streaming: + async for chunk in streaming: + print(chunk.content, end="", flush=True) +``` + +### Cancelamento Explícito + +```python Code +streaming = await crew.akickoff(inputs={"topic": "AI"}) +try: + async for chunk in streaming: + print(chunk.content, end="", flush=True) +finally: + await streaming.aclose() # assíncrono + # streaming.close() # equivalente síncrono +``` + +Após o cancelamento, `streaming.is_cancelled` e `streaming.is_completed` são ambos `True`. Tanto `aclose()` quanto `close()` são idempotentes. + +## Notas Importantes + +- O streaming ativa automaticamente o streaming do LLM para todos os agentes na crew +- Você deve iterar através de todos os chunks antes de acessar a propriedade `.result` +- Para `kickoff_for_each_async()` com streaming, use `.results` (plural) para obter todas as saídas +- O streaming adiciona overhead mínimo e pode realmente melhorar a performance percebida +- Cada chunk inclui contexto completo (task, agente, tipo de chunk) para UIs ricas + +## Tratamento de Erros + +Trate erros durante a execução com streaming: + +```python Code +streaming = crew.kickoff(inputs={"topic": "AI"}) + +try: + for chunk in streaming: + print(chunk.content, end="", flush=True) + + result = streaming.result + print(f"\nSucesso: {result.raw}") + +except Exception as e: + print(f"\nErro durante o streaming: {e}") + if streaming.is_completed: + print("O streaming foi completado mas ocorreu um erro") +``` + +Ao aproveitar o streaming, você pode construir aplicações mais responsivas e interativas com o CrewAI, fornecendo aos usuários visibilidade em tempo real da execução dos agentes e resultados. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/learn/streaming-runtime-contract.mdx b/docs/v1.15.13/pt-BR/learn/streaming-runtime-contract.mdx new file mode 100644 index 0000000000..3e4a758bb8 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/streaming-runtime-contract.mdx @@ -0,0 +1,194 @@ +--- +title: Contrato de Streaming do Runtime +description: Transmita frames ordenados do runtime a partir de Flows, chamadas diretas de LLM e turnos conversacionais. +icon: tower-broadcast +mode: "wide" +--- + +## Visão geral + +O CrewAI expõe um contrato de streaming baseado em frames para runtimes que precisam de mais do que chunks de texto simples. O contrato emite objetos `StreamFrame` ordenados para eventos de ciclo de vida de Flow, tokens de LLM diretos, atividade de ferramentas, mensagens de conversa e eventos personalizados. + +Use esta API ao criar uma UI, ponte de serviço, aplicativo de terminal ou runtime de implantação que precise de um fluxo estável de eventos estruturados enquanto um Flow, turno de chat ou chamada direta de LLM está em execução. + +## StreamFrame + +Todo frame tem o mesmo envelope: + +```python +from crewai.types.streaming import StreamFrame + +frame.id # id único do frame +frame.seq # ordem local da execução, quando disponível +frame.type # tipo do evento de origem, como "flow_started" +frame.channel # "llm", "flow", "tools", "messages", "lifecycle" ou "custom" +frame.namespace # namespace de origem/runtime +frame.timestamp # timestamp do evento +frame.parent_id # id do evento pai, quando disponível +frame.previous_id # id do evento anterior, quando disponível +frame.data # payload do evento +frame.event # alias para frame.data +frame.content # texto imprimível para frames de token, caso contrário "" +``` + +O campo `channel` é a forma mais rápida de rotear frames em consumidores: + +| Canal | Contém | +|-------|--------| +| `llm` | Tokens e chunks de raciocínio de eventos de streaming de LLM | +| `flow` | Ciclo de vida do Flow, execução de métodos, roteamento e eventos de pausa/retomada | +| `tools` | Eventos de uso de ferramentas | +| `messages` | Eventos do transcript da conversa | +| `lifecycle` | Eventos de ciclo de vida do runtime que não pertencem a outro canal | +| `custom` | Eventos que não mapeiam para um canal integrado | + +`frame.type` preserva o tipo do evento de origem, para que consumidores possam tratar eventos específicos dentro de um canal. + +## Transmitir um Flow + +Defina `stream=True` em um Flow para fazer `kickoff()` retornar uma sessão de stream: + +```python +from crewai.flow import Flow, start + + +class ReportFlow(Flow): + @start() + def generate(self): + return "done" + + +flow = ReportFlow(stream=True) +stream = flow.kickoff() + +with stream: + for chunk in stream: + print(chunk.content, end="", flush=True) + if chunk.type == "tool_usage_started": + print(chunk.event["tool_name"]) + +result = stream.result +``` + +Você deve consumir o stream antes de ler `stream.result`. Acessar o resultado cedo demais gera um `RuntimeError`, para que consumidores não tratem uma execução parcial como concluída. + +Você também pode chamar `flow.stream_events(...)` diretamente quando quiser streaming para uma única invocação sem definir `stream=True` na instância do Flow. + +## Filtrar por canal + +`StreamSession` expõe projeções por canal que preservam a ordem global dos frames dentro do canal selecionado: + +```python +stream = flow.stream_events() + +with stream: + for frame in stream.llm: + print(frame.content, end="", flush=True) + +result = stream.result +``` + +As projeções disponíveis são: + +| Projeção | Frames | +|----------|--------| +| `stream.events` | Todos os frames | +| `stream.llm` | Frames de LLM | +| `stream.messages` | Frames de mensagens de conversa | +| `stream.flow` | Frames de Flow | +| `stream.tools` | Frames de ferramentas | +| `stream.interleave([...])` | Um conjunto selecionado de canais | + +Use `stream.interleave(["flow", "llm", "messages"])` quando um consumidor quiser apenas alguns canais, mas ainda precisar da ordem relativa entre eles. + +## Streaming assíncrono + +Use `astream()` para consumidores assíncronos: + +```python +flow = ReportFlow() +stream = flow.astream() + +async with stream: + async for chunk in stream.events: + print(chunk.channel, chunk.type, chunk.content) + +result = stream.result +``` + +A sessão assíncrona tem as mesmas projeções da sessão síncrona. + +## Transmitir uma chamada direta de LLM + +`llm.call(...)` ainda retorna o resultado final montado. Use `llm.stream_events(...)` quando quiser iterar pelos chunks conforme eles chegam, mantendo o payload estruturado do evento: + +```python +from crewai import LLM + + +llm = LLM(model="gpt-4o-mini") +stream = llm.stream_events( + messages=[ + { + "role": "user", + "content": "Explain CrewAI streaming in two short sentences.", + } + ] +) + +with stream: + for chunk in stream: + print(chunk.content, end="", flush=True) + +result = stream.result +``` + +`llm.stream_events(...)` ativa temporariamente o streaming para a chamada encapsulada e restaura a configuração anterior de `stream` do LLM depois. As integrações de provedores continuam emitindo os eventos de stream de LLM subjacentes; esse helper fornece uma API de iterador comum sobre esses eventos para todos os provedores de LLM. + +## Turnos conversacionais + +Flows conversacionais podem transmitir um turno de usuário com `stream_turn()`: + +```python +from crewai import Flow +from crewai.experimental.conversational import ConversationConfig, ConversationState + + +@ConversationConfig(llm="gpt-4o-mini", defer_trace_finalization=True) +class ChatFlow(Flow[ConversationState]): + conversational = True + + +flow = ChatFlow() +stream = flow.stream_turn("What can you help me with?", session_id="session-1") + +with stream: + for frame in stream.events: + if frame.channel == "llm" and frame.type == "llm_stream_chunk": + print(frame.content, end="", flush=True) + +reply = stream.result +``` + +Durante `stream_turn()`, o caminho de resposta conversacional integrado ativa o streaming de tokens de LLM para esse turno e restaura a configuração anterior de `stream` do LLM depois. Handlers de rota personalizados que criam seus próprios agentes ou instâncias de LLM devem configurar esses LLMs para streaming se precisarem de saída em nível de token. + +## Limpeza + +Use a sessão como gerenciador de contexto quando possível. Se um cliente se desconectar antes de o stream ser esgotado, feche a sessão explicitamente: + +```python +stream = flow.stream_events() + +try: + for frame in stream.events: + print(frame.type) +finally: + if not stream.is_exhausted: + stream.close() +``` + +Para streams assíncronos, use `await stream.aclose()`. + +## Streaming de chunks legado + +O streaming de Crew com `stream=True` ainda retorna a API orientada a chunks `CrewStreamingOutput` descrita em [Streaming da Execução de Crew](/pt-BR/learn/streaming-crew-execution). Chamadas diretas `llm.call(...)` ainda retornam o resultado final do LLM. O contrato de frames é destinado a runtimes que precisam de um envelope de evento estável em Flows, chamadas diretas de LLM, turnos conversacionais, ferramentas e mensagens. diff --git a/docs/v1.15.13/pt-BR/learn/tool-hooks.mdx b/docs/v1.15.13/pt-BR/learn/tool-hooks.mdx new file mode 100644 index 0000000000..aa3b954dfb --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/tool-hooks.mdx @@ -0,0 +1,498 @@ +--- +title: Hooks de Chamada de Ferramenta +description: Aprenda a usar hooks de chamada de ferramenta para interceptar, modificar e controlar execução de ferramentas no CrewAI +mode: "wide" +--- + +Os Hooks de Chamada de Ferramenta fornecem controle fino sobre a execução de ferramentas durante operações do agente. Esses hooks permitem interceptar chamadas de ferramenta, modificar entradas, transformar saídas, implementar verificações de segurança e adicionar logging ou monitoramento abrangente. + +## Visão Geral + +Os hooks de ferramenta são executados em dois pontos críticos: +- **Antes da Chamada de Ferramenta**: Modificar entradas, validar parâmetros ou bloquear execução +- **Depois da Chamada de Ferramenta**: Transformar resultados, sanitizar saídas ou registrar detalhes de execução + +## Tipos de Hook + +### Hooks Antes da Chamada de Ferramenta + +Executados antes de cada execução de ferramenta, esses hooks podem: +- Inspecionar e modificar entradas de ferramenta +- Bloquear execução de ferramenta com base em condições +- Implementar gates de aprovação para operações perigosas +- Validar parâmetros +- Registrar invocações de ferramenta + +**Assinatura:** +```python +def before_hook(context: ToolCallHookContext) -> bool | None: + # Retorne False para bloquear execução + # Retorne True ou None para permitir execução + ... +``` + +### Hooks Depois da Chamada de Ferramenta + +Executados depois de cada execução de ferramenta, esses hooks podem: +- Modificar ou sanitizar resultados de ferramenta +- Adicionar metadados ou formatação +- Registrar resultados de execução +- Implementar validação de resultado +- Transformar formatos de saída + +**Assinatura:** +```python +def after_hook(context: ToolCallHookContext) -> str | None: + # Retorne string de resultado modificado + # Retorne None para manter resultado original + ... +``` + +## Contexto do Hook de Ferramenta + +O objeto `ToolCallHookContext` fornece acesso abrangente ao estado de execução da ferramenta: + +```python +class ToolCallHookContext: + tool_name: str # Nome da ferramenta sendo chamada + tool_input: dict[str, Any] # Parâmetros de entrada mutáveis da ferramenta + tool: CrewStructuredTool # Referência da instância da ferramenta + agent: Agent | BaseAgent | None # Agente executando a ferramenta + task: Task | None # Tarefa atual + crew: Crew | None # Instância da crew + tool_result: str | None # Resultado da ferramenta (apenas hooks posteriores) +``` + +### Modificando Entradas de Ferramenta + +**Importante:** Sempre modifique entradas de ferramenta in-place: + +```python +# ✅ Correto - modificar in-place +def sanitize_input(context: ToolCallHookContext) -> None: + context.tool_input['query'] = context.tool_input['query'].lower() + +# ❌ Errado - substitui referência do dict +def wrong_approach(context: ToolCallHookContext) -> None: + context.tool_input = {'query': 'nova consulta'} +``` + +## Métodos de Registro + +### 1. Registro Baseado em Decoradores (Recomendado) + +Use decoradores para sintaxe mais limpa: + +```python +from crewai.hooks import before_tool_call, after_tool_call + +@before_tool_call +def block_dangerous_tools(context): + """Bloqueia ferramentas perigosas.""" + dangerous_tools = ['delete_database', 'drop_table', 'rm_rf'] + if context.tool_name in dangerous_tools: + print(f"⛔ Ferramenta perigosa bloqueada: {context.tool_name}") + return False # Bloquear execução + return None + +@after_tool_call +def sanitize_results(context): + """Sanitiza resultados.""" + if context.tool_result and "password" in context.tool_result.lower(): + return context.tool_result.replace("password", "[CENSURADO]") + return None +``` + +### 2. Hooks com Escopo de Crew + +Registre hooks para uma instância específica de crew: + +```python +from crewai import CrewBase +from crewai.project import crew +from crewai.hooks import before_tool_call_crew, after_tool_call_crew + +@CrewBase +class MyProjCrew: + @before_tool_call_crew + def validate_tool_inputs(self, context): + # Aplica-se apenas a esta crew + if context.tool_name == "web_search": + if not context.tool_input.get('query'): + print("❌ Consulta de busca inválida") + return False + return None + + @after_tool_call_crew + def log_tool_results(self, context): + # Logging de ferramenta específico da crew + print(f"✅ {context.tool_name} concluída") + return None + + @crew + def crew(self) -> Crew: + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +## Casos de Uso Comuns + +### 1. Guardrails de Segurança + +```python +@before_tool_call +def safety_check(context: ToolCallHookContext) -> bool | None: + """Bloqueia ferramentas que podem causar danos.""" + destructive_tools = [ + 'delete_file', + 'drop_table', + 'remove_user', + 'system_shutdown' + ] + + if context.tool_name in destructive_tools: + print(f"🛑 Ferramenta destrutiva bloqueada: {context.tool_name}") + return False + + # Avisar em operações sensíveis + sensitive_tools = ['send_email', 'post_to_social_media', 'charge_payment'] + if context.tool_name in sensitive_tools: + print(f"⚠️ Executando ferramenta sensível: {context.tool_name}") + + return None +``` + +### 2. Gate de Aprovação Humana + +```python +@before_tool_call +def require_approval_for_actions(context: ToolCallHookContext) -> bool | None: + """Requer aprovação para ações específicas.""" + approval_required = [ + 'send_email', + 'make_purchase', + 'delete_file', + 'post_message' + ] + + if context.tool_name in approval_required: + response = context.request_human_input( + prompt=f"Aprovar {context.tool_name}?", + default_message=f"Entrada: {context.tool_input}\nDigite 'sim' para aprovar:" + ) + + if response.lower() != 'sim': + print(f"❌ Execução de ferramenta negada: {context.tool_name}") + return False + + return None +``` + +### 3. Validação e Sanitização de Entrada + +```python +@before_tool_call +def validate_and_sanitize_inputs(context: ToolCallHookContext) -> bool | None: + """Valida e sanitiza entradas.""" + # Validar consultas de busca + if context.tool_name == 'web_search': + query = context.tool_input.get('query', '') + if len(query) < 3: + print("❌ Consulta de busca muito curta") + return False + + # Sanitizar consulta + context.tool_input['query'] = query.strip().lower() + + # Validar caminhos de arquivo + if context.tool_name == 'read_file': + path = context.tool_input.get('path', '') + if '..' in path or path.startswith('/'): + print("❌ Caminho de arquivo inválido") + return False + + return None +``` + +### 4. Sanitização de Resultado + +```python +@after_tool_call +def sanitize_sensitive_data(context: ToolCallHookContext) -> str | None: + """Sanitiza dados sensíveis.""" + if not context.tool_result: + return None + + import re + result = context.tool_result + + # Remover chaves de API + result = re.sub( + r'(api[_-]?key|token)["\']?\s*[:=]\s*["\']?[\w-]+', + r'\1: [CENSURADO]', + result, + flags=re.IGNORECASE + ) + + # Remover endereços de email + result = re.sub( + r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', + '[EMAIL-CENSURADO]', + result + ) + + # Remover números de cartão de crédito + result = re.sub( + r'\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b', + '[CARTÃO-CENSURADO]', + result + ) + + return result +``` + +### 5. Análise de Uso de Ferramenta + +```python +import time +from collections import defaultdict + +tool_stats = defaultdict(lambda: {'count': 0, 'total_time': 0, 'failures': 0}) + +@before_tool_call +def start_timer(context: ToolCallHookContext) -> None: + context.tool_input['_start_time'] = time.time() + return None + +@after_tool_call +def track_tool_usage(context: ToolCallHookContext) -> None: + start_time = context.tool_input.get('_start_time', time.time()) + duration = time.time() - start_time + + tool_stats[context.tool_name]['count'] += 1 + tool_stats[context.tool_name]['total_time'] += duration + + if not context.tool_result or 'error' in context.tool_result.lower(): + tool_stats[context.tool_name]['failures'] += 1 + + print(f""" + 📊 Estatísticas da Ferramenta {context.tool_name}: + - Execuções: {tool_stats[context.tool_name]['count']} + - Tempo Médio: {tool_stats[context.tool_name]['total_time'] / tool_stats[context.tool_name]['count']:.2f}s + - Falhas: {tool_stats[context.tool_name]['failures']} + """) + + return None +``` + +### 6. Limitação de Taxa + +```python +from collections import defaultdict +from datetime import datetime, timedelta + +tool_call_history = defaultdict(list) + +@before_tool_call +def rate_limit_tools(context: ToolCallHookContext) -> bool | None: + """Limita taxa de chamadas de ferramenta.""" + tool_name = context.tool_name + now = datetime.now() + + # Limpar entradas antigas (mais antigas que 1 minuto) + tool_call_history[tool_name] = [ + call_time for call_time in tool_call_history[tool_name] + if now - call_time < timedelta(minutes=1) + ] + + # Verificar limite de taxa (máximo 10 chamadas por minuto) + if len(tool_call_history[tool_name]) >= 10: + print(f"🚫 Limite de taxa excedido para {tool_name}") + return False + + # Registrar esta chamada + tool_call_history[tool_name].append(now) + return None +``` + +### 7. Logging de Debug + +```python +@before_tool_call +def debug_tool_call(context: ToolCallHookContext) -> None: + """Debug de chamada de ferramenta.""" + print(f""" + 🔍 Debug de Chamada de Ferramenta: + - Ferramenta: {context.tool_name} + - Agente: {context.agent.role if context.agent else 'Desconhecido'} + - Tarefa: {context.task.description[:50] if context.task else 'Desconhecida'}... + - Entrada: {context.tool_input} + """) + return None + +@after_tool_call +def debug_tool_result(context: ToolCallHookContext) -> None: + """Debug de resultado de ferramenta.""" + if context.tool_result: + result_preview = context.tool_result[:200] + print(f"✅ Preview do Resultado: {result_preview}...") + else: + print("⚠️ Nenhum resultado retornado") + return None +``` + +## Gerenciamento de Hooks + +### Desregistrando Hooks + +```python +from crewai.hooks import ( + unregister_before_tool_call_hook, + unregister_after_tool_call_hook +) + +# Desregistrar hook específico +def my_hook(context): + ... + +register_before_tool_call_hook(my_hook) +# Mais tarde... +success = unregister_before_tool_call_hook(my_hook) +print(f"Desregistrado: {success}") +``` + +### Limpando Hooks + +```python +from crewai.hooks import ( + clear_before_tool_call_hooks, + clear_after_tool_call_hooks, + clear_all_tool_call_hooks +) + +# Limpar tipo específico de hook +count = clear_before_tool_call_hooks() +print(f"Limpou {count} hooks antes") + +# Limpar todos os hooks de ferramenta +before_count, after_count = clear_all_tool_call_hooks() +print(f"Limpou {before_count} hooks antes e {after_count} hooks depois") +``` + +## Padrões Avançados + +### Execução Condicional de Hook + +```python +@before_tool_call +def conditional_blocking(context: ToolCallHookContext) -> bool | None: + """Bloqueia apenas em condições específicas.""" + # Bloquear apenas para agentes específicos + if context.agent and context.agent.role == "junior_agent": + if context.tool_name in ['delete_file', 'send_email']: + print(f"❌ Agentes júnior não podem usar {context.tool_name}") + return False + + # Bloquear apenas durante tarefas específicas + if context.task and "sensível" in context.task.description.lower(): + if context.tool_name == 'web_search': + print("❌ Busca na web bloqueada para tarefas sensíveis") + return False + + return None +``` + +### Modificação de Entrada com Consciência de Contexto + +```python +@before_tool_call +def enhance_tool_inputs(context: ToolCallHookContext) -> None: + """Adiciona contexto baseado no papel do agente.""" + # Adicionar contexto baseado no papel do agente + if context.agent and context.agent.role == "researcher": + if context.tool_name == 'web_search': + # Adicionar restrições de domínio para pesquisadores + context.tool_input['domains'] = ['edu', 'gov', 'org'] + + # Adicionar contexto baseado na tarefa + if context.task and "urgente" in context.task.description.lower(): + if context.tool_name == 'send_email': + context.tool_input['priority'] = 'high' + + return None +``` + +## Melhores Práticas + +1. **Mantenha Hooks Focados**: Cada hook deve ter uma responsabilidade única +2. **Evite Computação Pesada**: Hooks executam em cada chamada de ferramenta +3. **Trate Erros Graciosamente**: Use try-except para prevenir falhas de hooks +4. **Use Type Hints**: Aproveite `ToolCallHookContext` para melhor suporte IDE +5. **Documente Condições de Bloqueio**: Deixe claro quando/por que ferramentas são bloqueadas +6. **Teste Hooks Independentemente**: Teste unitário de hooks antes de usar em produção +7. **Limpe Hooks em Testes**: Use `clear_all_tool_call_hooks()` entre execuções de teste +8. **Modifique In-Place**: Sempre modifique `context.tool_input` in-place, nunca substitua +9. **Registre Decisões Importantes**: Especialmente ao bloquear execução de ferramenta +10. **Considere Performance**: Cache validações caras quando possível + +## Tratamento de Erros + +```python +@before_tool_call +def safe_validation(context: ToolCallHookContext) -> bool | None: + try: + # Sua lógica de validação + if not validate_input(context.tool_input): + return False + except Exception as e: + print(f"⚠️ Erro no hook: {e}") + # Decida: permitir ou bloquear em erro + return None # Permitir execução apesar do erro +``` + +## Segurança de Tipos + +```python +from crewai.hooks import ToolCallHookContext, BeforeToolCallHookType, AfterToolCallHookType + +# Anotações de tipo explícitas +def my_before_hook(context: ToolCallHookContext) -> bool | None: + return None + +def my_after_hook(context: ToolCallHookContext) -> str | None: + return None + +# Registro type-safe +register_before_tool_call_hook(my_before_hook) +register_after_tool_call_hook(my_after_hook) +``` + +## Solução de Problemas + +### Hook Não Está Executando +- Verifique se hook está registrado antes da execução da crew +- Verifique se hook anterior retornou `False` (bloqueia execução e hooks subsequentes) +- Garanta que assinatura do hook corresponda ao tipo esperado + +### Modificações de Entrada Não Funcionam +- Use modificações in-place: `context.tool_input['key'] = value` +- Não substitua o dict: `context.tool_input = {}` + +### Modificações de Resultado Não Funcionam +- Retorne a string modificada dos hooks posteriores +- Retornar `None` mantém o resultado original +- Garanta que a ferramenta realmente retornou um resultado + +### Ferramenta Bloqueada Inesperadamente +- Verifique todos os hooks antes por condições de bloqueio +- Verifique ordem de execução do hook +- Adicione logging de debug para identificar qual hook está bloqueando + +## Conclusão + +Os Hooks de Chamada de Ferramenta fornecem capacidades poderosas para controlar e monitorar execução de ferramentas no CrewAI. Use-os para implementar guardrails de segurança, gates de aprovação, validação de entrada, sanitização de resultado, logging e análise. Combinados com tratamento adequado de erros e segurança de tipos, os hooks permitem sistemas de agentes seguros e prontos para produção com observabilidade abrangente. + diff --git a/docs/v1.15.13/pt-BR/learn/using-annotations.mdx b/docs/v1.15.13/pt-BR/learn/using-annotations.mdx new file mode 100644 index 0000000000..1bb936f359 --- /dev/null +++ b/docs/v1.15.13/pt-BR/learn/using-annotations.mdx @@ -0,0 +1,155 @@ +--- +title: "Usando Anotações no crew.py" +description: "Aprenda como usar anotações para estruturar corretamente agentes, tarefas e componentes no CrewAI" +icon: "at" +mode: "wide" +--- + +Este guia explica como utilizar anotações para referenciar corretamente **agentes**, **tarefas** e outros componentes em um arquivo `crew.py` clássico. + + +Novos projetos criados com `crewai create crew ` são JSON-first e usam `crew.jsonc` com `agents/*.jsonc`. Use este guia ao trabalhar em um projeto clássico criado com `crewai create crew --classic`, ao migrar um projeto Python/YAML existente ou quando precisar de controle via decorators em Python. + + +## Introdução + +As anotações no framework CrewAI são utilizadas para decorar classes e métodos, fornecendo metadados e funcionalidades para diversos componentes do seu crew. Em projetos clássicos Python/YAML, elas organizam o código que carrega `config/agents.yaml`, `config/tasks.yaml` e retorna o objeto `Crew`. + +## Anotações Disponíveis + +O framework CrewAI fornece as seguintes anotações: + +- `@CrewBase`: Usada para decorar a classe principal do crew. +- `@agent`: Decora métodos que definem e retornam objetos Agent. +- `@task`: Decora métodos que definem e retornam objetos Task. +- `@crew`: Decora o método que cria e retorna o objeto Crew. +- `@llm`: Decora métodos que inicializam e retornam objetos Language Model. +- `@tool`: Decora métodos que inicializam e retornam objetos Tool. +- `@callback`: Utilizada para definir métodos de callback. +- `@output_json`: Utilizada para métodos que retornam dados em JSON. +- `@output_pydantic`: Utilizada para métodos que retornam modelos Pydantic. +- `@cache_handler`: Utilizada para definição de métodos de manipulação de cache. + +## Exemplos de Uso + +Vamos passar por exemplos de como utilizar essas anotações: + +### 1. Classe Base do Crew + +```python +@CrewBase +class LinkedinProfileCrew(): + """LinkedinProfile crew""" + agents_config = 'config/agents.yaml' + tasks_config = 'config/tasks.yaml' +``` + +A anotação `@CrewBase` é usada para decorar a classe principal do crew. Esta classe geralmente contém as configurações e métodos para criação de agentes, tarefas e do próprio crew. + + +`@CrewBase` faz bem mais do que registrar a classe: + +- **Inicialização de configuração:** busca `agents_config` e `tasks_config` (padrões `config/agents.yaml` e `config/tasks.yaml`) ao lado do arquivo da classe, carrega esses YAMLs na inicialização e utiliza dicionários vazios quando os arquivos não existem. +- **Orquestração de decoradores:** mantém versões memoizadas dos métodos marcados com `@agent`, `@task`, `@before_kickoff` e `@after_kickoff` para que sejam instanciados uma única vez por crew e respeitem a ordem de declaração. +- **Encadeamento de hooks:** conecta automaticamente os hooks preservados ao objeto `Crew` retornado pelo método `@crew`, garantindo que executem antes e depois de `.kickoff()`. +- **Integração MCP:** quando a classe define `mcp_server_params`, `get_mcp_tools()` cria sob demanda um adaptador MCP, carrega as ferramentas declaradas e um hook interno pós-kickoff encerra o adaptador. Consulte a [visão geral de MCP](/pt-BR/mcp/overview) para detalhes de configuração. + + +### 2. Definição de Tool + +```python +@tool +def myLinkedInProfileTool(self): + return LinkedInProfileTool() +``` + +A anotação `@tool` é usada para decorar métodos que retornam objetos tool. Essas ferramentas podem ser usadas por agentes para executar tarefas específicas. + +### 3. Definição de LLM + +```python +@llm +def groq_llm(self): + api_key = os.getenv('api_key') + return ChatGroq(api_key=api_key, temperature=0, model_name="mixtral-8x7b-32768") +``` + +A anotação `@llm` é usada para decorar métodos que inicializam e retornam objetos Language Model. Esses LLMs são utilizados pelos agentes para tarefas de processamento de linguagem natural. + +### 4. Definição de Agente + +```python +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'] + ) +``` + +A anotação `@agent` é usada para decorar métodos que definem e retornam objetos Agent. + +### 5. Definição de Tarefa + +```python +@task +def research_task(self) -> Task: + return Task( + config=self.tasks_config['research_linkedin_task'], + agent=self.researcher() + ) +``` + +A anotação `@task` é usada para decorar métodos que definem e retornam objetos Task. Esses métodos especificam a configuração da tarefa e o agente responsável por ela. + +### 6. Criação do Crew + +```python +@crew +def crew(self) -> Crew: + """Creates the LinkedinProfile crew""" + return Crew( + agents=self.agents, + tasks=self.tasks, + process=Process.sequential, + verbose=True + ) +``` + +A anotação `@crew` é usada para decorar o método que cria e retorna o objeto `Crew`. Este método reúne todos os componentes (agentes e tarefas) em um crew funcional. + +## Configuração YAML Clássica + +Em projetos clássicos, as configurações dos agentes geralmente são armazenadas em um arquivo YAML. Veja um exemplo de como o arquivo `agents.yaml` pode ser estruturado para o agente researcher: + +```yaml +researcher: + role: > + LinkedIn Profile Senior Data Researcher + goal: > + Uncover detailed LinkedIn profiles based on provided name {name} and domain {domain} + Generate a Dall-E image based on domain {domain} + backstory: > + You're a seasoned researcher with a knack for uncovering the most relevant LinkedIn profiles. + Known for your ability to navigate LinkedIn efficiently, you excel at gathering and presenting + professional information clearly and concisely. + allow_delegation: False + verbose: True + llm: groq_llm + tools: + - myLinkedInProfileTool + - mySerperDevTool + - myDallETool +``` + +Esta configuração YAML corresponde ao agente researcher definido na classe `LinkedinProfileCrew`. A configuração especifica o papel do agente, objetivo, contexto e outras propriedades, como o LLM e as tools que ele utiliza. + +Repare como os campos `llm` e `tools` no arquivo YAML correspondem aos métodos decorados com `@llm` e `@tool` na classe Python. + +## Boas Práticas + +- **Nomenclatura Consistente**: Utilize nomenclatura clara e consistente para seus métodos. Por exemplo, métodos de agentes podem ser nomeados de acordo com suas funções (ex: researcher, reporting_analyst). +- **Variáveis de Ambiente**: Utilize variáveis de ambiente para informações sensíveis como chaves de API. +- **Flexibilidade**: Estruture seu crew de forma flexível, permitindo fácil adição ou remoção de agentes e tarefas. +- **Correspondência YAML-Código**: Em projetos clássicos, assegure que os nomes e estruturas nos arquivos YAML correspondam corretamente aos métodos decorados em seu código Python. + +Seguindo essas orientações e utilizando corretamente as anotações, você conseguirá manter crews clássicos bem estruturados. Para novas crews, prefira a estrutura JSON-first em [Crews](/pt-BR/concepts/crews). diff --git a/docs/v1.15.13/pt-BR/mcp/dsl-integration.mdx b/docs/v1.15.13/pt-BR/mcp/dsl-integration.mdx new file mode 100644 index 0000000000..ec036e4205 --- /dev/null +++ b/docs/v1.15.13/pt-BR/mcp/dsl-integration.mdx @@ -0,0 +1,234 @@ +--- +title: Integração DSL MCP +description: Aprenda a usar a sintaxe DSL simples do CrewAI para integrar servidores MCP diretamente com seus agentes usando o campo mcps. +icon: code +mode: "wide" +--- + +## Visão Geral + +A integração DSL (Domain Specific Language) MCP do CrewAI oferece a **forma mais simples** de conectar seus agentes aos servidores MCP (Model Context Protocol). Basta adicionar um campo `mcps` ao seu agente e o CrewAI cuida de toda a complexidade automaticamente. + + + Esta é a **abordagem recomendada** para a maioria dos casos de uso de MCP. + Para cenários avançados que requerem gerenciamento manual de conexão, veja + [MCPServerAdapter](/pt-BR/mcp/overview#advanced-mcpserveradapter). + + +## Uso Básico + +Adicione servidores MCP ao seu agente usando o campo `mcps`: + +```python +from crewai import Agent + +agent = Agent( + role="Assistente de Pesquisa", + goal="Ajudar com tarefas de pesquisa e análise", + backstory="Assistente especialista com acesso a ferramentas avançadas de pesquisa", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=sua_chave&profile=pesquisa" + ] +) + +# As ferramentas MCP agora estão automaticamente disponíveis! +# Não é necessário gerenciamento manual de conexão ou configuração de ferramentas +``` + +## Formatos de Referência Suportados + +### Servidores MCP Remotos Externos + +```python +# Servidor HTTPS básico +"https://api.example.com/mcp" + +# Servidor com autenticação +"https://mcp.exa.ai/mcp?api_key=sua_chave&profile=seu_perfil" + +# Servidor com caminho personalizado +"https://services.company.com/api/v1/mcp" +``` + +### Seleção de Ferramentas Específicas + +Use a sintaxe `#` para selecionar ferramentas específicas de um servidor: + +```python +# Obter apenas a ferramenta de previsão do servidor meteorológico +"https://weather.api.com/mcp#get_forecast" + +# Obter apenas a ferramenta de busca do Exa +"https://mcp.exa.ai/mcp?api_key=sua_chave#web_search_exa" +``` + +### Integrações MCP Conectadas + +Conecte servidores MCP do catálogo CrewAI ou traga os seus próprios. Uma vez conectados em sua conta, referencie-os pelo slug: + +```python +# MCP conectado com todas as ferramentas +"snowflake" + +# Ferramenta específica de um MCP conectado +"stripe#list_invoices" + +# Múltiplos MCPs conectados +mcps=[ + "snowflake", + "stripe", + "github" +] +``` + +## Exemplo Completo + +Aqui está um exemplo completo usando múltiplos servidores MCP: + +```python +from crewai import Agent, Task, Crew, Process + +# Criar agente com múltiplas fontes MCP +agente_multi_fonte = Agent( + role="Analista de Pesquisa Multi-Fonte", + goal="Conduzir pesquisa abrangente usando múltiplas fontes de dados", + backstory="""Pesquisador especialista com acesso a busca web, dados meteorológicos, + informações financeiras e ferramentas de pesquisa acadêmica""", + mcps=[ + # Servidores MCP externos + "https://mcp.exa.ai/mcp?api_key=sua_chave_exa&profile=pesquisa", + "https://weather.api.com/mcp#get_current_conditions", + + # MCPs conectados do catálogo + "snowflake", + "stripe#list_invoices", + "github#search_repositories" + ] +) + +# Criar tarefa de pesquisa abrangente +tarefa_pesquisa = Task( + description="""Pesquisar o impacto dos agentes de IA na produtividade empresarial. + Incluir impactos climáticos atuais no trabalho remoto, tendências do mercado financeiro, + e publicações acadêmicas recentes sobre frameworks de agentes de IA.""", + expected_output="""Relatório abrangente cobrindo: + 1. Análise do impacto dos agentes de IA nos negócios + 2. Considerações climáticas para trabalho remoto + 3. Tendências do mercado financeiro relacionadas à IA + 4. Citações e insights de pesquisa acadêmica + 5. Análise do cenário competitivo""", + agent=agente_multi_fonte +) + +# Criar e executar crew +crew_pesquisa = Crew( + agents=[agente_multi_fonte], + tasks=[tarefa_pesquisa], + process=Process.sequential, + verbose=True +) + +resultado = crew_pesquisa.kickoff() +print(f"Pesquisa concluída com {len(agente_multi_fonte.mcps)} fontes de dados MCP") +``` + +## Recursos Principais + +- 🔄 **Descoberta Automática de Ferramentas**: Ferramentas são descobertas e integradas automaticamente +- 🏷️ **Prevenção de Colisão de Nomes**: Nomes de servidor são prefixados aos nomes das ferramentas +- ⚡ **Otimizado para Performance**: Conexões sob demanda com cache de esquemas +- 🛡️ **Resiliência a Erros**: Tratamento gracioso de servidores indisponíveis +- ⏱️ **Proteção por Timeout**: Timeouts integrados previnem conexões travadas +- 📊 **Integração Transparente**: Funciona perfeitamente com recursos existentes do CrewAI + +## Tratamento de Erros + +A integração DSL MCP é projetada para ser resiliente: + +```python +agente = Agent( + role="Agente Resiliente", + goal="Continuar trabalhando apesar de problemas no servidor", + backstory="Agente que lida graciosamente com falhas", + mcps=[ + "https://servidor-confiavel.com/mcp", # Vai funcionar + "https://servidor-inalcancavel.com/mcp", # Será ignorado graciosamente + "https://servidor-lento.com/mcp", # Timeout gracioso + "snowflake" # MCP conectado do catálogo + ] +) +# O agente usará ferramentas de servidores funcionais e registrará avisos para os que falharem +``` + +## Recursos de Performance + +### Cache Automático + +Esquemas de ferramentas são cacheados por 5 minutos para melhorar a performance: + +```python +# Primeira criação de agente - descobre ferramentas do servidor +agente1 = Agent(role="Primeiro", goal="Teste", backstory="Teste", + mcps=["https://api.example.com/mcp"]) + +# Segunda criação de agente (dentro de 5 minutos) - usa esquemas cacheados +agente2 = Agent(role="Segundo", goal="Teste", backstory="Teste", + mcps=["https://api.example.com/mcp"]) # Muito mais rápido! +``` + +### Conexões Sob Demanda + +Conexões de ferramentas são estabelecidas apenas quando as ferramentas são realmente usadas: + +```python +# Criação do agente é rápida - nenhuma conexão MCP feita ainda +agente = Agent( + role="Agente Sob Demanda", + goal="Usar ferramentas eficientemente", + backstory="Agente eficiente que conecta apenas quando necessário", + mcps=["https://api.example.com/mcp"] +) + +# Conexão MCP é feita apenas quando uma ferramenta é realmente executada +# Isso minimiza o overhead de conexão e melhora a performance de inicialização +``` + +## Melhores Práticas + +### 1. Use Ferramentas Específicas Quando Possível + +```python +# Bom - obter apenas as ferramentas necessárias +mcps=["https://weather.api.com/mcp#get_forecast"] + +# Menos eficiente - obter todas as ferramentas do servidor +mcps=["https://weather.api.com/mcp"] +``` + +### 2. Lidar com Autenticação de Forma Segura + +```python +import os + +# Armazenar chaves API em variáveis de ambiente +exa_key = os.getenv("EXA_API_KEY") +exa_profile = os.getenv("EXA_PROFILE") + +agente = Agent( + role="Agente Seguro", + goal="Usar ferramentas MCP com segurança", + backstory="Agente consciente da segurança", + mcps=[f"https://mcp.exa.ai/mcp?api_key={exa_key}&profile={exa_profile}"] +) +``` + +### 3. Planejar para Falhas de Servidor + +```python +# Sempre incluir opções de backup +mcps=[ + "https://api-principal.com/mcp", # Escolha principal + "https://api-backup.com/mcp", # Opção de backup + "snowflake" # Fallback MCP conectado +] +``` diff --git a/docs/v1.15.13/pt-BR/mcp/multiple-servers.mdx b/docs/v1.15.13/pt-BR/mcp/multiple-servers.mdx new file mode 100644 index 0000000000..911a1603e1 --- /dev/null +++ b/docs/v1.15.13/pt-BR/mcp/multiple-servers.mdx @@ -0,0 +1,65 @@ +--- +title: Conectando a Múltiplos Servidores MCP +description: Saiba como usar o MCPServerAdapter no CrewAI para conectar-se simultaneamente a múltiplos servidores MCP e agregar suas ferramentas. +icon: layer-group +mode: "wide" +--- + +## Visão Geral + +O `MCPServerAdapter` em `crewai-tools` permite que você conecte-se a vários servidores MCP simultaneamente. Isso é útil quando seus agentes precisam acessar ferramentas distribuídas entre diferentes serviços ou ambientes. O adaptador agrega as ferramentas de todos os servidores especificados, tornando-as disponíveis para seus agentes CrewAI. + +## Configuração + +Para conectar-se a múltiplos servidores, você fornece uma lista de dicionários de parâmetros de servidor para o `MCPServerAdapter`. Cada dicionário na lista deve definir os parâmetros para um servidor MCP. + +Os tipos de transporte suportados para cada servidor na lista incluem `stdio`, `sse` e `streamable-http`. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters # Needed for Stdio example + +# Define parameters for multiple MCP servers +server_params_list = [ + # Streamable HTTP Server + { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" + }, + # SSE Server + { + "url": "http://localhost:8000/sse", + "transport": "sse" + }, + # StdIO Server + StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, + ) +] + +try: + with MCPServerAdapter(server_params_list) as aggregated_tools: + print(f"Available aggregated tools: {[tool.name for tool in aggregated_tools]}") + + agente_multiservidor = Agent( + role="Assistente Versátil", + goal="Utilizar ferramentas de servidores MCP locais Stdio, remotos SSE e remotos HTTP.", + backstory="Um agente de IA capaz de aproveitar um conjunto diversificado de ferramentas de múltiplas fontes.", + tools=aggregated_tools, # Todas as ferramentas estão disponíveis aqui + verbose=True, + ) + + ... # Your other agent, tasks, and crew code here + +except Exception as e: + print(f"Error connecting to or using multiple MCP servers (Managed): {e}") + print("Ensure all MCP servers are running and accessible with correct configurations.") + +``` + +## Gerenciamento de Conexão + +Ao utilizar o gerenciador de contexto (`with` statement), o `MCPServerAdapter` gerencia o ciclo de vida (início e término) de todas as conexões aos servidores MCP configurados. Isso simplifica o gerenciamento de recursos e garante que todas as conexões sejam devidamente fechadas ao sair do contexto. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/mcp/overview.mdx b/docs/v1.15.13/pt-BR/mcp/overview.mdx new file mode 100644 index 0000000000..4fc1bdab0d --- /dev/null +++ b/docs/v1.15.13/pt-BR/mcp/overview.mdx @@ -0,0 +1,329 @@ +--- +title: "Servidores MCP como Ferramentas no CrewAI" +description: "Aprenda como integrar servidores MCP como ferramentas nos seus agentes CrewAI usando a biblioteca `crewai-tools`." +icon: plug +mode: "wide" +--- + +## Visão Geral + +O [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) fornece uma maneira padronizada para agentes de IA fornecerem contexto para LLMs comunicando-se com serviços externos, conhecidos como Servidores MCP. + +O CrewAI oferece **duas abordagens** para integração MCP: + +### 🚀 **Novo: Integração DSL Simples** (Recomendado) + +Use o campo `mcps` diretamente nos agentes para integração perfeita de ferramentas MCP: + +```python +from crewai import Agent + +agent = Agent( + role="Analista de Pesquisa", + goal="Pesquisar e analisar informações", + backstory="Pesquisador especialista com acesso a ferramentas externas", + mcps=[ + "https://mcp.exa.ai/mcp?api_key=sua_chave", # Servidor MCP externo + "https://api.weather.com/mcp#get_forecast", # Ferramenta específica do servidor + "snowflake", # MCP conectado do catálogo + "stripe#list_invoices" # Ferramenta específica de MCP conectado + ] +) +# Ferramentas MCP agora estão automaticamente disponíveis para seu agente! +``` + +### 🔧 **Avançado: MCPServerAdapter** (Para Cenários Complexos) + +Para casos de uso avançados que requerem gerenciamento manual de conexão, a biblioteca `crewai-tools` fornece a classe `MCPServerAdapter`. + +Atualmente, suportamos os seguintes mecanismos de transporte: + +- **HTTPS**: para servidores remotos (comunicação segura via HTTPS) +- **Server-Sent Events (SSE)**: para servidores remotos (transmissão de dados unidirecional em tempo real do servidor para o cliente via HTTP) +- **Streamable HTTP**: para servidores remotos (comunicação flexível e potencialmente bidirecional via HTTP, geralmente utilizando SSE para streams do servidor para o cliente) + +## Tutorial em Vídeo + +Assista a este tutorial em vídeo para um guia abrangente sobre a integração do MCP com o CrewAI: + + + +## Instalação + +Antes de começar a usar MCP com `crewai-tools`, é necessário instalar a dependência extra `mcp` do `crewai-tools` com o seguinte comando: + +```shell +uv pip install 'crewai-tools[mcp]' +``` + +## Conceitos Chave & Primeiros Passos + +A classe `MCPServerAdapter` da `crewai-tools` é a principal forma de conectar-se a um servidor MCP e disponibilizar suas ferramentas aos seus agentes CrewAI. Ela suporta diferentes mecanismos de transporte e simplifica o gerenciamento de conexões. + +O uso de um gerenciador de contexto Python (`with`) é a **abordagem recomendada** para o `MCPServerAdapter`. Ele lida automaticamente com a abertura e o fechamento da conexão com o servidor MCP. + +## Configuração de Conexão + +O `MCPServerAdapter` suporta várias opções de configuração para personalizar o comportamento da conexão: + +- **`connect_timeout`** (opcional): Tempo máximo em segundos para aguardar o estabelecimento de uma conexão com o servidor MCP. O padrão é 30 segundos se não especificado. Isso é particularmente útil para servidores remotos que podem ter tempos de resposta variáveis. + +```python +# Exemplo com timeout personalizado para conexão +with MCPServerAdapter(server_params, connect_timeout=60) as tools: + # A conexão terá timeout após 60 segundos se não estabelecida + pass +``` + +```python +from crewai import Agent +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters # Para servidor Stdio + +# Exemplo de server_params (escolha um baseado no seu tipo de servidor): +# 1. Servidor Stdio: +server_params=StdioServerParameters( + command="python3", + args=["servers/your_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +# 2. Servidor SSE: +server_params = { + "url": "http://localhost:8000/sse", + "transport": "sse" +} + +# 3. Servidor Streamable HTTP: +server_params = { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" +} + +# Exemplo de uso (descomente e adapte após definir server_params): +with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + meu_agente = Agent( + role="Usuário de Ferramentas MCP", + goal="Utilizar ferramentas de um servidor MCP.", + backstory="Posso conectar a servidores MCP e usar suas ferramentas.", + tools=mcp_tools, # Passe as ferramentas carregadas para o seu agente + reasoning=True, + verbose=True + ) + # ... restante da configuração do seu crew ... +``` + +Este padrão geral mostra como integrar ferramentas. Para exemplos específicos para cada transporte, consulte os guias detalhados abaixo. + +## Filtrando Ferramentas + +```python +with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: + print(f"Available tools: {[tool.name for tool in mcp_tools]}") + + meu_agente = Agent( + role="Usuário de Ferramentas MCP", + goal="Utilizar ferramentas de um servidor MCP.", + backstory="Posso conectar a servidores MCP e usar suas ferramentas.", + tools=mcp_tools["tool_name"], # Passe as ferramentas filtradas para o seu agente + reasoning=True, + verbose=True + ) + # ... restante da configuração do seu crew ... +``` + +## Usando com CrewBase + +Para usar ferramentas de servidores MCP dentro de uma classe CrewBase, utilize o método `get_mcp_tools`. As configurações dos servidores devem ser fornecidas via o atributo `mcp_server_params`. Você pode passar uma configuração única ou uma lista com múltiplas configurações. + +```python +@CrewBase +class CrewWithMCP: + # ... defina o arquivo de configuração de agentes e tasks ... + + mcp_server_params = [ + # Servidor Streamable HTTP + { + "url": "http://localhost:8001/mcp", + "transport": "streamable-http" + }, + # Servidor SSE + { + "url": "http://localhost:8000/sse", + "transport": "sse" + }, + # Servidor StdIO + StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, + ) + ] + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) # obter todas as ferramentas disponíveis + + # ... restante da configuração do seu crew ... +``` + + +Quando uma classe é decorada com `@CrewBase`, o ciclo de vida do adaptador é controlado automaticamente: + +- A primeira chamada a `get_mcp_tools()` cria de forma preguiçosa um `MCPServerAdapter` compartilhado que é reutilizado por todos os agentes do crew. +- Após a conclusão de `.kickoff()`, um hook pós-kickoff injetado por `@CrewBase` encerra o adaptador, dispensando qualquer limpeza manual. +- Se `mcp_server_params` não estiver definido, `get_mcp_tools()` retorna uma lista vazia, permitindo manter o mesmo fluxo de código com ou sem MCP configurado. + +Assim, é seguro chamar `get_mcp_tools()` em vários agentes ou habilitar/desabilitar MCP dependendo do ambiente. + + + +### Configuração de Timeout de Conexão + +Você pode configurar o timeout de conexão para servidores MCP definindo o atributo de classe `mcp_connect_timeout`. Se nenhum timeout for especificado, o padrão é 30 segundos. + +```python +@CrewBase +class CrewWithMCP: + mcp_server_params = [...] + mcp_connect_timeout = 60 # timeout de 60 segundos para todas as conexões MCP + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) +``` + +```python +@CrewBase +class CrewWithDefaultTimeout: + mcp_server_params = [...] + # Nenhum mcp_connect_timeout especificado - usa padrão de 30 segundos + + @agent + def your_agent(self): + return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) +``` + +### Filtragem de Ferramentas + +Você pode filtrar quais ferramentas estão disponíveis para seu agente passando uma lista de nomes de ferramentas para o método `get_mcp_tools`. + +```python +@agent +def another_agent(self): + return Agent( + config=self.agents_config["your_agent"], + tools=self.get_mcp_tools("tool_1", "tool_2") # obter ferramentas específicas + ) +``` + +A configuração de timeout se aplica a todas as chamadas de ferramentas MCP dentro do crew: + +```python +@CrewBase +class CrewWithCustomTimeout: + mcp_server_params = [...] + mcp_connect_timeout = 90 # timeout de 90 segundos para todas as conexões MCP + + @agent + def filtered_agent(self): + return Agent( + config=self.agents_config["your_agent"], + tools=self.get_mcp_tools("tool_1", "tool_2") # ferramentas específicas com timeout personalizado + ) +``` + +## Explore Integrações MCP + + + + Conecte-se a servidores MCP locais via entrada/saída padrão. Ideal para + scripts e executáveis locais. + + + Integre com servidores MCP remotos usando Server-Sent Events para streaming + de dados em tempo real. + + + Utilize HTTP Streamable para uma comunicação robusta com servidores MCP + remotos. + + + Agregue ferramentas de vários servidores MCP simultaneamente usando um único + adaptador. + + + Revise práticas importantes de segurança para integração MCP e mantenha seus + agentes protegidos. + + + +Confira este repositório para demonstrações completas e exemplos de integração MCP com CrewAI! 👇 + + + Demo MCP do CrewAI + + +## Segurança ao Usar MCP + + + Sempre assegure-se de confiar no servidor MCP antes de utilizá-lo. + + +#### Aviso de Segurança: Ataques de DNS Rebinding + +Transportes SSE podem ser vulneráveis a ataques de DNS rebinding se não forem devidamente protegidos. +Para prevenir isso: + +1. **Sempre valide os cabeçalhos Origin** das conexões SSE recebidas para garantir que venham de fontes esperadas +2. **Evite vincular servidores a todas as interfaces de rede** (0.0.0.0) quando executando localmente – faça o bind apenas para localhost (127.0.0.1) +3. **Implemente autenticação adequada** para todas as conexões SSE + +Sem essas proteções, invasores podem usar DNS rebinding para interagir com servidores MCP locais via sites remotos. + +Para mais detalhes, consulte a [documentação de Segurança de Transporte da MCP da Anthropic](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations). + +### Limitações + +- **Primitivas Suportadas**: Atualmente, o `MCPServerAdapter` suporta principalmente a adaptação de `tools` MCP. + Outras primitivas MCP como `prompts` ou `resources` não são integradas diretamente como componentes CrewAI através deste adaptador por enquanto. +- **Manipulação de Saída**: O adaptador normalmente processa a saída principal de texto de uma ferramenta MCP (por exemplo, `.content[0].text`). Saídas complexas ou multimodais podem exigir tratamento customizado caso não se encaixem nesse padrão. diff --git a/docs/v1.15.13/pt-BR/mcp/security.mdx b/docs/v1.15.13/pt-BR/mcp/security.mdx new file mode 100644 index 0000000000..c62f1d9bc6 --- /dev/null +++ b/docs/v1.15.13/pt-BR/mcp/security.mdx @@ -0,0 +1,166 @@ +--- +title: Considerações de Segurança MCP +description: Saiba mais sobre as principais melhores práticas de segurança ao integrar servidores MCP com seus agentes CrewAI. +icon: lock +mode: "wide" +--- + +## Visão Geral + + +O aspecto mais crítico da segurança MCP é a **confiança**. Você deve **apenas** conectar seus agentes CrewAI a servidores MCP nos quais confie plenamente. + + +Ao integrar serviços externos como servidores MCP (Model Context Protocol) aos seus agentes CrewAI, a segurança é fundamental. +Servidores MCP podem executar código, acessar dados ou interagir com outros sistemas com base nas ferramentas que expõem. +É crucial compreender as implicações e seguir as melhores práticas para proteger suas aplicações e dados. + +### Riscos + +- Executar código arbitrário na máquina onde o agente está rodando (especialmente com o transporte `Stdio` se o servidor puder controlar o comando executado). +- Expor dados sensíveis do seu agente ou do seu ambiente. +- Manipular o comportamento do seu agente de maneiras não intencionais, incluindo realizar chamadas de API não autorizadas em seu nome. +- Sequestrar o processo de raciocínio do agente através de técnicas sofisticadas de prompt injection (veja abaixo). + +### 1. Confiando em Servidores MCP + + +**Somente conecte-se a servidores MCP em que confie.** + + +Antes de configurar o `MCPServerAdapter` para conectar a um servidor MCP, certifique-se de saber: +- **Quem opera o servidor?** É um serviço conhecido, de reputação confiável, ou um servidor interno sob o seu controle? +- **Quais ferramentas ele expõe?** Entenda as capacidades das ferramentas. Elas poderiam ser mal utilizadas caso um invasor obtenha controle ou se o próprio servidor for malicioso? +- **Quais dados ele acessa ou processa?** Saiba se há informações sensíveis que possam ser enviadas ou manipuladas pelo servidor MCP. + +Evite conectar-se a servidores MCP desconhecidos ou não verificados, especialmente se seus agentes lidam com tarefas ou dados sensíveis. + +### 2. Prompt Injection Seguro via Metadados de Ferramentas: O Risco do "Model Control Protocol" + +Um risco significativo e sutil é o potencial para prompt injection através dos metadados das ferramentas. Veja como funciona: + +1. Quando seu agente CrewAI se conecta a um servidor MCP, ele normalmente solicita uma lista de ferramentas disponíveis. +2. O servidor MCP responde com metadados para cada ferramenta, incluindo nome, descrição e descrições de parâmetros. +3. O LLM (Modelo de Linguagem) subjacente do seu agente usa esses metadados para entender como e quando usar as ferramentas. Muitas vezes esses metadados são incorporados no system prompt ou contexto do LLM. +4. Um servidor MCP malicioso pode construir seus metadados (nomes, descrições) para incluir instruções ocultas ou explícitas. Essas instruções podem atuar como prompt injection, efetivamente fazendo o LLM se comportar de determinada maneira, revelar informações sensíveis ou executar ações maliciosas. + +**Crucialmente, esse ataque pode ocorrer simplesmente ao conectar-se a um servidor malicioso e listar suas ferramentas, mesmo que seu agente nunca decida *usar* essas ferramentas.** A mera exposição aos metadados maliciosos pode ser suficiente para comprometer o comportamento do agente. + +**Mitigação:** + +* **Extrema Cautela com Servidores Não Confiáveis:** Reitere: *Não conecte-se a servidores MCP nos quais você não confie totalmente.* O risco de injection de metadados torna isso fundamental. + +### Segurança do Transporte Stdio + +O transporte Stdio (Entrada/Saída Padrão) é tipicamente usado para servidores MCP locais, rodando na mesma máquina que sua aplicação CrewAI. + +- **Isolamento de Processo**: Embora geralmente seja mais seguro pois não envolve exposição de rede por padrão, assegure-se de que o script ou comando executado pelo `StdioServerParameters` é de uma fonte confiável e possui permissões de sistema de arquivos adequadas. Um script Stdio servidor malicioso pode ainda prejudicar seu sistema local. +- **Saneamento de Entrada**: Se o seu script de servidor Stdio recebe entradas complexas derivadas das interações do agente, garanta que o script saneie essas entradas para evitar injection de comandos ou outras vulnerabilidades na lógica do script. +- **Limite de Recursos**: Esteja atento ao fato de que o processo servidor Stdio consome recursos locais (CPU, memória). Assegure-se de que seja bem comportado, evitando esgotar os recursos do sistema. + +### Ataques de Confused Deputy + +O [Problema do Confused Deputy](https://en.wikipedia.org/wiki/Confused_deputy_problem) é uma vulnerabilidade clássica de segurança que pode se manifestar em integrações MCP, especialmente quando um servidor MCP atua como proxy para outros serviços de terceiros (ex: Google Calendar, GitHub) que usam OAuth 2.0 para autorização. + +**Cenário:** + +1. Um servidor MCP (vamos chamá-lo de `MCP-Proxy`) permite que seu agente interaja com o `ThirdPartyAPI`. +2. O `MCP-Proxy` usa seu próprio `client_id` estático ao comunicar-se com o servidor de autorização do `ThirdPartyAPI`. +3. Você, como usuário, autoriza legitimamente o `MCP-Proxy` a acessar o `ThirdPartyAPI` em seu nome. Durante esse processo, o servidor de autenticação pode definir um cookie no seu navegador indicando seu consentimento para o `client_id` do `MCP-Proxy`. +4. Um invasor cria um link malicioso. Esse link inicia um fluxo OAuth com o `MCP-Proxy`, mas é projetado para enganar o servidor de autenticação do `ThirdPartyAPI`. +5. Se você clicar nesse link e o servidor de autenticação do `ThirdPartyAPI` encontrar seu cookie de consentimento existente para o `client_id` do `MCP-Proxy`, pode *deixar de* pedir seu consentimento novamente. +6. O `MCP-Proxy` pode, então, ser enganado a encaminhar um código de autorização (para o `ThirdPartyAPI`) para o atacante, ou um código de autorização MCP que o atacante possa usar para se passar por você perante o `MCP-Proxy`. + +**Mitigação (Principalmente para Desenvolvedores de Servidores MCP):** + +* Servidores proxy MCP usando IDs de cliente estáticos para serviços downstream **devem** obter consentimento explícito do usuário para *cada aplicação cliente ou agente* conectando-se a eles *antes* de iniciar um fluxo OAuth com o serviço de terceiros. Isso significa que o `MCP-Proxy` deve exibir uma tela de consentimento. + +**Implicação para Usuários CrewAI:** + +* Fique atento se um servidor MCP redireciona você para múltiplas autenticações OAuth, especialmente se isso for inesperado ou se as permissões solicitadas forem muito amplas. +* Prefira servidores MCP que deixem clara sua própria identidade e a identidade dos serviços de terceiros que possam fazer proxy. + +### Segurança no Transporte Remoto (SSE & HTTP Transmitível) + +Ao conectar-se a servidores MCP remotos via Server-Sent Events (SSE) ou HTTP transmitível, práticas padrão de segurança web são essenciais. + +### Considerações de Segurança SSE + +### a. Ataques de DNS Rebinding (Especialmente para SSE) + + +**Proteja-se contra ataques de DNS Rebinding.** + + +DNS rebinding permite que um site controlado por atacante contorne a política de mesma origem e faça requisições para servidores na rede local do usuário (ex: `localhost`) ou intranet. Isso é particularmente arriscado se você roda um servidor MCP localmente (ex: para desenvolvimento) e um agente em um ambiente do tipo navegador (embora menos comum no backend CrewAI) ou se o servidor MCP está em uma rede interna. + +**Estratégias de Mitigação para Implementadores de Servidores MCP:** +- **Valide os Headers `Origin` e `Host`**: Servidores MCP (especialmente com SSE) devem validar os headers HTTP `Origin` e/ou `Host` para garantir que as requisições venham dos domínios/clientes esperados. +- **Ligue em `localhost` (127.0.0.1)**: Ao rodar servidores MCP localmente para desenvolvimento, conecte-se a `127.0.0.1` em vez de `0.0.0.0`. Isso impede que sejam acessíveis por outras máquinas na rede. +- **Autenticação**: Exija autenticação para todas as conexões ao seu servidor MCP caso não seja destinado a acesso público anônimo. + +### b. Use HTTPS + +- **Criptografe Dados em Trânsito**: Sempre use HTTPS (HTTP Seguro) para URLs de servidores MCP remotos. Isso criptografa a comunicação entre sua aplicação CrewAI e o servidor MCP, protegendo contra escuta e ataques Man-in-the-Middle (MitM). O `MCPServerAdapter` respeitará o esquema (`http` ou `https`) fornecido na URL. + +### c. Token Passthrough (Anti-Padrão) + +Isso é uma preocupação principalmente para desenvolvedores de servidores MCP, mas entender o conceito ajuda a escolher servidores seguros. + +"Token passthrough" é quando um servidor MCP aceita um token de acesso do seu agente CrewAI (que pode ser um token para um serviço *diferente*, por exemplo, `ServiceA`) e simplesmente o repassa para outra API ( `ServiceB`) downstream sem validação adequada. Especificamente, `ServiceB` (ou o próprio servidor MCP) só deveria aceitar tokens explicitamente emitidos *para eles* (ou seja, o claim 'audience' no token deve corresponder ao servidor/serviço). + +**Riscos:** + +* Burlar controles de segurança (como limites de taxa ou permissões granulares) no servidor MCP ou na API downstream. +* Quebra trilhas de auditoria e responsabilização. +* Permite uso indevido de tokens roubados. + +**Mitigação (Para Desenvolvedores de Servidores MCP):** + +* Servidores MCP **NÃO DEVEM** aceitar tokens que não foram explicitamente emitidos para eles. Devem validar o claim de audiência dos tokens. + +**Implicação para Usuários CrewAI:** + +* Embora isso não seja diretamente controlável pelo usuário, destaca a importância de conectar-se a servidores MCP bem projetados e que sigam as melhores práticas de segurança. + +#### Autenticação e Autorização + +- **Verifique a Identidade**: Se o servidor MCP fornece ferramentas sensíveis ou acesso a dados privados, ele DEVE implementar mecanismos de autenticação robustos para verificar a identidade do cliente (sua aplicação CrewAI). Isso pode envolver chaves de API, tokens OAuth ou outros métodos padrão. +- **Princípio do Menor Privilégio**: Certifique-se de que as credenciais usadas pelo `MCPServerAdapter` (se houver) tenham apenas as permissões necessárias para acessar as ferramentas requeridas. + +### d. Validação e Saneamento de Entrada + +- **Validação de Entrada é Crítica**: Servidores MCP **devem** validar rigorosamente todas as entradas recebidas de agentes *antes* de processá-las ou passá-las para as ferramentas. Esta é a principal defesa contra diversas vulnerabilidades comuns: + - **Injection de Comando:** Caso uma ferramenta construa comandos de shell, queries SQL ou outras instruções de linguagens interpretadas a partir da entrada, o servidor deve sanitizar cuidadosamente esta entrada para evitar que comandos maliciosos sejam injetados e executados. + - **Path Traversal:** Se uma ferramenta acessa arquivos com base em parâmetros de entrada, o servidor deve validar e sanitizar esses caminhos para evitar acesso a arquivos ou diretórios não autorizados (por exemplo, bloqueando sequências `../`). + - **Verificações de Tipo e Faixa de Dados:** Servidores devem garantir que os dados de entrada estejam nos tipos esperados (ex: string, número, booleano) e dentro de faixas aceitáveis ou em formatos definidos (ex: regex para URLs). + - **Validação de Schema JSON:** Todos os parâmetros das ferramentas devem ser validados estritamente com seus esquemas JSON definidos. Isso ajuda a capturar requisições mal formatadas precocemente. +- **Atenção do Lado do Cliente**: Embora a validação no servidor seja fundamental, como usuário CrewAI, fique atento aos dados que seus agentes são configurados para enviar a ferramentas MCP, especialmente ao interagir com servidores MCP novos ou menos confiáveis. + +### e. Limite de Taxa e Gerenciamento de Recursos + +- **Previna Abusos**: Servidores MCP devem implementar limite de taxa para prevenir abusos, seja intencional (ataques de negação de serviço) ou não intencional (ex: um agente mal configurado fazendo muitas requisições). +- **Re-tentativas do Lado do Cliente**: Implemente lógica de repetição sensata em suas tarefas CrewAI se problemas de rede transitórios ou limites de taxa do servidor forem esperados, mas evite re-tentativas agressivas que possam aumentar a carga do servidor. + +## 4. Conselhos para Implementação de Servidor MCP Seguro (Para Desenvolvedores) + +Se você está desenvolvendo um servidor MCP ao qual agentes CrewAI possam se conectar, considere estas melhores práticas além dos pontos acima: + +- **Siga Práticas de Código Seguro**: Adote princípios padrão de programação segura para sua linguagem e framework escolhidos (ex: OWASP Top 10). +- **Princípio do Menor Privilégio**: Certifique-se de que o processo que executa o servidor MCP (especialmente para `Stdio`) tenha apenas as permissões mínimas necessárias. As próprias ferramentas também devem operar com o mínimo de privilégio necessário para executar sua função. +- **Gerenciamento de Dependências**: Mantenha todas as dependências do lado do servidor, incluindo pacotes do sistema operacional, runtimes de linguagem e bibliotecas de terceiros, sempre atualizadas para corrigir vulnerabilidades conhecidas. Use ferramentas para escanear por dependências vulneráveis. +- **Padrões Seguros por Padrão**: Projete seu servidor e suas ferramentas para serem seguros por padrão. Por exemplo, recursos potencialmente arriscados devem ser desabilitados por padrão ou requerer ativação explícita, com avisos claros. +- **Controle de Acesso para Ferramentas**: Implemente mecanismos robustos para controlar quais agentes ou usuários autenticados e autorizados podem acessar ferramentas específicas, especialmente as que são poderosas, sensíveis ou incorram em custos. +- **Tratamento Seguro de Erros**: Servidores não devem expor mensagens detalhadas de erro interno, traces de stack ou informações de debug para o cliente, pois estas podem revelar detalhes internos ou potenciais vulnerabilidades. Logue os erros de forma abrangente no lado do servidor para diagnóstico. +- **Log e Monitoramento Abrangentes**: Implemente um log detalhado de eventos relevantes para segurança (ex: tentativas de autenticação, invocações de ferramenta, erros, mudanças de autorização). Monitore esses logs em busca de atividades suspeitas ou padrões de abuso. +- **Aderência à Especificação de Autorização MCP**: Caso implemente autenticação e autorização, siga estritamente a [especificação de autorização MCP](https://modelcontextprotocol.io/specification/draft/basic/authorization) e as [melhores práticas de segurança OAuth 2.0](https://datatracker.ietf.org/doc/html/rfc9700) relevantes. +- **Auditorias de Segurança Regulares**: Caso seu servidor MCP manipule dados sensíveis, realize operações críticas ou seja exposto publicamente, considere auditorias de segurança periódicas conduzidas por profissionais qualificados. + +## 5. Leituras Adicionais + +Para informações mais detalhadas sobre segurança MCP, consulte a documentação oficial: +- **[Segurança de Transporte MCP](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations)** + +Ao entender essas considerações de segurança e implementar as melhores práticas, você pode aproveitar com segurança o poder dos servidores MCP em seus projetos CrewAI. +Estes pontos não esgotam o assunto, mas cobrem as questões de segurança mais comuns e críticas. +As ameaças continuarão a evoluir, por isso é importante se manter informado e adaptar suas medidas de segurança de acordo. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/mcp/sse.mdx b/docs/v1.15.13/pt-BR/mcp/sse.mdx new file mode 100644 index 0000000000..c44006fb33 --- /dev/null +++ b/docs/v1.15.13/pt-BR/mcp/sse.mdx @@ -0,0 +1,151 @@ +--- +title: Transporte SSE +description: Saiba como conectar o CrewAI a servidores MCP remotos usando Server-Sent Events (SSE) para comunicação em tempo real. +icon: wifi +mode: "wide" +--- + +## Visão Geral + +Server-Sent Events (SSE) fornecem uma forma padrão para um servidor web enviar atualizações a um cliente através de uma única conexão HTTP de longa duração. No contexto do MCP, SSE é utilizado para que servidores remotos transmitam dados (como respostas de ferramentas) para sua aplicação CrewAI em tempo real. + +## Conceitos-Chave + +- **Servidores Remotos**: SSE é adequado para servidores MCP hospedados remotamente. +- **Fluxo Unidirecional**: Normalmente, SSE é um canal de comunicação de mão única, do servidor para o cliente. +- **Configuração do `MCPServerAdapter`**: Para SSE, você fornecerá a URL do servidor e especificará o tipo de transporte. + +## Conectando via SSE + +Você pode se conectar a um servidor MCP baseado em SSE usando duas abordagens principais para gerenciar o ciclo de vida da conexão: + +### 1. Conexão Totalmente Gerenciada (Recomendado) + +Utilizar um gerenciador de contexto Python (`with` statement) é a abordagem recomendada. Ele lida automaticamente com o estabelecimento e o encerramento da conexão com o servidor MCP SSE. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL + "transport": "sse" +} + +# Using MCPServerAdapter with a context manager +try: + with MCPServerAdapter(server_params) as tools: + print(f"Available tools from SSE MCP server: {[tool.name for tool in tools]}") + + # Example: Using a tool from the SSE MCP server + agente_sse = Agent( + role="Usuário de Serviço Remoto", + goal="Utilizar uma ferramenta fornecida por um servidor MCP remoto via SSE.", + backstory="Um agente de IA que conecta a serviços externos via SSE.", + tools=tools, + reasoning=True, + verbose=True, + ) + + sse_task = Task( + description="Buscar atualizações em tempo real das ações 'AAPL' usando uma ferramenta SSE.", + expected_output="O preço mais recente da ação AAPL.", + agent=agente_sse, + markdown=True + ) + + sse_crew = Crew( + agents=[agente_sse], + tasks=[sse_task], + verbose=True, + process=Process.sequential + ) + + if tools: # Only kickoff if tools were loaded + result = sse_crew.kickoff() # Add inputs={'stock_symbol': 'AAPL'} if tool requires it + print("\nCrew Task Result (SSE - Managed):\n", result) + else: + print("Skipping crew kickoff as tools were not loaded (check server connection).") + +except Exception as e: + print(f"Error connecting to or using SSE MCP server (Managed): {e}") + print("Ensure the SSE MCP server is running and accessible at the specified URL.") + +``` + + +Substitua `"http://localhost:8000/sse"` pela URL real do seu servidor MCP SSE. + + +### 2. Ciclo de Vida Manual da Conexão + +Caso precise de um controle mais detalhado, você pode gerenciar manualmente o ciclo de vida da conexão do `MCPServerAdapter`. + + +Você **DEVE** chamar `mcp_server_adapter.stop()` para garantir que a conexão seja encerrada e os recursos liberados. O uso de um bloco `try...finally` é altamente recomendado. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8000/sse", # Replace with your actual SSE server URL + "transport": "sse" +} + +mcp_server_adapter = None +try: + mcp_server_adapter = MCPServerAdapter(server_params) + mcp_server_adapter.start() + tools = mcp_server_adapter.tools + print(f"Available tools (manual SSE): {[tool.name for tool in tools]}") + + manual_sse_agent = Agent( + role="Analista Remoto de Dados", + goal="Analisar dados obtidos de um servidor MCP remoto SSE usando gerenciamento manual de conexão.", + backstory="Um agente de IA especializado em gerenciar conexões SSE explicitamente.", + tools=tools, + verbose=True + ) + + analysis_task = Task( + description="Buscar e analisar as tendências mais recentes de atividade de usuários do servidor SSE.", + expected_output="Um relatório resumido das tendências de atividade dos usuários.", + agent=manual_sse_agent + ) + + analysis_crew = Crew( + agents=[manual_sse_agent], + tasks=[analysis_task], + verbose=True, + process=Process.sequential + ) + + result = analysis_crew.kickoff() + print("\nCrew Task Result (SSE - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual SSE MCP integration: {e}") + print("Ensure the SSE MCP server is running and accessible.") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: + print("Stopping SSE MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: + print("SSE MCP server adapter was not connected. No stop needed or start failed.") + +``` + +## Considerações de Segurança para SSE + + +**Ataques de DNS Rebinding**: Transportes SSE podem ser vulneráveis a ataques de DNS rebinding se o servidor MCP não estiver devidamente protegido. Isso pode permitir que sites maliciosos interajam com servidores MCP locais ou da intranet. + + +Para mitigar esse risco: +- As implementações do servidor MCP devem **validar os cabeçalhos `Origin`** em conexões SSE recebidas. +- Ao rodar servidores MCP SSE locais para desenvolvimento, **faça o bind apenas em `localhost` (`127.0.0.1`)** ao invés de todas as interfaces de rede (`0.0.0.0`). +- Implemente **autenticação adequada** para todas as conexões SSE caso exponham ferramentas ou dados sensíveis. + +Para uma visão abrangente das melhores práticas de segurança, consulte nossa página de [Considerações de Segurança](./security.mdx) e a documentação oficial [MCP Transport Security](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations). \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/mcp/stdio.mdx b/docs/v1.15.13/pt-BR/mcp/stdio.mdx new file mode 100644 index 0000000000..e2b4adf8bd --- /dev/null +++ b/docs/v1.15.13/pt-BR/mcp/stdio.mdx @@ -0,0 +1,134 @@ +--- +title: Transporte Stdio +description: Aprenda como conectar o CrewAI a servidores MCP locais usando o mecanismo de transporte Stdio (Entrada/Saída Padrão). +icon: server +mode: "wide" +--- + +## Visão Geral + +O transporte Stdio (Entrada/Saída Padrão) é projetado para conectar o `MCPServerAdapter` a servidores MCP locais que se comunicam por meio de seus fluxos de entrada e saída padrão. Isso é normalmente utilizado quando o servidor MCP é um script ou executável rodando na mesma máquina da sua aplicação CrewAI. + +## Conceitos-Chave + +- **Execução Local**: O transporte Stdio gerencia um processo localmente em execução para o servidor MCP. +- **`StdioServerParameters`**: Esta classe da biblioteca `mcp` é usada para configurar o comando, argumentos e variáveis de ambiente para iniciar o servidor Stdio. + +## Conectando via Stdio + +Você pode se conectar a um servidor MCP baseado em Stdio usando duas abordagens principais para gerenciar o ciclo de vida da conexão: + +### 1. Conexão Totalmente Gerenciada (Recomendado) + +Usar um context manager do Python (declaração `with`) é a abordagem recomendada. Ela lida automaticamente com o início do processo do servidor MCP e sua finalização quando o contexto é encerrado. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters +import os + +# Criar um objeto StdioServerParameters +server_params=StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +with MCPServerAdapter(server_params) as tools: + print(f"Available tools from Stdio MCP server: {[tool.name for tool in tools]}") + + # Exemplo: Usando as ferramentas do servidor MCP Stdio em um Agente CrewAI + pesquisador_local = Agent( + role="Processador Local de Dados", + goal="Processar dados usando uma ferramenta local baseada em Stdio.", + backstory="Uma IA que utiliza scripts locais via MCP para tarefas especializadas.", + tools=tools, + reasoning=True, + verbose=True, + ) + + processing_task = Task( + description="Processar o arquivo de dados de entrada 'data.txt' e resumir seu conteúdo.", + expected_output="Um resumo dos dados processados.", + agent=pesquisador_local, + markdown=True + ) + + data_crew = Crew( + agents=[pesquisador_local], + tasks=[processing_task], + verbose=True, + process=Process.sequential + ) + + result = data_crew.kickoff() + print("\nCrew Task Result (Stdio - Managed):\n", result) + +``` + +### 2. Ciclo de Vida Manual da Conexão + +Se você precisa de um controle mais refinado sobre quando o processo do servidor MCP Stdio é iniciado e finalizado, pode gerenciar o ciclo de vida do `MCPServerAdapter` manualmente. + + +Você **DEVE** chamar `mcp_server_adapter.stop()` para garantir que o processo do servidor seja finalizado e os recursos, liberados. Recomenda-se fortemente o uso de um bloco `try...finally`. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter +from mcp import StdioServerParameters +import os + +# Criar um objeto StdioServerParameters +stdio_params=StdioServerParameters( + command="python3", + args=["servers/your_stdio_server.py"], + env={"UV_PYTHON": "3.12", **os.environ}, +) + +mcp_server_adapter = MCPServerAdapter(server_params=stdio_params) +try: + mcp_server_adapter.start() # Inicia manualmente a conexão e o processo do servidor + tools = mcp_server_adapter.tools + print(f"Available tools (manual Stdio): {[tool.name for tool in tools]}") + + # Exemplo: Usando as ferramentas com sua configuração de Agent, Task, Crew + manual_agent = Agent( + role="Executor Local de Tarefas", + goal="Executar uma tarefa local específica usando uma ferramenta Stdio gerenciada manualmente.", + backstory="Uma IA proficiente em controlar processos locais via MCP.", + tools=tools, + verbose=True + ) + + manual_task = Task( + description="Executar o comando 'perform_analysis' via ferramenta Stdio.", + expected_output="Resultados da análise.", + agent=manual_agent + ) + + manual_crew = Crew( + agents=[manual_agent], + tasks=[manual_task], + verbose=True, + process=Process.sequential + ) + + + result = manual_crew.kickoff() # As entradas reais dependem da sua ferramenta + print("\nCrew Task Result (Stdio - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual Stdio MCP integration: {e}") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: # Verifica se está conectado antes de parar + print("Stopping Stdio MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Assegure que stop seja chamado** + elif mcp_server_adapter: # Se o adaptador existe mas não está conectado (ex.: start falhou) + print("Stdio MCP server adapter was not connected. No stop needed or start failed.") + +``` + +Lembre-se de substituir caminhos e comandos de exemplo pelos detalhes reais do seu servidor Stdio. O parâmetro `env` em `StdioServerParameters` pode ser usado para definir variáveis de ambiente para o processo do servidor, o que pode ser útil para configurar seu comportamento ou fornecer caminhos necessários (como `PYTHONPATH`). \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/mcp/streamable-http.mdx b/docs/v1.15.13/pt-BR/mcp/streamable-http.mdx new file mode 100644 index 0000000000..7884968d7d --- /dev/null +++ b/docs/v1.15.13/pt-BR/mcp/streamable-http.mdx @@ -0,0 +1,136 @@ +--- +title: Transporte HTTP Streamable +description: Saiba como conectar o CrewAI a servidores MCP remotos usando o transporte HTTP Streamable flexível. +icon: globe +mode: "wide" +--- + +## Visão Geral + +O transporte HTTP Streamable oferece uma maneira flexível de se conectar a servidores MCP remotos. Ele é frequentemente baseado em HTTP e pode suportar vários padrões de comunicação, incluindo requisição-resposta e streaming, às vezes utilizando Server-Sent Events (SSE) para fluxos do servidor para o cliente dentro de uma interação HTTP mais ampla. + +## Conceitos-Chave + +- **Servidores Remotos**: Projetado para servidores MCP hospedados remotamente. +- **Flexibilidade**: Pode suportar padrões de interação mais complexos do que SSE puro, potencialmente incluindo comunicação bidirecional se o servidor implementá-la. +- **Configuração do `MCPServerAdapter`**: Você precisará fornecer a URL base do servidor para comunicação MCP e especificar `"streamable-http"` como o tipo de transporte. + +## Conectando via HTTP Streamable + +Você tem dois métodos principais para gerenciar o ciclo de vida da conexão com um servidor MCP HTTP Streamable: + +### 1. Conexão Totalmente Gerenciada (Recomendado) + +A abordagem recomendada é usar um gerenciador de contexto Python (`with` statement), que lida automaticamente com a configuração e encerramento da conexão. + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8001/mcp", # Replace with your actual Streamable HTTP server URL + "transport": "streamable-http" +} + +try: + with MCPServerAdapter(server_params) as tools: + print(f"Available tools from Streamable HTTP MCP server: {[tool.name for tool in tools]}") + + agente_http = Agent( + role="Integrador de Serviços HTTP", + goal="Utilizar ferramentas de um servidor MCP remoto via Streamable HTTP.", + backstory="Um agente de IA especializado em interagir com serviços web complexos.", + tools=tools, + verbose=True, + ) + + http_task = Task( + description="Realizar uma consulta de dados complexa usando uma ferramenta do servidor Streamable HTTP.", + expected_output="O resultado da consulta de dados complexa.", + agent=agente_http, + ) + + http_crew = Crew( + agents=[agente_http], + tasks=[http_task], + verbose=True, + process=Process.sequential + ) + + result = http_crew.kickoff() + print("\nCrew Task Result (Streamable HTTP - Managed):\n", result) + +except Exception as e: + print(f"Error connecting to or using Streamable HTTP MCP server (Managed): {e}") + print("Ensure the Streamable HTTP MCP server is running and accessible at the specified URL.") + +``` +**Nota:** Substitua `"http://localhost:8001/mcp"` pela URL real do seu servidor MCP HTTP Streamable. + +### 2. Ciclo de Vida da Conexão Manual + +Para cenários que exigem controle mais explícito, você pode gerenciar a conexão do `MCPServerAdapter` manualmente. + + +É **crítico** chamar `mcp_server_adapter.stop()` quando terminar para fechar a conexão e liberar recursos. Usar um bloco `try...finally` é a forma mais segura de garantir isso. + + +```python +from crewai import Agent, Task, Crew, Process +from crewai_tools import MCPServerAdapter + +server_params = { + "url": "http://localhost:8001/mcp", # Replace with your actual Streamable HTTP server URL + "transport": "streamable-http" +} + +mcp_server_adapter = None +try: + mcp_server_adapter = MCPServerAdapter(server_params) + mcp_server_adapter.start() + tools = mcp_server_adapter.tools + print(f"Available tools (manual Streamable HTTP): {[tool.name for tool in tools]}") + + manual_http_agent = Agent( + role="Usuário Avançado de Serviços Web", + goal="Interagir com um servidor MCP usando conexões HTTP Streamable gerenciadas manualmente.", + backstory="Um especialista em IA em ajustar integrações baseadas em HTTP.", + tools=tools, + verbose=True + ) + + data_processing_task = Task( + description="Enviar dados para processamento e recuperar resultados via Streamable HTTP.", + expected_output="Dados processados ou confirmação.", + agent=manual_http_agent + ) + + data_crew = Crew( + agents=[manual_http_agent], + tasks=[data_processing_task], + verbose=True, + process=Process.sequential + ) + + result = data_crew.kickoff() + print("\nCrew Task Result (Streamable HTTP - Manual):\n", result) + +except Exception as e: + print(f"An error occurred during manual Streamable HTTP MCP integration: {e}") + print("Ensure the Streamable HTTP MCP server is running and accessible.") +finally: + if mcp_server_adapter and mcp_server_adapter.is_connected: + print("Stopping Streamable HTTP MCP server connection (manual)...") + mcp_server_adapter.stop() # **Crucial: Ensure stop is called** + elif mcp_server_adapter: + print("Streamable HTTP MCP server adapter was not connected. No stop needed or start failed.") +``` + +## Considerações de Segurança + +Ao utilizar o transporte HTTP Streamable, as melhores práticas gerais de segurança web são fundamentais: +- **Use HTTPS**: Sempre prefira HTTPS (HTTP Seguro) para as URLs do seu servidor MCP para criptografar os dados em trânsito. +- **Autenticação**: Implemente mecanismos robustos de autenticação se seu servidor MCP expuser ferramentas ou dados sensíveis. +- **Validação de Entrada**: Garanta que seu servidor MCP valide todas as requisições e parâmetros recebidos. + +Para um guia abrangente sobre como proteger suas integrações MCP, consulte nossa página de [Considerações de Segurança](./security.mdx) e a documentação oficial de [Segurança em Transportes MCP](https://modelcontextprotocol.io/docs/concepts/transports#security-considerations). \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/arize-phoenix.mdx b/docs/v1.15.13/pt-BR/observability/arize-phoenix.mdx new file mode 100644 index 0000000000..df14020544 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/arize-phoenix.mdx @@ -0,0 +1,145 @@ +--- +title: Arize Phoenix +description: Integração do Arize Phoenix para CrewAI com OpenTelemetry e OpenInference +icon: magnifying-glass-chart +mode: "wide" +--- + +# Integração com Arize Phoenix + +Este guia demonstra como integrar o **Arize Phoenix** ao **CrewAI** usando o OpenTelemetry através do [OpenInference](https://github.com/openinference/openinference) SDK. Ao final deste guia, você será capaz de rastrear seus agentes CrewAI e depurá-los com facilidade. + +> **O que é o Arize Phoenix?** O [Arize Phoenix](https://phoenix.arize.com) é uma plataforma de observabilidade de LLM que oferece rastreamento e avaliação para aplicações de IA. + +[![Assista a um vídeo demonstrando a nossa integração com o Phoenix](https://storage.googleapis.com/arize-assets/fixtures/setup_crewai.png)](https://www.youtube.com/watch?v=Yc5q3l6F7Ww) + +## Primeiros Passos + +Vamos percorrer um exemplo simples de uso do CrewAI e integração com o Arize Phoenix via OpenTelemetry utilizando o OpenInference. + +Você também pode acessar este guia no [Google Colab](https://colab.research.google.com/github/Arize-ai/phoenix/blob/main/tutorials/tracing/crewai_tracing_tutorial.ipynb). + +### Passo 1: Instale as Dependências + +```bash +pip install openinference-instrumentation-crewai crewai crewai-tools arize-phoenix-otel +``` + +### Passo 2: Configure as Variáveis de Ambiente + +Configure as chaves de API do Phoenix Cloud e ajuste o OpenTelemetry para enviar rastros ao Phoenix. O Phoenix Cloud é uma versão hospedada do Arize Phoenix, mas não é obrigatório para utilizar esta integração. + +Você pode obter uma chave de API gratuita do Serper [aqui](https://serper.dev/). + +```python +import os +from getpass import getpass + +# Obtenha suas credenciais do Phoenix Cloud +PHOENIX_API_KEY = getpass("🔑 Digite sua Phoenix Cloud API Key: ") + +# Obtenha as chaves de API para os serviços +OPENAI_API_KEY = getpass("🔑 Digite sua OpenAI API key: ") +SERPER_API_KEY = getpass("🔑 Digite sua Serper API key: ") + +# Defina as variáveis de ambiente +os.environ["PHOENIX_CLIENT_HEADERS"] = f"api_key={PHOENIX_API_KEY}" +os.environ["PHOENIX_COLLECTOR_ENDPOINT"] = "https://app.phoenix.arize.com" # Phoenix Cloud, altere para seu endpoint se estiver utilizando uma instância self-hosted +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +os.environ["SERPER_API_KEY"] = SERPER_API_KEY +``` + +### Passo 3: Inicialize o OpenTelemetry com o Phoenix + +Inicialize o SDK de instrumentação OpenTelemetry do OpenInference para começar a capturar rastros e enviá-los ao Phoenix. + +```python +from phoenix.otel import register + +tracer_provider = register( + project_name="crewai-tracing-demo", + auto_instrument=True, +) +``` + +### Passo 4: Crie uma Aplicação CrewAI + +Vamos criar uma aplicação CrewAI em que dois agentes colaboram para pesquisar e escrever um post de blog sobre avanços em IA. + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool +from openinference.instrumentation.crewai import CrewAIInstrumentor +from phoenix.otel import register + +# configure o monitoramento para seu crew +tracer_provider = register( + endpoint="http://localhost:6006/v1/traces") +CrewAIInstrumentor().instrument(skip_dep_check=True, tracer_provider=tracer_provider) +search_tool = SerperDevTool() + +# Defina seus agentes com papéis e objetivos +pesquisador = Agent( + role="Analista Sênior de Pesquisa", + goal="Descobrir os avanços mais recentes em IA e ciência de dados", + backstory=""" +Você trabalha em um importante think tank de tecnologia. Sua especialidade é identificar tendências emergentes. Você tem habilidade para dissecar dados complexos e apresentar insights acionáveis. +""", + verbose=True, + allow_delegation=False, + tools=[search_tool], +) +writer = Agent( + role="Estrategista de Conteúdo Técnico", + goal="Criar conteúdo envolvente sobre avanços tecnológicos", + backstory="Você é um Estrategista de Conteúdo renomado, conhecido por seus artigos perspicazes e envolventes. Você transforma conceitos complexos em narrativas atraentes.", + verbose=True, + allow_delegation=True, +) + +# Crie tarefas para seus agentes +task1 = Task( + description="Realize uma análise abrangente dos avanços mais recentes em IA em 2024. Identifique tendências-chave, tecnologias inovadoras e impactos potenciais na indústria.", + expected_output="Relatório analítico completo em tópicos", + agent=pesquisador, +) + +task2 = Task( + description="Utilizando os insights fornecidos, desenvolva um blog envolvente destacando os avanços mais significativos em IA. O post deve ser informativo e acessível, voltado para um público técnico. Dê um tom interessante, evite palavras complexas para não soar como IA.", + expected_output="Post de blog completo com pelo menos 4 parágrafos", + agent=writer, +) + +# Instancie seu crew com um processo sequencial +crew = Crew( + agents=[pesquisador, writer], tasks=[task1, task2], verbose=1, process=Process.sequential +) + +# Coloque seu crew para trabalhar! +result = crew.kickoff() + +print("######################") +print(result) +``` + +### Passo 5: Visualize os Rastros no Phoenix + +Após executar o agente, você poderá visualizar os rastros gerados pela sua aplicação CrewAI no Phoenix. Você verá etapas detalhadas das interações dos agentes e chamadas de LLM, o que pode ajudar na depuração e otimização dos seus agentes de IA. + +Acesse sua conta Phoenix Cloud e navegue até o projeto que você especificou no parâmetro `project_name`. Você verá uma visualização de linha do tempo do seu rastro, incluindo todas as interações dos agentes, uso de ferramentas e chamadas LLM. + +![Exemplo de rastro no Phoenix mostrando interações de agentes](https://storage.googleapis.com/arize-assets/fixtures/crewai_traces.png) + + +### Informações de Compatibilidade de Versão +- Python 3.8+ +- CrewAI >= 0.86.0 +- Arize Phoenix >= 7.0.1 +- OpenTelemetry SDK >= 1.31.0 + + +### Referências +- [Documentação do Phoenix](https://docs.arize.com/phoenix/) - Visão geral da plataforma Phoenix. +- [Documentação do CrewAI](https://docs.crewai.com/) - Visão geral do framework CrewAI. +- [Documentação do OpenTelemetry](https://opentelemetry.io/docs/) - Guia do OpenTelemetry +- [OpenInference GitHub](https://github.com/openinference/openinference) - Código-fonte do SDK OpenInference. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/braintrust.mdx b/docs/v1.15.13/pt-BR/observability/braintrust.mdx new file mode 100644 index 0000000000..c0a19cfa3e --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/braintrust.mdx @@ -0,0 +1,237 @@ +--- +title: Braintrust +description: Integração do Braintrust para CrewAI com rastreamento OpenTelemetry e avaliação +icon: magnifying-glass-chart +mode: "wide" +--- + +# Integração Braintrust + +Este guia demonstra como integrar o **Braintrust** com **CrewAI** usando OpenTelemetry para rastreamento e avaliação abrangentes. Ao final deste guia, você poderá rastrear seus agentes CrewAI, monitorar seu desempenho e avaliar suas saídas usando a poderosa plataforma de observabilidade do Braintrust. + +> **O que é Braintrust?** [Braintrust](https://www.braintrust.dev) é uma plataforma de avaliação e observabilidade de IA que fornece rastreamento, avaliação e monitoramento abrangentes para aplicações de IA com rastreamento de experimentos e análises de desempenho integrados. + +## Começar + +Vamos percorrer um exemplo simples de uso do CrewAI e integração com Braintrust via OpenTelemetry para observabilidade e avaliação abrangentes. + +### Passo 1: Instalar Dependências + +```bash +uv add braintrust[otel] crewai crewai-tools opentelemetry-instrumentation-openai opentelemetry-instrumentation-crewai python-dotenv +``` + +### Passo 2: Configurar Variáveis de Ambiente + +Configure as chaves de API do Braintrust e configure o OpenTelemetry para enviar rastreamentos para o Braintrust. Você precisará de uma chave de API do Braintrust e sua chave de API do OpenAI. + +```python +import os +from getpass import getpass + +# Obter suas credenciais do Braintrust +BRAINTRUST_API_KEY = getpass("🔑 Digite sua Chave de API do Braintrust: ") + +# Obter chaves de API para serviços +OPENAI_API_KEY = getpass("🔑 Digite sua chave de API do OpenAI: ") + +# Configurar variáveis de ambiente +os.environ["BRAINTRUST_API_KEY"] = BRAINTRUST_API_KEY +os.environ["BRAINTRUST_PARENT"] = "project_name:crewai-demo" +os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY +``` + +### Passo 3: Inicializar OpenTelemetry com Braintrust + +Inicialize a instrumentação OpenTelemetry do Braintrust para começar a capturar rastreamentos e enviá-los para o Braintrust. + +```python +import os +from typing import Any, Dict + +from braintrust.otel import BraintrustSpanProcessor +from crewai import Agent, Crew, Task +from crewai.llm import LLM +from opentelemetry import trace +from opentelemetry.instrumentation.crewai import CrewAIInstrumentor +from opentelemetry.instrumentation.openai import OpenAIInstrumentor +from opentelemetry.sdk.trace import TracerProvider + +def setup_tracing() -> None: + """Configurar rastreamento OpenTelemetry com Braintrust.""" + current_provider = trace.get_tracer_provider() + if isinstance(current_provider, TracerProvider): + provider = current_provider + else: + provider = TracerProvider() + trace.set_tracer_provider(provider) + + provider.add_span_processor(BraintrustSpanProcessor()) + CrewAIInstrumentor().instrument(tracer_provider=provider) + OpenAIInstrumentor().instrument(tracer_provider=provider) + + +setup_tracing() +``` + +### Passo 4: Criar uma Aplicação CrewAI + +Vamos criar uma aplicação CrewAI onde dois agentes colaboram para pesquisar e escrever um post de blog sobre avanços em IA, com rastreamento abrangente habilitado. + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool + +def create_crew() -> Crew: + """Criar uma crew com múltiplos agentes para rastreamento abrangente.""" + llm = LLM(model="gpt-4o-mini") + search_tool = SerperDevTool() + + # Definir agentes com papéis específicos + researcher = Agent( + role="Analista de Pesquisa Sênior", + goal="Descobrir desenvolvimentos de ponta em IA e ciência de dados", + backstory="""Você trabalha em um think tank de tecnologia líder. + Sua especialidade está em identificar tendências emergentes. + Você tem talento para dissecar dados complexos e apresentar insights acionáveis.""", + verbose=True, + allow_delegation=False, + llm=llm, + tools=[search_tool], + ) + + writer = Agent( + role="Estrategista de Conteúdo Tecnológico", + goal="Criar conteúdo envolvente sobre avanços tecnológicos", + backstory="""Você é um Estrategista de Conteúdo renomado, conhecido por seus artigos perspicazes e envolventes. + Você transforma conceitos complexos em narrativas convincentes.""", + verbose=True, + allow_delegation=True, + llm=llm, + ) + + # Criar tarefas para seus agentes + research_task = Task( + description="""Realize uma análise abrangente dos últimos avanços em {topic}. + Identifique tendências principais, tecnologias revolucionárias e impactos potenciais na indústria.""", + expected_output="Relatório de análise completo em pontos de bala", + agent=researcher, + ) + + writing_task = Task( + description="""Usando os insights fornecidos, desenvolva um post de blog envolvente + que destaque os avanços mais significativos em {topic}. + Seu post deve ser informativo, mas acessível, atendendo a um público conhecedor de tecnologia. + Faça soar legal, evite palavras complexas para não soar como IA.""", + expected_output="Post de blog completo de pelo menos 4 parágrafos", + agent=writer, + context=[research_task], + ) + + # Instanciar sua crew com um processo sequencial + crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True, + process=Process.sequential + ) + + return crew + +def run_crew(): + """Executar a crew e retornar resultados.""" + crew = create_crew() + result = crew.kickoff(inputs={"topic": "desenvolvimentos em IA"}) + return result + +# Executar sua crew +if __name__ == "__main__": + # A instrumentação já foi inicializada acima neste módulo + result = run_crew() + print(result) +``` + +### Passo 5: Visualizar Rastreamentos no Braintrust + +Após executar sua crew, você pode visualizar rastreamentos abrangentes no Braintrust através de diferentes perspectivas: + + + + + Visualização de Rastreamento Braintrust + + + + + + Visualização de Linha do Tempo Braintrust + + + + + + Visualização de Thread Braintrust + + + + +### Passo 6: Avaliar via SDK (Experimentos) + +Você também pode executar avaliações usando o Eval SDK do Braintrust. Isso é útil para comparar versões ou pontuar saídas offline. Abaixo está um exemplo em Python usando a classe `Eval` com a crew que criamos acima: + +```python +# eval_crew.py +from braintrust import Eval +from autoevals import Levenshtein + +def evaluate_crew_task(input_data): + """Função de tarefa que envolve nossa crew para avaliação.""" + crew = create_crew() + result = crew.kickoff(inputs={"topic": input_data["topic"]}) + return str(result) + +Eval( + "Crew de Pesquisa em IA", # Nome do projeto + { + "data": lambda: [ + {"topic": "tendências de inteligência artificial 2024"}, + {"topic": "avanços em aprendizado de máquina"}, + {"topic": "ética e governança de IA"}, + ], + "task": evaluate_crew_task, + "scores": [Levenshtein], + }, +) +``` + +Configure sua chave de API e execute: + +```bash +export BRAINTRUST_API_KEY="YOUR_API_KEY" +braintrust eval eval_crew.py +``` + +Veja o [guia do Eval SDK do Braintrust](https://www.braintrust.dev/docs/start/eval-sdk) para mais detalhes. + +### Principais Recursos da Integração Braintrust + +- **Rastreamento Abrangente**: Rastreie todas as interações de agentes, uso de ferramentas e chamadas LLM +- **Monitoramento de Desempenho**: Monitore tempos de execução, uso de tokens e taxas de sucesso +- **Rastreamento de Experimentos**: Compare diferentes configurações de crew e modelos +- **Avaliação Automatizada**: Configure métricas de avaliação personalizadas para saídas de crew +- **Rastreamento de Erros**: Monitore e depure falhas em suas execuções de crew +- **Análise de Custos**: Rastreie uso de tokens e custos associados + +### Informações de Compatibilidade de Versão +- Python 3.8+ +- CrewAI >= 0.86.0 +- Braintrust >= 0.1.0 +- OpenTelemetry SDK >= 1.31.0 + +### Referências +- [Documentação Braintrust](https://www.braintrust.dev/docs) - Visão geral da plataforma Braintrust +- [Integração CrewAI Braintrust](https://www.braintrust.dev/docs/integrations/crew-ai) - Guia oficial de integração CrewAI +- [Eval SDK Braintrust](https://www.braintrust.dev/docs/start/eval-sdk) - Execute experimentos via SDK +- [Documentação CrewAI](https://docs.crewai.com/) - Visão geral do framework CrewAI +- [Documentação OpenTelemetry](https://opentelemetry.io/docs/) - Guia OpenTelemetry +- [GitHub Braintrust](https://github.com/braintrustdata/braintrust) - Código fonte do SDK Braintrust diff --git a/docs/v1.15.13/pt-BR/observability/datadog.mdx b/docs/v1.15.13/pt-BR/observability/datadog.mdx new file mode 100644 index 0000000000..a357fea83c --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/datadog.mdx @@ -0,0 +1,108 @@ +--- +title: Integração Datadog +description: Saiba como integrar o Datadog com o CrewAI para enviar os rastros de observabilidade do LLM para o Datadog. +icon: dog +mode: "wide" +--- + +# Integrar o Datadog com a CrewAI + +Este guia demonstrará como integrar o **Datadog** com o **CrewAI** usando a instrumentação automática do Datadog. Ao final deste guia, você poderá enviar rastreamentos do LLM Observability para o Datadog e visualizar as execuções do agente CrewAI no Agentic Execution View do Datadog LLM Observability. + +## O que é o Datadog LLM Observability? + +O [Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/) ajuda os engenheiros de IA, cientistas de dados e desenvolvedores de aplicativos a desenvolver, avaliar e monitorar rapidamente os aplicativos LLM. Melhore com confiança a qualidade dos resultados, o desempenho, os custos e o risco geral com experimentos estruturados, rastreamento de ponta a ponta em agentes de IA e avaliações. + +## Primeiros passos + +### Instalar dependências + +```shell +pip install ddtrace crewai crewai-tools +``` + +### Definir variáveis de ambiente + +Se você não tiver uma chave de API da Datadog, poderá [criar uma conta](https://www.datadoghq.com/) e [obter sua chave de API](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys). + +Você também precisará especificar um nome de aplicativo de ML nas seguintes variáveis de ambiente. Um aplicativo de ML é um agrupamento de rastros de observabilidade do LLM associados a um aplicativo específico baseado em LLM. Consulte [ML Application Naming Guidelines](https://docs.datadoghq.com/llm_observability/instrumentation/sdk?tab=python#application-naming-guidelines) para obter mais informações sobre as limitações dos nomes de aplicativos do ML. + +```shell +export DD_API_KEY= +export DD_SITE= +export DD_LLMOBS_ENABLED=true +export DD_LLMOBS_ML_APP= +export DD_LLMOBS_AGENTLESS_ENABLED=true +export DD_APM_TRACING_ENABLED=false +``` + +Além disso, configure todas as chaves de API do provedor LLM + +```shell +export OPENAI_API_KEY= +export ANTHROPIC_API_KEY= +export GEMINI_API_KEY= +... +``` + +### Criar um aplicativo agente CrewAI + +```python +# crewai_agent.py +from crewai import Agent, Task, Crew + +from crewai_tools import ( + WebsiteSearchTool +) + +web_rag_tool = WebsiteSearchTool() + +writer = Agent( + role="Writer", + goal="Você torna a matemática envolvente e compreensível para crianças pequenas por meio da poesia", + backstory="Você é um especialista em escrever haikus, mas não sabe nada de matemática", + tools=[web_rag_tool], +) + +task = Task( + description=("O que é {multiplicação}?"), + expected_output=("Componha um haicai que inclua a resposta."), + agent=writer +) + +crew = Crew( + agents=[writer], + tasks=[task], + share_crew=False +) + +output = crew.kickoff(dict(multiplicação="2 * 2")) +``` + +### Executar o aplicativo com a instrumentação automática do Datadog + +Com as [variáveis de ambiente](#definir-variáveis-de-ambiente) definidas, agora você pode executar o aplicativo com a instrumentação automática do Datadog. + +```shell +ddtrace-run python crewai_agent.py +``` + +### Visualizar os rastros no Datadog + +Depois de executar o aplicativo, você pode visualizar os traços na [Datadog LLM Observability's Traces View](https://app.datadoghq.com/llm/traces), selecionando o nome do aplicativo de ML que você escolheu no menu suspenso superior esquerdo. + +Ao clicar em um rastreamento, você verá os detalhes do rastreamento, incluindo o total de tokens usados, o número de chamadas LLM, os modelos usados e o custo estimado. Clicar em um intervalo específico reduzirá esses detalhes e mostrará a entrada, a saída e os metadados relacionados. + + +Visualização do rastreamento de observabilidade do Datadog LLM + +Além disso, você pode visualizar a visualização do gráfico de execução do rastreamento, que mostra o controle e o fluxo de dados do rastreamento, que será dimensionado com agentes maiores para mostrar transferências e relacionamentos entre chamadas LLM, chamadas de ferramentas e interações de agentes. + + +Visualização do fluxo de execução do agente de observabilidade do Datadog LLM + + +## Referências + +- [Datadog LLM Observability](https://www.datadoghq.com/product/llm-observability/) +- [Datadog LLM Observability CrewAI Auto-Instrumentation](https://docs.datadoghq.com/llm_observability/instrumentation/auto_instrumentation?tab=python#crew-ai) diff --git a/docs/v1.15.13/pt-BR/observability/galileo.mdx b/docs/v1.15.13/pt-BR/observability/galileo.mdx new file mode 100644 index 0000000000..4296e35fb9 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/galileo.mdx @@ -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. + +![Galileo trace view](/images/galileo-trace-veiw.png) + +## 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). diff --git a/docs/v1.15.13/pt-BR/observability/langdb.mdx b/docs/v1.15.13/pt-BR/observability/langdb.mdx new file mode 100644 index 0000000000..86b2aea826 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/langdb.mdx @@ -0,0 +1,287 @@ +--- +title: Integração LangDB +description: Governe, proteja e otimize seus fluxos de trabalho CrewAI com LangDB AI Gateway—acesse mais de 350 modelos, roteamento automático, otimização de custos e observabilidade completa. +icon: database +mode: "wide" +--- + +# Introdução + +[LangDB AI Gateway](https://langdb.ai) fornece APIs compatíveis com OpenAI para conectar com múltiplos Modelos de Linguagem Grandes e serve como uma plataforma de observabilidade que torna effortless rastrear fluxos de trabalho CrewAI de ponta a ponta, proporcionando acesso a mais de 350 modelos de linguagem. Com uma única chamada `init()`, todas as interações de agentes, execuções de tarefas e chamadas LLM são capturadas, fornecendo observabilidade abrangente e infraestrutura de IA pronta para produção para suas aplicações. + + + Exemplo de rastreamento CrewAI LangDB + + +**Confira:** [Ver o exemplo de trace ao vivo](https://app.langdb.ai/sharing/threads/3becbfed-a1be-ae84-ea3c-4942867a3e22) + +## Recursos + +### Capacidades do AI Gateway +- **Acesso a mais de 350 LLMs**: Conecte-se a todos os principais modelos de linguagem através de uma única integração +- **Modelos Virtuais**: Crie configurações de modelo personalizadas com parâmetros específicos e regras de roteamento +- **MCP Virtual**: Habilite compatibilidade e integração com sistemas MCP (Model Context Protocol) para comunicação aprimorada de agentes +- **Guardrails**: Implemente medidas de segurança e controles de conformidade para comportamento de agentes + +### Observabilidade e Rastreamento +- **Rastreamento Automático**: Uma única chamada `init()` captura todas as interações CrewAI +- **Visibilidade Ponta a Ponta**: Monitore fluxos de trabalho de agentes do início ao fim +- **Rastreamento de Uso de Ferramentas**: Rastreie quais ferramentas os agentes usam e seus resultados +- **Monitoramento de Chamadas de Modelo**: Insights detalhados sobre interações LLM +- **Análise de Performance**: Monitore latência, uso de tokens e custos +- **Suporte a Depuração**: Execução passo a passo para solução de problemas +- **Monitoramento em Tempo Real**: Dashboard de traces e métricas ao vivo + +## Instruções de Configuração + + + + Instale o cliente LangDB com flag de recurso CrewAI: + ```bash + pip install 'pylangdb[crewai]' + ``` + + + Configure suas credenciais LangDB: + ```bash + export LANGDB_API_KEY="" + export LANGDB_PROJECT_ID="" + export LANGDB_API_BASE_URL='https://api.us-east-1.langdb.ai' + ``` + + + Importe e inicialize LangDB antes de configurar seu código CrewAI: + ```python + from pylangdb.crewai import init + # Inicializar LangDB + init() + ``` + + + Configure seu LLM com cabeçalhos LangDB: + ```python + from crewai import Agent, Task, Crew, LLM + import os + + # Configurar LLM com cabeçalhos LangDB + llm = LLM( + model="openai/gpt-4o", # Substitua pelo modelo que você quer usar + api_key=os.getenv("LANGDB_API_KEY"), + base_url=os.getenv("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.getenv("LANGDB_PROJECT_ID")} + ) + ``` + + + +## Exemplo de Início Rápido + +Aqui está um exemplo simples para começar com LangDB e CrewAI: + +```python +import os +from pylangdb.crewai import init +from crewai import Agent, Task, Crew, LLM + +# Inicializar LangDB antes de qualquer importação CrewAI +init() + +def create_llm(model): + return LLM( + model=model, + api_key=os.environ.get("LANGDB_API_KEY"), + base_url=os.environ.get("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.environ.get("LANGDB_PROJECT_ID")} + ) + +# Defina seu agente +researcher = Agent( + role="Especialista em Pesquisa", + goal="Pesquisar tópicos minuciosamente", + backstory="Pesquisador especialista com habilidades em encontrar informações", + llm=create_llm("openai/gpt-4o"), # Substitua pelo modelo que você quer usar + verbose=True +) + +# Criar uma tarefa +task = Task( + description="Pesquise o tópico dado e forneça um resumo abrangente", + agent=researcher, + expected_output="Resumo de pesquisa detalhado com principais descobertas" +) + +# Criar e executar a equipe +crew = Crew(agents=[researcher], tasks=[task]) +result = crew.kickoff() +print(result) +``` + +## Exemplo Completo: Agente de Pesquisa e Planejamento + +Este exemplo abrangente demonstra um fluxo de trabalho multi-agente com capacidades de pesquisa e planejamento. + +### Pré-requisitos + +```bash +pip install crewai 'pylangdb[crewai]' crewai_tools setuptools python-dotenv +``` + +### Configuração do Ambiente + +```bash +# Credenciais LangDB +export LANGDB_API_KEY="" +export LANGDB_PROJECT_ID="" +export LANGDB_API_BASE_URL='https://api.us-east-1.langdb.ai' + +# Chaves API adicionais (opcional) +export SERPER_API_KEY="" # Para capacidades de busca na web +``` + +### Implementação Completa + +```python +#!/usr/bin/env python3 + +import os +import sys +from pylangdb.crewai import init +init() # Inicializar LangDB antes de qualquer importação CrewAI +from dotenv import load_dotenv +from crewai import Agent, Task, Crew, Process, LLM +from crewai_tools import SerperDevTool + +load_dotenv() + +def create_llm(model): + return LLM( + model=model, + api_key=os.environ.get("LANGDB_API_KEY"), + base_url=os.environ.get("LANGDB_API_BASE_URL"), + extra_headers={"x-project-id": os.environ.get("LANGDB_PROJECT_ID")} + ) + +class ResearchPlanningCrew: + def researcher(self) -> Agent: + return Agent( + role="Especialista em Pesquisa", + goal="Pesquisar tópicos minuciosamente e compilar informações abrangentes", + backstory="Pesquisador especialista com habilidades em encontrar e analisar informações de várias fontes", + tools=[SerperDevTool()], + llm=create_llm("openai/gpt-4o"), + verbose=True + ) + + def planner(self) -> Agent: + return Agent( + role="Planejador Estratégico", + goal="Criar planos acionáveis baseados em descobertas de pesquisa", + backstory="Planejador estratégico que divide desafios complexos em planos executáveis", + reasoning=True, + max_reasoning_attempts=3, + llm=create_llm("openai/anthropic/claude-3.7-sonnet"), + verbose=True + ) + + def research_task(self) -> Task: + return Task( + description="Pesquise o tópico minuciosamente e compile informações abrangentes", + agent=self.researcher(), + expected_output="Relatório de pesquisa abrangente com principais descobertas e insights" + ) + + def planning_task(self) -> Task: + return Task( + description="Crie um plano estratégico baseado nas descobertas da pesquisa", + agent=self.planner(), + expected_output="Plano de execução estratégica com fases, objetivos e etapas acionáveis", + context=[self.research_task()] + ) + + def crew(self) -> Crew: + return Crew( + agents=[self.researcher(), self.planner()], + tasks=[self.research_task(), self.planning_task()], + verbose=True, + process=Process.sequential + ) + +def main(): + topic = sys.argv[1] if len(sys.argv) > 1 else "Inteligência Artificial na Saúde" + + crew_instance = ResearchPlanningCrew() + + # Atualizar descrições de tarefas com o tópico específico + crew_instance.research_task().description = f"Pesquise {topic} minuciosamente e compile informações abrangentes" + crew_instance.planning_task().description = f"Crie um plano estratégico para {topic} baseado nas descobertas da pesquisa" + + result = crew_instance.crew().kickoff() + print(result) + +if __name__ == "__main__": + main() +``` + +### Executando o Exemplo + +```bash +python main.py "Soluções de Energia Sustentável" +``` + +## Visualizando Traces no LangDB + +Após executar sua aplicação CrewAI, você pode visualizar traces detalhados no dashboard LangDB: + + + Dashboard de trace LangDB mostrando fluxo de trabalho CrewAI + + +### O Que Você Verá + +- **Interações de Agentes**: Fluxo completo de conversas de agentes e transferências de tarefas +- **Uso de Ferramentas**: Quais ferramentas foram chamadas, suas entradas e saídas +- **Chamadas de Modelo**: Interações LLM detalhadas com prompts e respostas +- **Métricas de Performance**: Rastreamento de latência, uso de tokens e custos +- **Linha do Tempo de Execução**: Visualização passo a passo de todo o fluxo de trabalho + + +## Solução de Problemas + +### Problemas Comuns + +- **Nenhum trace aparecendo**: Certifique-se de que `init()` seja chamado antes de qualquer importação CrewAI +- **Erros de autenticação**: Verifique sua chave API LangDB e ID do projeto + + +## Recursos + + + + Documentação oficial e guias LangDB + + + Tutoriais passo a passo para construir agentes de IA + + + Exemplos completos de integração CrewAI + + + Acesse seus traces e análises + + + Navegue por mais de 350 modelos de linguagem disponíveis + + + Opções auto-hospedadas e capacidades empresariais + + + +## Próximos Passos + +Este guia cobriu o básico da integração do LangDB AI Gateway com CrewAI. Para aprimorar ainda mais seus fluxos de trabalho de IA, explore: + +- **Modelos Virtuais**: Crie configurações de modelo personalizadas com estratégias de roteamento +- **Guardrails e Segurança**: Implemente filtragem de conteúdo e controles de conformidade +- **Implantação em Produção**: Configure fallbacks, tentativas e balanceamento de carga + +Para recursos mais avançados e casos de uso, visite a [Documentação LangDB](https://docs.langdb.ai) ou explore o [Catálogo de Modelos](https://app.langdb.ai/models) para descobrir todos os modelos disponíveis. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/langfuse.mdx b/docs/v1.15.13/pt-BR/observability/langfuse.mdx new file mode 100644 index 0000000000..5381a9e96c --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/langfuse.mdx @@ -0,0 +1,108 @@ +--- +title: Integração Langfuse +description: Saiba como integrar o Langfuse ao CrewAI via OpenTelemetry usando OpenLit +icon: vials +mode: "wide" +--- + +# Integre o Langfuse ao CrewAI + +Este notebook demonstra como integrar o **Langfuse** ao **CrewAI** usando OpenTelemetry via o SDK **OpenLit**. Ao final deste notebook, você será capaz de rastrear suas aplicações CrewAI com o Langfuse para melhorar a observabilidade e a depuração. + +> **O que é Langfuse?** [Langfuse](https://langfuse.com) é uma plataforma open-source de engenharia LLM. Ela fornece recursos de rastreamento e monitoramento para aplicações LLM, ajudando desenvolvedores a depurar, analisar e otimizar seus sistemas de IA. O Langfuse se integra com várias ferramentas e frameworks através de integrações nativas, OpenTelemetry e APIs/SDKs. + +[![Vídeo de Visão Geral do Langfuse](https://github.com/user-attachments/assets/3926b288-ff61-4b95-8aa1-45d041c70866)](https://langfuse.com/watch-demo) + +## Primeiros Passos + +Vamos passar por um exemplo simples usando CrewAI e integrando ao Langfuse via OpenTelemetry utilizando o OpenLit. + +### Passo 1: Instale as Dependências + +```python +%pip install langfuse openlit crewai crewai_tools +``` + +### Passo 2: Configure as Variáveis de Ambiente + +Defina suas chaves de API do Langfuse e configure as opções de exportação do OpenTelemetry para enviar os traces ao Langfuse. Consulte a [Documentação Langfuse OpenTelemetry](https://langfuse.com/docs/opentelemetry/get-started) para mais informações sobre o endpoint Langfuse OpenTelemetry `/api/public/otel` e autenticação. + +```python +import os + +# Obtenha as chaves do seu projeto na página de configurações do projeto: https://cloud.langfuse.com +os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..." +os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..." +os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # 🇪🇺 Região UE +# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # 🇺🇸 Região EUA + + +# Sua chave OpenAI +os.environ["OPENAI_API_KEY"] = "sk-proj-..." +``` +Com as variáveis de ambiente configuradas, agora podemos inicializar o cliente Langfuse. A função get_client() inicializa o cliente Langfuse usando as credenciais fornecidas nas variáveis de ambiente. + +```python +from langfuse import get_client + +langfuse = get_client() + +# Verificar conexão +if langfuse.auth_check(): + print("Cliente Langfuse autenticado e pronto!") +else: + print("Falha na autenticação. Verifique suas credenciais e host.") +``` + +### Passo 3: Inicialize o OpenLit + +Inicialize o SDK de instrumentação OpenTelemetry do OpenLit para começar a capturar traces do OpenTelemetry. + +```python +import openlit + +openlit.init() +``` + +### Passo 4: Crie uma Aplicação Simples CrewAI + +Vamos criar uma aplicação simples CrewAI onde múltiplos agentes colaboram para responder à pergunta de um usuário. + +```python +from crewai import Agent, Task, Crew + +from crewai_tools import ( + WebsiteSearchTool +) + +web_rag_tool = WebsiteSearchTool() + +escritor = Agent( + role="Escritor", + goal="Você torna a matemática envolvente e compreensível para crianças pequenas através de poesias", + backstory="Você é especialista em escrever haicais mas não sabe nada de matemática.", + tools=[web_rag_tool], +) + +tarefa = Task(description=("O que é {multiplicação}?"), + expected_output=("Componha um haicai que inclua a resposta."), + agent=escritor) + +equipe = Crew( + agents=[escritor], + tasks=[tarefa], + share_crew=False +) +``` + +### Passo 5: Veja os Traces no Langfuse + +Após rodar o agente, você pode visualizar os traces gerados pela sua aplicação CrewAI no [Langfuse](https://cloud.langfuse.com). Você verá etapas detalhadas das interações do LLM, o que pode ajudar na depuração e otimização do seu agente de IA. + +![Exemplo de trace CrewAI no Langfuse](https://langfuse.com/images/cookbook/integration_crewai/crewai-example-trace.png) + +_[Exemplo público de trace no Langfuse](https://cloud.langfuse.com/project/cloramnkj0002jz088vzn1ja4/traces/e2cf380ffc8d47d28da98f136140642b?timestamp=2025-02-05T15%3A12%3A02.717Z&observation=3b32338ee6a5d9af)_ + +## Referências + +- [Documentação Langfuse OpenTelemetry](https://langfuse.com/docs/opentelemetry/get-started) \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/langtrace.mdx b/docs/v1.15.13/pt-BR/observability/langtrace.mdx new file mode 100644 index 0000000000..470c429338 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/langtrace.mdx @@ -0,0 +1,73 @@ +--- +title: Integração com Langtrace +description: Como monitorar custo, latência e desempenho dos Agentes CrewAI usando o Langtrace, uma ferramenta externa de observabilidade. +icon: chart-line +mode: "wide" +--- + +# Visão Geral do Langtrace + +O Langtrace é uma ferramenta externa e open-source que auxilia na configuração de observabilidade e avaliações para Modelos de Linguagem de Grande Porte (LLMs), frameworks de LLM e Bancos de Dados Vetoriais. +Apesar de não ser integrado diretamente ao CrewAI, o Langtrace pode ser utilizado em conjunto com o CrewAI para fornecer uma visibilidade aprofundada sobre o custo, latência e desempenho dos seus Agentes CrewAI. +Essa integração permite o registro de hiperparâmetros, o monitoramento de regressões de desempenho e o estabelecimento de um processo de melhoria contínua dos seus Agentes. + +![Visão geral de uma seleção de execuções de sessões de agentes](/images/langtrace1.png) +![Visão geral dos traces de agentes](/images/langtrace2.png) +![Visão detalhada dos traces de LLM](/images/langtrace3.png) + +## Instruções de Configuração + + + + Cadastre-se acessando [https://langtrace.ai/signup](https://langtrace.ai/signup). + + + Defina o tipo do projeto como `CrewAI` e gere uma chave de API. + + + Use o seguinte comando: + + ```bash + pip install langtrace-python-sdk + ``` + + + Importe e inicialize o Langtrace no início do seu script, antes de quaisquer imports do CrewAI: + + ```python + from langtrace_python_sdk import langtrace + langtrace.init(api_key='') + + # Agora importe os módulos do CrewAI + from crewai import Agent, Task, Crew + ``` + + + +### Funcionalidades e Sua Aplicação no CrewAI + +1. **Rastreamento de Token e Custo do LLM** + + - Monitore o uso de tokens e os custos associados para cada interação dos agentes CrewAI. + +2. **Gráfico de Trace para Etapas de Execução** + + - Visualize o fluxo de execução das suas tarefas CrewAI, incluindo latência e logs. + - Útil para identificar gargalos nos fluxos de trabalho dos seus agentes. + +3. **Curadoria de Dataset com Anotação Manual** + + - Crie conjuntos de dados a partir das saídas das suas tarefas CrewAI para futuros treinamentos ou avaliações. + +4. **Versionamento e Gerenciamento de Prompt** + + - Acompanhe as diferentes versões de prompts utilizados em seus agentes CrewAI. + - Útil para testes A/B e otimização de desempenho dos agentes. + +5. **Playground de Prompt com Comparações de Modelos** + + - Teste e compare diferentes prompts e modelos para seus agentes CrewAI antes da implantação. + +6. **Testes e Avaliações** + + - Configure testes automatizados para seus agentes e tarefas CrewAI. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/maxim.mdx b/docs/v1.15.13/pt-BR/observability/maxim.mdx new file mode 100644 index 0000000000..d3b121813b --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/maxim.mdx @@ -0,0 +1,149 @@ +--- +title: Integração Maxim +description: Inicie o monitoramento, avaliação e observabilidade de agentes +icon: bars-staggered +mode: "wide" +--- + +# Integração Maxim + +Maxim AI oferece monitoramento completo de agentes, avaliação e observabilidade para suas aplicações CrewAI. Com a integração de uma linha do Maxim, você pode facilmente rastrear e analisar interações dos agentes, métricas de desempenho e muito mais. + +## Funcionalidades: Integração com Uma Linha + +- **Rastreamento de Agentes de Ponta a Ponta**: Monitore todo o ciclo de vida dos seus agentes +- **Análise de Desempenho**: Acompanhe latência, tokens consumidos e custos +- **Monitoramento de Hiperparâmetros**: Visualize detalhes de configuração das execuções dos agentes +- **Rastreamento de Chamadas de Ferramentas**: Observe quando e como os agentes usam suas ferramentas +- **Visualização Avançada**: Entenda as trajetórias dos agentes através de dashboards intuitivos + +## Começando + +### Pré-requisitos + +- Python versão >=3.10 +- Uma conta Maxim ([cadastre-se aqui](https://getmaxim.ai/)) +- Um projeto CrewAI + +### Instalação + +Instale o SDK do Maxim via pip: + +```python +pip install maxim-py>=3.6.2 +``` + +Ou adicione ao seu `requirements.txt`: + +``` +maxim-py>=3.6.2 +``` + +### Configuração Básica + +### 1. Configure as variáveis de ambiente + +```python +### Configuração de Variáveis de Ambiente + +# Crie um arquivo `.env` na raiz do seu projeto: + +# Configuração da API Maxim +MAXIM_API_KEY=your_api_key_here +MAXIM_LOG_REPO_ID=your_repo_id_here +``` + +### 2. Importe os pacotes necessários + +```python +from crewai import Agent, Task, Crew, Process +from maxim import Maxim +from maxim.logger.crewai import instrument_crewai +``` + +### 3. Inicialize o Maxim com sua chave de API + +```python +# Inicialize o logger do Maxim +logger = Maxim().logger() + +# Instrumente o CrewAI com apenas uma linha +instrument_crewai(logger) +``` + +### 4. Crie e execute sua aplicação CrewAI normalmente + +```python +pesquisador = Agent( + role='Pesquisador Sênior', + goal='Descobrir os avanços mais recentes em IA', + backstory="Você é um pesquisador especialista em um think tank de tecnologia...", + verbose=True, + llm=llm +) + +# Defina a tarefa +research_task = Task( + description="Pesquise os avanços mais recentes em IA...", + expected_output="", + agent=pesquisador +) + +# Configure e execute a crew +crew = Crew( + agents=[pesquisador], + tasks=[research_task], + verbose=True +) + +try: + result = crew.kickoff() +finally: + maxim.cleanup() # Garanta o cleanup mesmo em caso de erros +``` + +É isso! Todas as interações dos seus agentes CrewAI agora serão registradas e estarão disponíveis em seu painel Maxim. + +Confira este Google Colab Notebook para referência rápida – [Notebook](https://colab.research.google.com/drive/1ZKIZWsmgQQ46n8TH9zLsT1negKkJA6K8?usp=sharing) + +## Visualizando Seus Rastreamentos + +Após executar sua aplicação CrewAI: + +![Exemplo de rastreamento no Maxim mostrando interações de agentes](https://raw.githubusercontent.com/maximhq/maxim-docs/master/images/Screenshot2025-05-14at12.10.58PM.png) + +1. Faça login no seu [Painel Maxim](https://getmaxim.ai/dashboard) +2. Navegue até seu repositório +3. Visualize rastreamentos detalhados de agentes, incluindo: + - Conversas dos agentes + - Padrões de uso de ferramentas + - Métricas de desempenho + - Análises de custos + +## Solução de Problemas + +### Problemas Comuns + +- **Nenhum rastreamento aparecendo**: Certifique-se de que sua chave de API e o ID do repositório estão corretos +- Certifique-se de que você **chamou `instrument_crewai()`** ***antes*** de executar sua crew. Isso inicializa corretamente os hooks de logging. +- Defina `debug=True` na chamada do `instrument_crewai()` para expor erros internos: + + ```python + instrument_crewai(logger, debug=True) + ``` + +- Configure seus agentes com `verbose=True` para capturar logs detalhados: + + ```python + + agent = CrewAgent(..., verbose=True) + ``` + +- Verifique cuidadosamente se `instrument_crewai()` foi chamado **antes** de criar ou executar agentes. Isso pode parecer óbvio, mas é um erro comum. + +### Suporte + +Se você encontrar algum problema: + +- Consulte a [Documentação do Maxim](https://getmaxim.ai/docs) +- Maxim Github [Link](https://github.com/maximhq) \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/mlflow.mdx b/docs/v1.15.13/pt-BR/observability/mlflow.mdx new file mode 100644 index 0000000000..83a89c0f07 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/mlflow.mdx @@ -0,0 +1,186 @@ +--- +title: Integração com MLflow +description: Comece rapidamente a monitorar seus Agents com MLflow. +icon: bars-staggered +mode: "wide" +--- + +# Visão Geral do MLflow + +[MLflow](https://mlflow.org/) é uma plataforma open-source que auxilia profissionais e equipes de machine learning a lidar com as complexidades do processo de aprendizagem de máquina. + +Ela oferece um recurso de tracing que aprimora a observabilidade de LLMs em suas aplicações de IA Generativa, capturando informações detalhadas sobre a execução dos serviços de sua aplicação. +O tracing fornece uma forma de registrar os inputs, outputs e metadados associados a cada etapa intermediária de uma requisição, permitindo que você identifique facilmente a origem de bugs e comportamentos inesperados. + +![Visão geral do uso de tracing MLflow com crewAI](/images/mlflow-tracing.gif) + +### Funcionalidades + +- **Painel de Tracing**: Monitore as atividades dos seus agentes crewAI com painéis detalhados que incluem entradas, saídas e metadados dos spans. +- **Tracing Automatizado**: Uma integração totalmente automatizada com crewAI, que pode ser habilitada executando `mlflow.crewai.autolog()`. +- **Instrumentação Manual de Tracing com pouco esforço**: Personalize a instrumentação dos traces usando as APIs de alto nível do MLflow, como decorators, wrappers de funções e context managers. +- **Compatibilidade com OpenTelemetry**: O MLflow Tracing suporta a exportação de traces para um OpenTelemetry Collector, que pode então ser usado para exportar traces para diversos backends como Jaeger, Zipkin e AWS X-Ray. +- **Empacote e Faça Deploy dos Agents**: Empacote e faça deploy de seus agents crewAI em um servidor de inferência com diversas opções de destino. +- **Hospede LLMs com Segurança**: Hospede múltiplos LLMs de vários provedores em um endpoint unificado através do gateway do MFflow. +- **Avaliação**: Avalie seus agents crewAI com uma ampla variedade de métricas utilizando a API conveniente `mlflow.evaluate()`. + +## Instruções de Configuração + + + + ```shell + # A integração crewAI está disponível no mlflow>=2.19.0 + pip install mlflow + ``` + + + ```shell + # Este processo é opcional, mas é recomendado utilizar o servidor de tracking do MLflow para melhor visualização e mais funcionalidades. + mlflow server + ``` + + + Adicione as duas linhas a seguir ao código da sua aplicação: + + ```python + import mlflow + + mlflow.crewai.autolog() + + # Opcional: Defina uma tracking URI e um nome de experimento caso utilize um servidor de tracking + mlflow.set_tracking_uri("http://localhost:5000") + mlflow.set_experiment("CrewAI") + ``` + + Exemplo de uso para tracing de Agents do CrewAI: + + ```python + from crewai import Agent, Crew, Task + from crewai.knowledge.source.string_knowledge_source import StringKnowledgeSource + from crewai_tools import SerperDevTool, WebsiteSearchTool + + from textwrap import dedent + + content = "Users name is John. He is 30 years old and lives in San Francisco." + string_source = StringKnowledgeSource( + content=content, metadata={"preference": "personal"} + ) + + search_tool = WebsiteSearchTool() + + + class TripAgents: + def city_selection_agent(self): + especialista_cidades = Agent( + role="Especialista em Seleção de Cidades", + goal="Selecionar a melhor cidade com base no clima, estação e preços", + backstory="Especialista em analisar dados de viagem para escolher destinos ideais", + tools=[search_tool], + verbose=True, + ) + + def local_expert(self): + especialista_local = Agent( + role="Especialista Local nesta cidade", + goal="Fornecer as MELHORES informações sobre a cidade selecionada", + backstory="Um guia local experiente com amplo conhecimento sobre a cidade, suas atrações e costumes", + tools=[search_tool], + verbose=True, + ) + + + class TripTasks: + def identify_task(self, agent, origin, cities, interests, range): + return Task( + description=dedent( + f""" + Analise e selecione a melhor cidade para a viagem com base em critérios específicos como padrões climáticos, eventos sazonais e custos de viagem. Esta tarefa envolve comparar várias cidades, considerando fatores como condições climáticas atuais, eventos culturais ou sazonais e despesas gerais de viagem. + Sua resposta final deve ser um relatório detalhado sobre a cidade escolhida e tudo o que você descobriu sobre ela, incluindo custos reais de voo, previsão do tempo e atrações. + + Saindo de: {origin} + Opções de cidades: {cities} + Data da viagem: {range} + Interesses do viajante: {interests} + """ + ), + agent=agent, + expected_output="Relatório detalhado sobre a cidade escolhida incluindo custos de voo, previsão do tempo e atrações", + ) + + def gather_task(self, agent, origin, interests, range): + return Task( + description=dedent( + f""" + Como especialista local nesta cidade, você deve compilar um guia aprofundado para alguém que está viajando para lá e quer ter a MELHOR viagem possível! + Reúna informações sobre principais atrações, costumes locais, eventos especiais e recomendações de atividades diárias. + Encontre os melhores lugares para ir, aqueles que só um local conhece. + Este guia deve fornecer uma visão abrangente do que a cidade tem a oferecer, incluindo joias escondidas, pontos culturais, marcos imperdíveis, previsão do tempo e custos gerais. + A resposta final deve ser um guia completo da cidade, rico em insights culturais e dicas práticas, adaptado para aprimorar a experiência de viagem. + + Data da viagem: {range} + Saindo de: {origin} + Interesses do viajante: {interests} + """ + ), + agent=agent, + expected_output="Guia completo da cidade incluindo joias escondidas, pontos culturais e dicas práticas", + ) + + + class TripCrew: + def __init__(self, origin, cities, date_range, interests): + self.cities = cities + self.origin = origin + self.interests = interests + self.date_range = date_range + + def run(self): + agents = TripAgents() + tasks = TripTasks() + + city_selector_agent = agents.city_selection_agent() + local_expert_agent = agents.local_expert() + + identify_task = tasks.identify_task( + city_selector_agent, + self.origin, + self.cities, + self.interests, + self.date_range, + ) + gather_task = tasks.gather_task( + local_expert_agent, self.origin, self.interests, self.date_range + ) + + crew = Crew( + agents=[city_selector_agent, local_expert_agent], + tasks=[identify_task, gather_task], + verbose=True, + memory=True, + knowledge={ + "sources": [string_source], + "metadata": {"preference": "personal"}, + }, + ) + + result = crew.kickoff() + return result + + + trip_crew = TripCrew("California", "Tokyo", "Dec 12 - Dec 20", "sports") + result = trip_crew.run() + + print("Resultado da equipe:", result) + ``` + Consulte a [Documentação de Tracing do MLflow](https://mlflow.org/docs/latest/llms/tracing/index.html) para mais configurações e casos de uso. + + + Agora os traces dos seus agentes crewAI estão sendo capturados pelo MLflow. + Vamos acessar o servidor de tracking do MLflow para visualizar os traces e obter insights dos seus Agents. + + Abra `127.0.0.1:5000` em seu navegador para acessar o servidor de tracking do MLflow. + + Exemplo de tracing do MLflow com crewai + + + \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/neatlogs.mdx b/docs/v1.15.13/pt-BR/observability/neatlogs.mdx new file mode 100644 index 0000000000..24b17cfced --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/neatlogs.mdx @@ -0,0 +1,134 @@ +--- +title: Neatlogs Integration +description: Understand, debug, and share your CrewAI agent runs +icon: magnifying-glass-chart +mode: "wide" +--- + +# Introduction + +Neatlogs helps you **see what your agent did**, **why**, and **share it**. + +It captures every step: thoughts, tool calls, responses, evaluations. No raw logs. Just clear, structured traces. Great for debugging and collaboration. + +## Why use Neatlogs? + +CrewAI agents use multiple tools and reasoning steps. When something goes wrong, you need context — not just errors. + +Neatlogs lets you: + +- Follow the full decision path +- Add feedback directly on steps +- Chat with the trace using AI assistant +- Share runs publicly for feedback +- Turn insights into tasks + +All in one place. + +Manage your traces effortlessly + +![Traces](/images/neatlogs-1.png) +![Trace Response](/images/neatlogs-2.png) + +The best UX to view a CrewAI trace. Post comments anywhere you want. Use AI to debug. + +![Trace Details](/images/neatlogs-3.png) +![Ai Chat Bot With A Trace](/images/neatlogs-4.png) +![Comments Drawer](/images/neatlogs-5.png) + +## Core Features + +- **Trace Viewer**: Track thoughts, tools, and decisions in sequence +- **Inline Comments**: Tag teammates on any trace step +- **Feedback & Evaluation**: Mark outputs as correct or incorrect +- **Error Highlighting**: Automatic flagging of API/tool failures +- **Task Conversion**: Convert comments into assigned tasks +- **Ask the Trace (AI)**: Chat with your trace using Neatlogs AI bot +- **Public Sharing**: Publish trace links to your community + +## Quick Setup with CrewAI + + + + Visit [neatlogs.com](https://neatlogs.com/?utm_source=crewAI-docs), create a project, copy the API key. + + + ```bash + pip install neatlogs + ``` + (Latest version 0.8.0, Python 3.8+; MIT license) + + + Before starting Crew agents, add: + + ```python + import neatlogs + neatlogs.init("YOUR_PROJECT_API_KEY") + ``` + + Agents run as usual. Neatlogs captures everything automatically. + + + + + + +## Under the Hood + +According to GitHub, Neatlogs: + +- Captures thoughts, tool calls, responses, errors, and token stats +- Supports AI-powered task generation and robust evaluation workflows + +All with just two lines of code. + + + +## Watch It Work + +### 🔍 Full Demo (4 min) + + + +### ⚙️ CrewAI Integration (30 s) + + + + + +## Links & Support + +- 📘 [Neatlogs Docs](https://docs.neatlogs.com/) +- 🔐 [Dashboard & API Key](https://app.neatlogs.com/) +- 🐦 [Follow on Twitter](https://twitter.com/neatlogs) +- 📧 Contact: hello@neatlogs.com +- 🛠 [GitHub SDK](https://github.com/NeatLogs/neatlogs) + + + +## TL;DR + +With just: + +```bash +pip install neatlogs + +import neatlogs +neatlogs.init("YOUR_API_KEY") + +You can now capture, understand, share, and act on your CrewAI agent runs in seconds. +No setup overhead. Full trace transparency. Full team collaboration. +``` diff --git a/docs/v1.15.13/pt-BR/observability/openlit.mdx b/docs/v1.15.13/pt-BR/observability/openlit.mdx new file mode 100644 index 0000000000..0d69ae20df --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/openlit.mdx @@ -0,0 +1,181 @@ +--- +title: Integração OpenLIT +description: Comece a monitorar seus Agentes rapidamente com apenas uma linha de código usando OpenTelemetry. +icon: magnifying-glass-chart +mode: "wide" +--- + +# Visão Geral do OpenLIT + +[OpenLIT](https://github.com/openlit/openlit?src=crewai-docs) é uma ferramenta open-source que simplifica o monitoramento de desempenho de agentes de IA, LLMs, VectorDBs e GPUs com apenas **uma** linha de código. + +Ela oferece rastreamento e métricas nativos do OpenTelemetry para acompanhar parâmetros importantes como custo, latência, interações e sequências de tarefas. +Essa configuração permite acompanhar hiperparâmetros e monitorar problemas de desempenho, ajudando a encontrar formas de aprimorar e refinar seus agentes com o tempo. + + + Visão geral do uso de agentes, incluindo custo e tokens + Visão geral dos rastreamentos e métricas otel do agente + Visão detalhada dos rastreamentos do agente + + +### Funcionalidades + +- **Painel Analítico**: Monitore a saúde e desempenho dos seus Agentes com dashboards detalhados que acompanham métricas, custos e interações dos usuários. +- **SDK de Observabilidade Nativo OpenTelemetry**: SDKs neutros de fornecedor para enviar rastreamentos e métricas para suas ferramentas de observabilidade existentes como Grafana, DataDog e outros. +- **Rastreamento de Custos para Modelos Customizados e Ajustados**: Adapte estimativas de custo para modelos específicos usando arquivos de precificação customizados para orçamentos precisos. +- **Painel de Monitoramento de Exceções**: Identifique e solucione rapidamente problemas ao rastrear exceções comuns e erros por meio de um painel de monitoramento. +- **Conformidade e Segurança**: Detecte ameaças potenciais como profanidade e vazamento de dados sensíveis (PII). +- **Detecção de Prompt Injection**: Identifique possíveis injeções de código e vazamentos de segredos. +- **Gerenciamento de Chaves de API e Segredos**: Gerencie suas chaves de API e segredos do LLM de forma centralizada e segura, evitando práticas inseguras. +- **Gerenciamento de Prompt**: Gerencie e versiona prompts de Agente usando o PromptHub para acesso consistente e fácil entre os agentes. +- **Model Playground** Teste e compare diferentes modelos para seus agentes CrewAI antes da implantação. + +## Instruções de Configuração + + + + + + ```shell + git clone git@github.com:openlit/openlit.git + ``` + + + A partir do diretório raiz do [Repositório OpenLIT](https://github.com/openlit/openlit), execute o comando abaixo: + ```shell + docker compose up -d + ``` + + + + + ```shell + pip install openlit + ``` + + + Adicione as duas linhas abaixo ao seu código de aplicação: + + + ```python + import openlit + openlit.init(otlp_endpoint="http://127.0.0.1:4318") + ``` + + Exemplo de uso para monitoramento de um Agente CrewAI: + + ```python + from crewai import Agent, Task, Crew, Process + import openlit + + openlit.init(disable_metrics=True) + # Definir seus agentes + pesquisador = Agent( + role="Pesquisador", + goal="Realizar pesquisas e análises aprofundadas sobre IA e agentes de IA", + backstory="Você é um pesquisador especialista em tecnologia, engenharia de software, IA e startups. Trabalha como freelancer e está atualmente pesquisando para um novo cliente.", + allow_delegation=False, + llm='command-r' + ) + + + # Definir sua task + task = Task( + description="Gere uma lista com 5 ideias interessantes para um artigo e escreva um parágrafo cativante para cada ideia, mostrando o potencial de um artigo completo sobre o tema. Retorne a lista de ideias com seus parágrafos e suas anotações.", + expected_output="5 tópicos, cada um com um parágrafo e notas complementares.", + ) + + # Definir o agente gerente + gerente = Agent( + role="Gerente de Projeto", + goal="Gerenciar eficientemente a equipe e garantir a conclusão de tarefas de alta qualidade", + backstory="Você é um gerente de projetos experiente, habilidoso em supervisionar projetos complexos e guiar equipes para o sucesso. Sua função é coordenar os esforços dos membros da equipe, garantindo que cada tarefa seja concluída no prazo e com o mais alto padrão.", + allow_delegation=True, + llm='command-r' + ) + + # Instanciar sua crew com um manager personalizado + crew = Crew( + agents=[pesquisador], + tasks=[task], + manager_agent=gerente, + process=Process.hierarchical, + ) + + # Iniciar o trabalho da crew + result = crew.kickoff() + + print(result) + ``` + + + + Adicione as duas linhas abaixo ao seu código de aplicação: + ```python + import openlit + + openlit.init() + ``` + + Execute o seguinte comando para configurar o endpoint de exportação OTEL: + ```shell + export OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4318" + ``` + + Exemplo de uso para monitoramento de um Agente CrewAI Async: + + ```python + import asyncio + from crewai import Crew, Agent, Task + import openlit + + openlit.init(otlp_endpoint="http://127.0.0.1:4318") + + # Criar um agente com execução de código habilitada + coding_agent = Agent( + role="Analista de Dados Python", + goal="Analisar dados e fornecer insights usando Python", + backstory="Você é um analista de dados experiente com fortes habilidades em Python.", + allow_code_execution=True, + llm="command-r" + ) + + # Criar uma task que exige execução de código + data_analysis_task = Task( + description="Analise o conjunto de dados fornecido e calcule a idade média dos participantes. Idades: {ages}", + agent=coding_agent, + expected_output="5 tópicos, cada um com um parágrafo e notas complementares.", + ) + + # Criar uma crew e adicionar a task + analysis_crew = Crew( + agents=[coding_agent], + tasks=[data_analysis_task] + ) + + # Função async para iniciar a crew de forma assíncrona + async def async_crew_execution(): + result = await analysis_crew.kickoff_async(inputs={"ages": [25, 30, 35, 40, 45]}) + print("Crew Result:", result) + + # Executar a função async + asyncio.run(async_crew_execution()) + ``` + + + Consulte o [repositório do SDK Python do OpenLIT](https://github.com/openlit/openlit/tree/main/sdk/python) para configurações e casos de uso avançados. + + + Com os dados de Observabilidade dos Agentes agora sendo coletados e enviados ao OpenLIT, o próximo passo é visualizar e analisar esses dados para obter insights sobre o desempenho, comportamento e identificar oportunidades de melhoria dos seus Agentes. + + Basta acessar o OpenLIT em `127.0.0.1:3000` no seu navegador para começar a explorar. Você pode fazer login usando as credenciais padrão + - **Email**: `user@openlit.io` + - **Senha**: `openlituser` + + + Visão geral do uso de agentes, incluindo custo e tokens + Visão geral dos rastreamentos e métricas otel do agente + + + + \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/opik.mdx b/docs/v1.15.13/pt-BR/observability/opik.mdx new file mode 100644 index 0000000000..5f2a2ef843 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/opik.mdx @@ -0,0 +1,130 @@ +--- +title: Integração Opik +description: Saiba como usar o Comet Opik para depurar, avaliar e monitorar suas aplicações CrewAI com rastreamento abrangente, avaliações automatizadas e dashboards prontos para produção. +icon: meteor +mode: "wide" +--- + +# Visão Geral do Opik + +Com o [Comet Opik](https://www.comet.com/docs/opik/), depure, avalie e monitore suas aplicações LLM, sistemas RAG e fluxos de trabalho agentic com rastreamento detalhado, avaliações automatizadas e dashboards prontos para produção. + + + Exemplo de monitoramento de agente Opik com CrewAI + + +O Opik oferece suporte abrangente para cada etapa do desenvolvimento da sua aplicação CrewAI: + +- **Registrar Traces e Spans**: Acompanhe automaticamente chamadas LLM e lógica da aplicação para depurar e analisar sistemas em desenvolvimento e em produção. Anote manualmente ou programaticamente, visualize e compare respostas entre projetos. +- **Avalie a Performance da sua Aplicação LLM**: Avalie contra um conjunto de testes personalizado e execute métricas de avaliação nativas ou defina suas próprias métricas via SDK ou UI. +- **Teste no Pipeline CI/CD**: Estabeleça bases de performance confiáveis com os testes unitários LLM do Opik, baseados em PyTest. Execute avaliações online para monitoramento contínuo em produção. +- **Monitore & Analise Dados de Produção**: Entenda a performance dos seus modelos em dados inéditos em produção e gere conjuntos de dados para novas iterações de desenvolvimento. + +## Configuração +A Comet oferece uma versão hospedada da plataforma Opik, ou você pode rodar a plataforma localmente. + +Para usar a versão hospedada, basta [criar uma conta gratuita na Comet](https://www.comet.com/signup?utm_medium=github&utm_source=crewai_docs) e obter sua chave de API. + +Para rodar a plataforma Opik localmente, veja nosso [guia de instalação](https://www.comet.com/docs/opik/self-host/overview/) para mais informações. + +Neste guia, utilizaremos o exemplo de início rápido da CrewAI. + + + + ```shell + pip install crewai crewai-tools opik --upgrade + ``` + + + ```python + import opik + opik.configure(use_local=False) + ``` + + + Primeiro, configuramos nossas chaves de API do provedor LLM como variáveis de ambiente: + + ```python + import os + import getpass + + if "OPENAI_API_KEY" not in os.environ: + os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ") + ``` + + + O primeiro passo é criar nosso projeto. Vamos utilizar um exemplo da documentação do CrewAI: + + ```python + from crewai import Agent, Crew, Task, Process + + + class NomeDaEquipe: + def agente_um(self) -> Agent: + return Agent( + role="Analista de Dados", + goal="Analisar tendências de dados no mercado", + backstory="Analista de dados experiente com formação em economia", + verbose=True, + ) + + def agente_dois(self) -> Agent: + return Agent( + role="Pesquisador de Mercado", + goal="Coletar informações sobre a dinâmica do mercado", + backstory="Pesquisador dedicado com olhar atento para detalhes", + verbose=True, + ) + + def tarefa_um(self) -> Task: + return Task( + name="Tarefa de Coleta de Dados", + description="Coletar dados recentes do mercado e identificar tendências.", + expected_output="Um relatório resumindo as principais tendências do mercado.", + agent=self.agente_um(), + ) + + def tarefa_dois(self) -> Task: + return Task( + name="Tarefa de Pesquisa de Mercado", + description="Pesquisar fatores que afetam a dinâmica do mercado.", + expected_output="Uma análise dos fatores que influenciam o mercado.", + agent=self.agente_dois(), + ) + + def equipe(self) -> Crew: + return Crew( + agents=[self.agente_um(), self.agente_dois()], + tasks=[self.tarefa_um(), self.tarefa_dois()], + process=Process.sequential, + verbose=True, + ) + + ``` + + Agora podemos importar o tracker do Opik e executar nossa crew: + + ```python + from opik.integrations.crewai import track_crewai + + track_crewai(project_name="crewai-integration-demo") + + my_crew = NomeDaEquipe().equipe() + result = my_crew.kickoff() + + print(result) + ``` + Após rodar sua aplicação CrewAI, acesse o app Opik para visualizar: + - Traces LLM, spans e seus metadados + - Interações dos agentes e fluxo de execução das tarefas + - Métricas de performance, como latência e uso de tokens + - Métricas de avaliação (nativas ou personalizadas) + + + +## Recursos + +- [🦉 Documentação Opik](https://www.comet.com/docs/opik/) +- [👉 Opik + CrewAI Colab](https://colab.research.google.com/github/comet-ml/opik/blob/main/apps/opik-documentation/documentation/docs/cookbook/crewai.ipynb) +- [🐦 X](https://x.com/cometml) +- [💬 Slack](https://slack.comet.com/) \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/overview.mdx b/docs/v1.15.13/pt-BR/observability/overview.mdx new file mode 100644 index 0000000000..e3776ba017 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/overview.mdx @@ -0,0 +1,120 @@ +--- +title: "Visão Geral" +description: "Monitore, avalie e otimize seus agentes CrewAI com ferramentas de observabilidade abrangentes" +icon: "face-smile" +mode: "wide" +--- + +## Observabilidade para CrewAI + +A observabilidade é fundamental para entender como seus agentes CrewAI estão desempenhando, identificar gargalos e garantir uma operação confiável em ambientes de produção. Esta seção aborda diversas ferramentas e plataformas que oferecem recursos de monitoramento, avaliação e otimização dos fluxos de trabalho dos seus agentes. + +## Por que a Observabilidade é Importante + +- **Monitoramento de Desempenho**: Acompanhe tempos de execução dos agentes, uso de tokens e consumo de recursos +- **Garantia de Qualidade**: Avalie a qualidade e a consistência das saídas em diferentes cenários +- **Depuração**: Identifique e resolva problemas no comportamento dos agentes e na execução de tarefas +- **Gestão de Custos**: Monitore o uso das APIs do LLM e os custos associados +- **Melhoria Contínua**: Colete insights para otimizar o desempenho dos agentes ao longo do tempo + +## Ferramentas de Observabilidade Disponíveis + +### Plataformas de Monitoramento e Rastreamento + + + + + Rastreamento ponta a ponta para fluxos de trabalho CrewAI com captura automática de interações de agentes. + + + + Monitoramento nativo OpenTelemetry com rastreamento de custos e análises de desempenho. + + + + Gerenciamento do ciclo de vida de machine learning com rastreamento e avaliação. + + + + Plataforma de engenharia de LLM com rastreamento detalhado e análises. + + + + Observabilidade open-source para LLMs e frameworks de agentes. + + + + Plataforma de observabilidade de IA para monitoramento e solução de problemas. + + + + Gateway de IA com monitoramento abrangente e recursos de confiabilidade. + + + + Depure, avalie e monitore aplicações LLM com rastreamento abrangente. + + + + Plataforma Weights & Biases para acompanhamento e avaliação de aplicações de IA. + + + +### Avaliação & Garantia de Qualidade + + + + Plataforma abrangente de avaliação para saídas de LLM e comportamentos de agentes. + + + +## Principais Métricas de Observabilidade + +### Métricas de Desempenho +- **Tempo de Execução**: Quanto tempo os agentes levam para concluir as tarefas +- **Uso de Tokens**: Tokens de entrada/saída consumidos pelas chamadas ao LLM +- **Latência de API**: Tempo de resposta de serviços externos +- **Taxa de Sucesso**: Percentual de tarefas concluídas com sucesso + +### Métricas de Qualidade +- **Acurácia da Saída**: Correção das respostas dos agentes +- **Consistência**: Confiabilidade em entradas semelhantes +- **Relevância**: Quão bem as saídas correspondem aos resultados esperados +- **Segurança**: Conformidade com políticas de conteúdo e diretrizes + +### Métricas de Custo +- **Custos de API**: Gastos decorrentes do uso do provedor LLM +- **Utilização de Recursos**: Consumo de processamento e memória +- **Custo por Tarefa**: Eficiência econômica das operações dos agentes +- **Acompanhamento de Orçamento**: Monitoramento em relação a limites de gastos + +## Primeiros Passos + +1. **Escolha suas Ferramentas**: Selecione plataformas de observabilidade que atendam às suas necessidades +2. **Instrumente seu Código**: Adicione monitoramento às suas aplicações CrewAI +3. **Configure Dashboards**: Prepare visualizações para as métricas principais +4. **Defina Alertas**: Crie notificações para eventos importantes +5. **Estabeleça Bases de Referência**: Meça o desempenho inicial para comparação futura +6. **Itere e Melhore**: Use os insights para otimizar seus agentes + +## Boas Práticas + +### Fase de Desenvolvimento +- Utilize rastreamento detalhado para entender o comportamento dos agentes +- Implemente métricas de avaliação desde o início do desenvolvimento +- Monitore o uso de recursos durante os testes +- Estabeleça verificações automatizadas de qualidade + +### Fase de Produção +- Implemente monitoramento e alertas abrangentes +- Acompanhe tendências de desempenho ao longo do tempo +- Monitore anomalias e degradações +- Mantenha visibilidade e controle dos custos + +### Melhoria Contínua +- Revisões regulares de desempenho e otimização +- Testes A/B de diferentes configurações de agentes +- Ciclos de feedback para aprimoramento da qualidade +- Documentação de lições aprendidas + +Escolha as ferramentas de observabilidade que melhor se encaixam no seu caso de uso, infraestrutura e requisitos de monitoramento para garantir que seus agentes CrewAI operem de forma confiável e eficiente. diff --git a/docs/v1.15.13/pt-BR/observability/patronus-evaluation.mdx b/docs/v1.15.13/pt-BR/observability/patronus-evaluation.mdx new file mode 100644 index 0000000000..c5e831c582 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/patronus-evaluation.mdx @@ -0,0 +1,206 @@ +--- +title: Avaliação Patronus AI +description: Monitore e avalie o desempenho de agentes CrewAI utilizando a plataforma abrangente de avaliação da Patronus AI para saídas de LLM e comportamentos de agentes. +icon: shield-check +mode: "wide" +--- + +# Avaliação Patronus AI + +## Visão Geral + +[Patronus AI](https://patronus.ai) oferece capacidades abrangentes de avaliação e monitoramento para agentes CrewAI, permitindo avaliar as saídas dos modelos, comportamentos dos agentes e o desempenho geral do sistema. Essa integração possibilita implementar fluxos de avaliação contínuos que ajudam a manter a qualidade e confiabilidade em ambientes de produção. + +## Principais Funcionalidades + +- **Avaliação Automatizada**: Avaliação em tempo real das saídas e comportamentos dos agentes +- **Critérios Personalizados**: Defina critérios de avaliação específicos para seus casos de uso +- **Monitoramento de Desempenho**: Acompanhe métricas de desempenho dos agentes ao longo do tempo +- **Garantia de Qualidade**: Assegure consistência na qualidade das saídas em diferentes cenários +- **Segurança & Conformidade**: Monitore possíveis problemas e violações de políticas + +## Ferramentas de Avaliação + +A Patronus disponibiliza três principais ferramentas de avaliação para diferentes casos de uso: + +1. **PatronusEvalTool**: Permite que os agentes selecionem o avaliador e os critérios mais apropriados para a tarefa de avaliação. +2. **PatronusPredefinedCriteriaEvalTool**: Utiliza avaliador e critérios predefinidos, especificados pelo usuário. +3. **PatronusLocalEvaluatorTool**: Utiliza avaliadores customizados definidos pelo usuário. + +## Instalação + +Para utilizar essas ferramentas, é necessário instalar o pacote Patronus: + +```shell +uv add patronus +``` + +Você também precisará configurar sua chave de API da Patronus como uma variável de ambiente: + +```shell +export PATRONUS_API_KEY="your_patronus_api_key" +``` + +## Passos para Começar + +Para utilizar as ferramentas de avaliação da Patronus de forma eficaz, siga estes passos: + +1. **Instale o Patronus**: Instale o pacote Patronus usando o comando acima. +2. **Configure a Chave de API**: Defina sua chave de API da Patronus como uma variável de ambiente. +3. **Escolha a Ferramenta Certa**: Selecione a ferramenta de avaliação Patronus mais adequada às suas necessidades. +4. **Configure a Ferramenta**: Configure a ferramenta com os parâmetros necessários. + +## Exemplos + +### Utilizando PatronusEvalTool + +O exemplo a seguir demonstra como usar o `PatronusEvalTool`, que permite aos agentes selecionar o avaliador e critérios mais apropriados: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusEvalTool + +# Initialize the tool +patronus_eval_tool = PatronusEvalTool() + +# Define an agent that uses the tool +coding_agent = Agent( + role="Agente de Programação", + goal="Gerar código de alta qualidade e verificar se a saída é código", + backstory="Um programador experiente que pode gerar código Python de alta qualidade.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate and evaluate code +generate_code_task = Task( + description="Crie um programa simples para gerar os N primeiros números da sequência de Fibonacci. Selecione o avaliador e os critérios mais apropriados para avaliar sua saída.", + expected_output="Programa que gera os N primeiros números da sequência de Fibonacci.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +### Utilizando PatronusPredefinedCriteriaEvalTool + +O exemplo a seguir demonstra como usar o `PatronusPredefinedCriteriaEvalTool`, que utiliza avaliador e critérios predefinidos: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusPredefinedCriteriaEvalTool + +# Initialize the tool with predefined criteria +patronus_eval_tool = PatronusPredefinedCriteriaEvalTool( + evaluators=[{"evaluator": "judge", "criteria": "contains-code"}] +) + +# Define an agent that uses the tool +coding_agent = Agent( + role="Agente de Programação", + goal="Gerar código de alta qualidade", + backstory="Um programador experiente que pode gerar código Python de alta qualidade.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate code +generate_code_task = Task( + description="Crie um programa simples para gerar os N primeiros números da sequência de Fibonacci.", + expected_output="Programa que gera os N primeiros números da sequência de Fibonacci.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +### Utilizando PatronusLocalEvaluatorTool + +O exemplo a seguir demonstra como usar o `PatronusLocalEvaluatorTool`, que utiliza avaliadores customizados via função: + +```python Code +from crewai import Agent, Task, Crew +from crewai_tools import PatronusLocalEvaluatorTool +from patronus import Client, EvaluationResult +import random + +# Initialize the Patronus client +client = Client() + +# Register a custom evaluator +@client.register_local_evaluator("random_evaluator") +def random_evaluator(**kwargs): + score = random.random() + return EvaluationResult( + score_raw=score, + pass_=score >= 0.5, + explanation="example explanation", + ) + +# Initialize the tool with the custom evaluator +patronus_eval_tool = PatronusLocalEvaluatorTool( + patronus_client=client, + evaluator="random_evaluator", + evaluated_model_gold_answer="example label", +) + +# Define an agent that uses the tool +coding_agent = Agent( + role="Agente de Programação", + goal="Gerar código de alta qualidade", + backstory="Um programador experiente que pode gerar código Python de alta qualidade.", + tools=[patronus_eval_tool], + verbose=True, +) + +# Example task to generate code +generate_code_task = Task( + description="Crie um programa simples para gerar os N primeiros números da sequência de Fibonacci.", + expected_output="Programa que gera os N primeiros números da sequência de Fibonacci.", + agent=coding_agent, +) + +# Create and run the crew +crew = Crew(agents=[coding_agent], tasks=[generate_code_task]) +result = crew.kickoff() +``` + +## Parâmetros + +### PatronusEvalTool + +O `PatronusEvalTool` não exige parâmetros durante a inicialização. Ele busca automaticamente os avaliadores e critérios disponíveis a partir da API da Patronus. + +### PatronusPredefinedCriteriaEvalTool + +O `PatronusPredefinedCriteriaEvalTool` aceita os seguintes parâmetros durante a inicialização: + +- **evaluators**: Obrigatório. Uma lista de dicionários contendo o avaliador e os critérios a serem utilizados. Por exemplo: `[{"evaluator": "judge", "criteria": "contains-code"}]`. + +### PatronusLocalEvaluatorTool + +O `PatronusLocalEvaluatorTool` aceita os seguintes parâmetros durante a inicialização: + +- **patronus_client**: Obrigatório. Instância do cliente Patronus. +- **evaluator**: Opcional. O nome do avaliador local registrado a ser utilizado. Default é uma string vazia. +- **evaluated_model_gold_answer**: Opcional. A resposta padrão (“gold answer”) para uso na avaliação. O padrão é uma string vazia. + +## Uso + +Ao utilizar as ferramentas de avaliação Patronus, você fornece a entrada do modelo, a saída e o contexto, e a ferramenta retorna os resultados da avaliação a partir da API da Patronus. + +Para o `PatronusEvalTool` e o `PatronusPredefinedCriteriaEvalTool`, os seguintes parâmetros são obrigatórios ao chamar a ferramenta: + +- **evaluated_model_input**: A descrição da tarefa do agente, em texto simples. +- **evaluated_model_output**: A saída da tarefa pelo agente. +- **evaluated_model_retrieved_context**: O contexto do agente. + +Para o `PatronusLocalEvaluatorTool`, os mesmos parâmetros são necessários, mas o avaliador e a resposta padrão são especificados durante a inicialização. + +## Conclusão + +As ferramentas de avaliação da Patronus fornecem uma forma poderosa de avaliar e pontuar entradas e saídas de modelos utilizando a plataforma Patronus AI. Ao possibilitar que agentes avaliem suas próprias saídas ou as de outros agentes, essas ferramentas ajudam a aprimorar a qualidade e confiabilidade dos fluxos de trabalho do CrewAI. \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/portkey.mdx b/docs/v1.15.13/pt-BR/observability/portkey.mdx new file mode 100644 index 0000000000..9e54136f53 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/portkey.mdx @@ -0,0 +1,823 @@ +--- +title: Integração com Portkey +description: Como usar Portkey com CrewAI +icon: key +mode: "wide" +--- + +Portkey CrewAI Header Image + + + +## Introdução + +Portkey aprimora o CrewAI com recursos prontos para produção, transformando seus crews de agentes experimentais em sistemas robustos ao fornecer: + +- **Observabilidade completa** de cada etapa do agente, uso de ferramentas e interações +- **Confiabilidade incorporada** com fallbacks, tentativas automáticas e balanceamento de carga +- **Rastreamento e otimização de custos** para gerenciar seus gastos com IA +- **Acesso a mais de 200 LLMs** por meio de uma única integração +- **Guardrails** para manter o comportamento dos agentes seguro e em conformidade +- **Prompts versionados** para desempenho consistente dos agentes + + +### Instalação & Configuração + + + +```bash +pip install -U crewai portkey-ai +``` + + + +Crie uma chave de API Portkey com limites de orçamento/taxa opcionais no [painel da Portkey](https://app.portkey.ai/). Você também pode adicionar configurações para confiabilidade, cache e outros recursos a essa chave. Mais sobre isso em breve. + + + +A integração é simples – basta atualizar a configuração do LLM no seu setup do CrewAI: + +```python +from crewai import LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Crie uma instância do LLM com integração Portkey +gpt_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", # Estamos usando uma chave virtual, então isso é apenas um placeholder + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_LLM_VIRTUAL_KEY", + trace_id="unique-trace-id", # Opcional, para rastreamento da requisição + ) +) + +#Use-os nos seus Crew Agents assim: + + @agent + def lead_market_analyst(self) -> Agent: + return Agent( + config=self.agents_config['lead_market_analyst'], + verbose=True, + memory=False, + llm=gpt_llm + ) + +``` + + +**O que são Virtual Keys?** Virtual keys no Portkey armazenam com segurança suas chaves de API dos provedores LLM (OpenAI, Anthropic, etc.) em um cofre criptografado. Elas facilitam a rotação de chaves e o gerenciamento de orçamento. [Saiba mais sobre virtual keys aqui](https://portkey.ai/docs/product/ai-gateway/virtual-keys). + + + + +## Recursos para Produção + +### 1. Observabilidade Avançada + +Portkey oferece observabilidade abrangente para seus agentes CrewAI, ajudando você a entender exatamente o que está acontecendo durante cada execução. + + + + + + + +Os traces fornecem uma visão hierárquica da execução do seu crew, mostrando a sequência de chamadas LLM, ativações de ferramentas e transições de estado. + +```python +# Adicione trace_id para habilitar o tracing hierárquico no Portkey +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + trace_id="unique-session-id" # Adicione um trace ID único + ) +) +``` + + + + + + + +Portkey registra cada interação com LLMs, incluindo: + +- Payloads completos das requisições e respostas +- Métricas de latência e uso de tokens +- Cálculos de custo +- Chamadas de ferramentas e execuções de funções + +Todos os logs podem ser filtrados por metadados, trace IDs, modelos e mais, tornando mais fácil depurar execuções específicas do crew. + + + + + + + +Portkey oferece dashboards integrados que ajudam você a: + +- Rastrear custos e uso de tokens em todas as execuções do crew +- Analisar métricas de desempenho, como latência e taxas de sucesso +- Identificar gargalos nos fluxos de trabalho dos agentes +- Comparar diferentes configurações de crew e LLMs + +Você pode filtrar e segmentar todas as métricas por metadados personalizados para analisar tipos de crew, grupos de usuários ou casos de uso específicos. + + + + + Analytics with metadata filters + + +Adicione metadados personalizados à configuração LLM do seu CrewAI para permitir filtragem e segmentação poderosas: + +```python +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + metadata={ + "crew_type": "research_crew", + "environment": "production", + "_user": "user_123", # Campo especial _user para analytics de usuários + "request_source": "mobile_app" + } + ) +) +``` + +Esses metadados podem ser usados para filtrar logs, traces e métricas no painel do Portkey, permitindo analisar execuções específicas do crew, usuários ou ambientes. + + + +### 2. Confiabilidade - Mantenha Seus Crews Funcionando Sem Interrupções + +Ao executar crews em produção, problemas podem ocorrer – limites de taxa da API, problemas de rede ou indisponibilidade do provedor. Os recursos de confiabilidade do Portkey garantem que seus agentes continuem funcionando mesmo quando problemas surgem. + +É simples habilitar fallback na sua configuração CrewAI usando um Config do Portkey: + +```python +from crewai import LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Crie LLM com configuração de fallback +portkey_llm = LLM( + model="gpt-4o", + max_tokens=1000, + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + config={ + "strategy": { + "mode": "fallback" + }, + "targets": [ + { + "provider": "openai", + "api_key": "YOUR_OPENAI_API_KEY", + "override_params": {"model": "gpt-4o"} + }, + { + "provider": "anthropic", + "api_key": "YOUR_ANTHROPIC_API_KEY", + "override_params": {"model": "claude-3-opus-20240229"} + } + ] + } + ) +) + +# Use essa configuração LLM com seus agentes +``` + +Essa configuração automaticamente tentará o Claude caso a requisição para o GPT-4o falhe, garantindo que seu crew continue funcionando. + + + + Lida automaticamente com falhas temporárias. Se uma chamada LLM falhar, o Portkey fará novas tentativas o número especificado de vezes – perfeito para limites de taxa ou instabilidades de rede. + + + Evite que seus agentes fiquem travados. Defina timeouts para garantir respostas (ou falhas controladas) dentro do tempo necessário. + + + Envie diferentes solicitações para diferentes provedores. Direcione raciocínios complexos para o GPT-4, tarefas criativas para Claude e respostas rápidas para Gemini conforme sua necessidade. + + + Mantenha-se em funcionamento mesmo se seu provedor principal falhar. Troque automaticamente para provedores de backup para manter a disponibilidade. + + + Distribua solicitações entre várias chaves de API ou provedores. Ótimo para operações de crew em grande escala e para permanecer dentro dos limites de taxa. + + + +### 3. Prompting no CrewAI + +O Prompt Engineering Studio do Portkey ajuda você a criar, gerenciar e otimizar os prompts usados em seus agentes CrewAI. Em vez de codificar prompts ou instruções manualmente, use a API de renderização de prompts do Portkey para buscar e aplicar dinâmicamente seus prompts versionados. + + +![Prompt Playground Interface](https://raw.githubusercontent.com/siddharthsambharia-portkey/Portkey-Product-Images/refs/heads/main/CrewAI%20Portkey%20Docs.webp) + + + + +Prompt Playground é um local para comparar, testar e implantar prompts perfeitos para sua aplicação de IA. É onde você experimenta com diferentes modelos, testa variáveis, compara saídas e refina sua estratégia de engenharia de prompts antes de implantar em produção. Ele permite: + +1. Desenvolver prompts de forma iterativa antes de usá-los em seus agentes +2. Testar prompts com diferentes variáveis e modelos +3. Comparar saídas entre diferentes versões de prompts +4. Colaborar com membros da equipe no desenvolvimento de prompts + +Esse ambiente visual facilita a criação de prompts eficazes para cada etapa do fluxo de trabalho dos seus agentes CrewAI. + + + +A API Prompt Render recupera seus templates de prompt com todos os parâmetros configurados: + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL, Portkey + +# Inicialize o cliente admin do Portkey +portkey_admin = Portkey(api_key="YOUR_PORTKEY_API_KEY") + +# Recupere o prompt usando a render API +prompt_data = portkey_client.prompts.render( + prompt_id="YOUR_PROMPT_ID", + variables={ + "agent_role": "Senior Research Scientist", + } +) + +backstory_agent_prompt=prompt_data.data.messages[0]["content"] + + +# Configure o LLM com integração Portkey +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY" + ) +) + +# Crie o agente utilizando o prompt renderizado +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory=backstory_agent, # Use o prompt renderizado + verbose=True, + llm=portkey_llm +) +``` + + + +Você pode: +- Criar múltiplas versões do mesmo prompt +- Comparar o desempenho entre versões +- Voltar a versões anteriores se necessário +- Especificar qual versão usar em seu código: + +```python +# Use uma versão específica do prompt +prompt_data = portkey_admin.prompts.render( + prompt_id="YOUR_PROMPT_ID@version_number", + variables={ + "agent_role": "Senior Research Scientist", + "agent_goal": "Discover groundbreaking insights" + } +) +``` + + + +Os prompts do Portkey usam modelos estilo Mustache para fácil substituição de variáveis: + +``` +You are a {{agent_role}} with expertise in {{domain}}. + +Your mission is to {{agent_goal}} by leveraging your knowledge +and experience in the field. + +Always maintain a {{tone}} tone and focus on providing {{focus_area}}. +``` + +Ao renderizar, basta passar as variáveis: + +```python +prompt_data = portkey_admin.prompts.render( + prompt_id="YOUR_PROMPT_ID", + variables={ + "agent_role": "Senior Research Scientist", + "domain": "artificial intelligence", + "agent_goal": "discover groundbreaking insights", + "tone": "professional", + "focus_area": "practical applications" + } +) +``` + + + + + Saiba mais sobre os recursos de gerenciamento de prompts do Portkey + + +### 4. Guardrails para Crews Seguros + +Guardrails garantem que seus agentes CrewAI operem com segurança e respondam adequadamente em todas as situações. + +**Por que usar Guardrails?** + +Os agentes CrewAI podem apresentar falhas de diversos tipos: +- Gerar conteúdo nocivo ou inapropriado +- Vazamento de informações sensíveis como PII +- Alucinar informações incorretas +- Gerar saídas em formatos incorretos + +Os guardrails do Portkey fornecem proteções tanto para entradas quanto para saídas. + +**Implementando Guardrails** + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Crie LLM com guardrails +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "input_guardrails": ["guardrails-id-xxx", "guardrails-id-yyy"], + "output_guardrails": ["guardrails-id-zzz"] + } + ) +) + +# Crie agente com LLM guardrailed +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +Os guardrails do Portkey podem: +- Detectar e redigir PII tanto em entradas quanto em saídas +- Filtrar conteúdo prejudicial ou inapropriado +- Validar formatos de resposta contra schemas +- Verificar alucinações comparando com ground truth +- Aplicar lógica e regras de negócio personalizadas + + + Explore os recursos de guardrails do Portkey para aumentar a segurança dos agentes + + +### 5. Rastreamento de Usuário com Metadados + +Rastreie usuários individuais através dos seus agentes CrewAI utilizando o sistema de metadados do Portkey. + +**O que é Metadata no Portkey?** + +Metadados permitem associar dados personalizados a cada requisição, possibilitando filtragem, segmentação e analytics. O campo especial `_user` é projetado especificamente para rastreamento de usuário. + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure o LLM com rastreamento de usuário +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + metadata={ + "_user": "user_123", # Campo especial _user para analytics de usuários + "user_tier": "premium", + "user_company": "Acme Corp", + "session_id": "abc-123" + } + ) +) + +# Crie agente com LLM rastreado +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +**Filtre Analytics por Usuário** + +Com os metadados configurados, você pode filtrar analytics por usuário e analisar métricas de desempenho individualmente: + + + + + +Isso permite: +- Rastreamento de custos e orçamento por usuário +- Analytics personalizados por usuário +- Métricas por equipe ou organização +- Monitoramento específico por ambiente (homologação x produção) + + + Veja como usar metadados personalizados para aprimorar seus analytics + + +### 6. Cache para Crews Eficientes + +Implemente caching para tornar seus agentes CrewAI mais eficientes e econômicos: + + + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure o LLM com caching simples +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "cache": { + "mode": "simple" + } + } + ) +) + +# Crie agente com LLM cacheado +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +O caching simples realiza correspondências exatas de prompts de entrada, cacheando requisições idênticas para evitar execuções redundantes do modelo. + + + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure o LLM com cache semântico +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY", + config={ + "cache": { + "mode": "semantic" + } + } + ) +) + +# Crie agente com LLM com cache semântico +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + +O cache semântico considera a similaridade contextual entre solicitações de entrada, armazenando respostas para entradas semanticamente similares. + + + +### 7. Interoperabilidade de Modelos + +O CrewAI oferece suporte a múltiplos provedores de LLM, e o Portkey amplia essa capacidade fornecendo acesso a mais de 200 LLMs por meio de uma interface unificada. Você pode facilmente alternar entre diferentes modelos sem alterar a lógica central do seu agente: + +```python +from crewai import Agent, LLM +from portkey_ai import createHeaders, PORTKEY_GATEWAY_URL + +# Configure LLMs com diferentes provedores +openai_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_OPENAI_VIRTUAL_KEY" + ) +) + +anthropic_llm = LLM( + model="claude-3-5-sonnet-latest", + max_tokens=1000, + base_url=PORTKEY_GATEWAY_URL, + api_key="dummy", + extra_headers=createHeaders( + api_key="YOUR_PORTKEY_API_KEY", + virtual_key="YOUR_ANTHROPIC_VIRTUAL_KEY" + ) +) + +# Escolha qual LLM usar para cada agente conforme necessário +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=openai_llm # Use anthropic_llm para Anthropic +) +``` + +Portkey oferece acesso a LLMs de provedores como: + +- OpenAI (GPT-4o, GPT-4 Turbo, etc.) +- Anthropic (Claude 3.5 Sonnet, Claude 3 Opus, etc.) +- Mistral AI (Mistral Large, Mistral Medium, etc.) +- Google Vertex AI (Gemini 1.5 Pro, etc.) +- Cohere (Command, Command-R, etc.) +- AWS Bedrock (Claude, Titan, etc.) +- Modelos locais/privados + + + Veja a lista completa de provedores LLM suportados pelo Portkey + + +## Configure Governança Corporativa para o CrewAI + +**Por que Governança Corporativa?** +Se você utiliza CrewAI dentro de sua organização, é importante considerar diversos aspectos de governança: +- **Gestão de Custos**: Controlar e rastrear os gastos com IA entre equipes +- **Controle de Acesso**: Gerenciar quais equipes podem usar modelos específicos +- **Analytics de Uso**: Compreender como a IA está sendo utilizada na organização +- **Segurança & Compliance**: Manutenção de padrões corporativos de segurança +- **Confiabilidade**: Garantir serviço consistente para todos os usuários + +O Portkey adiciona uma camada abrangente de governança para atender a essas necessidades corporativas. Vamos implementar esses controles passo a passo. + + + +Virtual Keys são a maneira segura do Portkey para gerenciar as chaves de API dos provedores de LLM. Elas fornecem controles essenciais como: +- Limites de orçamento para uso da API +- Capacidade de rate limiting +- Armazenamento seguro das chaves de API + +Para criar uma virtual key: +Vá até [Virtual Keys](https://app.portkey.ai/virtual-keys) no app Portkey. Salve e copie o ID da virtual key + + + + + + +Salve o ID da sua virtual key – você precisará dele no próximo passo. + + + + +Os Configs no Portkey definem como suas requisições são roteadas, com recursos como roteamento avançado, fallbacks e tentativas automáticas. + +Para criar seu config: +1. Vá até [Configs](https://app.portkey.ai/configs) no painel Portkey +2. Crie um novo config com: + ```json + { + "virtual_key": "YOUR_VIRTUAL_KEY_FROM_STEP1", + "override_params": { + "model": "gpt-4o" // Nome do seu modelo preferido + } + } + ``` +3. Salve e anote o nome do Config para o próximo passo + + + + + + + + +Agora crie uma chave de API Portkey e anexe a config criada no Passo 2: + +1. Vá até [API Keys](https://app.portkey.ai/api-keys) na Portkey e crie uma nova chave de API +2. Selecione sua config do `Passo 2` +3. Gere e salve sua chave de API + + + + + + + + +Após configurar sua chave de API Portkey com a config anexada, conecte-a aos seus agentes CrewAI: + +```python +from crewai import Agent, LLM +from portkey_ai import PORTKEY_GATEWAY_URL + +# Configure o LLM com sua chave de API +portkey_llm = LLM( + model="gpt-4o", + base_url=PORTKEY_GATEWAY_URL, + api_key="YOUR_PORTKEY_API_KEY" +) + +# Crie agente com LLM habilitado para Portkey +researcher = Agent( + role="Senior Research Scientist", + goal="Discover groundbreaking insights about the assigned topic", + backstory="You are an expert researcher with deep domain knowledge.", + verbose=True, + llm=portkey_llm +) +``` + + + + + +### Etapa 1: Implementar Controles de Orçamento & Rate Limits + +Virtual Keys permitem controle granular sobre o acesso ao LLM por equipe/departamento. Isso ajuda você a: +- Definir [limites de orçamento](https://portkey.ai/docs/product/ai-gateway/virtual-keys/budget-limits) +- Prevenir picos inesperados de uso através de Rate limits +- Rastrear gastos por departamento + +#### Configurando controles específicos de departamento: +1. Vá até [Virtual Keys](https://app.portkey.ai/virtual-keys) no painel Portkey +2. Crie uma nova Virtual Key para cada departamento com limites de orçamento e rate limits +3. Configure limites específicos por departamento + + + + + + + +### Etapa 2: Definir Regras de Acesso a Modelos + +À medida que o uso de IA cresce, controlar quais equipes têm acesso a quais modelos se torna fundamental. Os Configs do Portkey fornecem essa camada de controle com recursos como: + +#### Recursos de Controle de Acesso: +- **Restrições de Modelo**: Limite o acesso a modelos específicos +- **Proteção de Dados**: Implemente guardrails para dados sensíveis +- **Controles de Confiabilidade**: Adicione fallbacks e tentativas automáticas + +#### Exemplo de Configuração: +Aqui está um exemplo básico para rotear requisições ao OpenAI, usando especificamente o GPT-4o: + +```json +{ + "strategy": { + "mode": "single" + }, + "targets": [ + { + "virtual_key": "YOUR_OPENAI_VIRTUAL_KEY", + "override_params": { + "model": "gpt-4o" + } + } + ] +} +``` + + Crie seu config na [página de Configs](https://app.portkey.ai/configs) no painel do Portkey. + + + Os configs podem ser atualizados a qualquer momento para ajustar controles sem afetar aplicações em execução. + + + + + ### Etapa 3: Implementar Controles de Acesso + + Crie chaves de API específicas por usuário que automaticamente: + - Rastreiam uso por usuário/equipe com o auxílio das virtual keys + - Aplicam configs adequadas para rotear requisições + - Coletam metadados relevantes para filtragem de logs + - Impõem permissões de acesso + + Crie chaves de API através do [Portkey App](https://app.portkey.ai/) + + Exemplo usando Python SDK: + ```python + from portkey_ai import Portkey + + portkey = Portkey(api_key="YOUR_ADMIN_API_KEY") + + api_key = portkey.api_keys.create( + name="engineering-team", + type="organisation", + workspace_id="YOUR_WORKSPACE_ID", + defaults={ + "config_id": "your-config-id", + "metadata": { + "environment": "production", + "department": "engineering" + } + }, + scopes=["logs.view", "configs.read"] + ) + ``` + + Para instruções detalhadas de gerenciamento de chaves, veja a [documentação Portkey](https://portkey.ai/docs). + + + + ### Etapa 4: Implante & Monitore + Após distribuir as chaves de API para os membros da equipe, seu setup corporativo CrewAI está pronto. Cada membro pode agora usar suas chaves designadas com os níveis de acesso e controles de orçamento apropriados. + + Monitore o uso no painel Portkey: + - Rastreamento de custos por departamento + - Padrões de uso de modelos + - Volume de requisições + - Taxa de erros + + + + + +### Recursos Corporativos Agora Disponíveis +**Sua integração CrewAI agora conta com:** +- Controles de orçamento departamental +- Governança de acesso a modelos +- Rastreamento de uso & atribuição +- Guardrails de segurança +- Recursos de confiabilidade + + +## Perguntas Frequentes + + + + Portkey adiciona prontidão para produção ao CrewAI através de observabilidade abrangente (traces, logs, métricas), recursos de confiabilidade (fallbacks, tentativas automáticas, cache) e acesso a mais de 200 LLMs por meio de uma interface unificada. Isso facilita depurar, otimizar e escalar suas aplicações de agentes. + + + + Sim! Portkey integra-se perfeitamente a aplicações CrewAI existentes. Basta atualizar o código de configuração do LLM com a versão habilitada do Portkey. O restante do seu código de agente e crew permanece inalterado. + + + + Portkey suporta todos os recursos do CrewAI, incluindo agentes, ferramentas, workflows human-in-the-loop e todos os tipos de processo de tarefas (sequencial, hierárquico, etc.). Ele adiciona observabilidade e confiabilidade sem limitar nenhuma funcionalidade do framework. + + + + Sim, o Portkey permite que você use um `trace_id` consistente em múltiplos agentes de um crew para rastrear todo o fluxo de trabalho. Isso é especialmente útil para crews complexos onde você deseja entender o caminho completo de execução entre os agentes. + + + + O Portkey permite adicionar metadados personalizados à configuração do seu LLM, que podem ser usados para filtragem. Adicione campos como `crew_name`, `crew_type`, ou `session_id` para encontrar e analisar facilmente execuções específicas do crew. + + + + Sim! O Portkey utiliza suas próprias chaves de API dos provedores LLM. Elas são armazenadas com segurança como virtual keys, permitindo que você gerencie e gire as chaves facilmente sem alterar seu código. + + + + +## Recursos + + + +

Documentação oficial do CrewAI

+
+ +

Receba orientação personalizada sobre como implementar essa integração

+
+
diff --git a/docs/v1.15.13/pt-BR/observability/tracing.mdx b/docs/v1.15.13/pt-BR/observability/tracing.mdx new file mode 100644 index 0000000000..ba6c1b40a8 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/tracing.mdx @@ -0,0 +1,214 @@ +--- +title: CrewAI Tracing +description: Rastreamento integrado para Crews e Flows do CrewAI com a plataforma CrewAI AMP +icon: magnifying-glass-chart +mode: "wide" +--- + +# Rastreamento Integrado do CrewAI + +O CrewAI fornece recursos de rastreamento integrados que permitem monitorar e depurar seus Crews e Flows em tempo real. Este guia demonstra como habilitar o rastreamento para **Crews** e **Flows** usando a plataforma de observabilidade integrada do CrewAI. + +> **O que é o CrewAI Tracing?** O rastreamento integrado do CrewAI fornece observabilidade abrangente para seus agentes de IA, incluindo decisões de agentes, cronogramas de execução de tarefas, uso de ferramentas e chamadas de LLM - tudo acessível através da [plataforma CrewAI AMP](https://app.crewai.com). + +![CrewAI Tracing Interface](/images/crewai-tracing.png) + +## Pré-requisitos + +Antes de usar o rastreamento do CrewAI, você precisa: + +1. **Conta CrewAI AMP**: Cadastre-se para uma conta gratuita em [app.crewai.com](https://app.crewai.com) +2. **Autenticação CLI**: Use a CLI do CrewAI para autenticar seu ambiente local + +```bash +crewai login +``` + +## Instruções de Configuração + +### Passo 1: Crie sua Conta CrewAI AMP + +Visite [app.crewai.com](https://app.crewai.com) e crie sua conta gratuita. Isso lhe dará acesso à plataforma CrewAI AMP, onde você pode visualizar rastreamentos, métricas e gerenciar seus crews. + +### Passo 2: Instale a CLI do CrewAI e Autentique + +Se você ainda não o fez, instale o CrewAI com as ferramentas CLI: + +```bash +uv add crewai[tools] +``` + +Em seguida, autentique sua CLI com sua conta CrewAI AMP: + +```bash +crewai login +``` + +Este comando irá: + +1. Abrir seu navegador na página de autenticação +2. Solicitar que você insira um código de dispositivo +3. Autenticar seu ambiente local com sua conta CrewAI AMP +4. Habilitar recursos de rastreamento para seu desenvolvimento local + +### Passo 3: Habilite o Rastreamento em seu Crew + +Você pode habilitar o rastreamento para seu Crew definindo o parâmetro `tracing` como `True`: + +```python +from crewai import Agent, Crew, Process, Task +from crewai_tools import SerperDevTool + +# Define your agents +researcher = Agent( + role="Senior Research Analyst", + goal="Uncover cutting-edge developments in AI and data science", + backstory=\"\"\"You work at a leading tech think tank. + Your expertise lies in identifying emerging trends. + You have a knack for dissecting complex data and presenting actionable insights.\"\"\", + verbose=True, + tools=[SerperDevTool()], +) + +writer = Agent( + role="Tech Content Strategist", + goal="Craft compelling content on tech advancements", + backstory=\"\"\"You are a renowned Content Strategist, known for your insightful and engaging articles. + You transform complex concepts into compelling narratives.\"\"\", + verbose=True, +) + +# Create tasks for your agents +research_task = Task( + description=\"\"\"Conduct a comprehensive analysis of the latest advancements in AI in 2024. + Identify key trends, breakthrough technologies, and potential industry impacts.\"\"\", + expected_output="Full analysis report in bullet points", + agent=researcher, +) + +writing_task = Task( + description=\"\"\"Using the insights provided, develop an engaging blog + post that highlights the most significant AI advancements. + Your post should be informative yet accessible, catering to a tech-savvy audience.\"\"\", + expected_output="Full blog post of at least 4 paragraphs", + agent=writer, +) + +# Enable tracing in your crew +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + process=Process.sequential, + tracing=True, # Enable built-in tracing + verbose=True +) + +# Execute your crew +result = crew.kickoff() +``` + +### Passo 4: Habilite o Rastreamento em seu Flow + +Da mesma forma, você pode habilitar o rastreamento para Flows do CrewAI: + +```python +from crewai.flow.flow import Flow, listen, start +from pydantic import BaseModel + +class ExampleState(BaseModel): + counter: int = 0 + message: str = "" + +class ExampleFlow(Flow[ExampleState]): + def __init__(self): + super().__init__(tracing=True) # Enable tracing for the flow + + @start() + def first_method(self): + print("Starting the flow") + self.state.counter = 1 + self.state.message = "Flow started" + return "continue" + + @listen("continue") + def second_method(self): + print("Continuing the flow") + self.state.counter += 1 + self.state.message = "Flow continued" + return "finish" + + @listen("finish") + def final_method(self): + print("Finishing the flow") + self.state.counter += 1 + self.state.message = "Flow completed" + +# Create and run the flow with tracing enabled +flow = ExampleFlow(tracing=True) +result = flow.kickoff() +``` + +### Passo 5: Visualize os Rastreamentos no Painel CrewAI AMP + +Após executar o crew ou flow, você pode visualizar os rastreamentos gerados pela sua aplicação CrewAI no painel CrewAI AMP. Você verá etapas detalhadas das interações dos agentes, usos de ferramentas e chamadas de LLM. +Basta clicar no link abaixo para visualizar os rastreamentos ou ir para a aba de rastreamentos no painel [aqui](https://app.crewai.com/crewai_plus/trace_batches) +![CrewAI Tracing Interface](/images/view-traces.png) + +### Alternativa: Configuração de Variável de Ambiente + +Você também pode habilitar o rastreamento globalmente definindo uma variável de ambiente: + +```bash +export CREWAI_TRACING_ENABLED=true +``` + +Ou adicione-a ao seu arquivo `.env`: + +```env +CREWAI_TRACING_ENABLED=true +``` + +Quando esta variável de ambiente estiver definida, todos os Crews e Flows terão automaticamente o rastreamento habilitado, mesmo sem definir explicitamente `tracing=True`. + +## Visualizando seus Rastreamentos + +### Acesse o Painel CrewAI AMP + +1. Visite [app.crewai.com](https://app.crewai.com) e faça login em sua conta +2. Navegue até o painel do seu projeto +3. Clique na aba **Traces** para visualizar os detalhes de execução + +### O que Você Verá nos Rastreamentos + +O rastreamento do CrewAI fornece visibilidade abrangente sobre: + +- **Decisões dos Agentes**: Veja como os agentes raciocinam através das tarefas e tomam decisões +- **Cronograma de Execução de Tarefas**: Representação visual de sequências e dependências de tarefas +- **Uso de Ferramentas**: Monitore quais ferramentas são chamadas e seus resultados +- **Chamadas de LLM**: Rastreie todas as interações do modelo de linguagem, incluindo prompts e respostas +- **Métricas de Desempenho**: Tempos de execução, uso de tokens e custos +- **Rastreamento de Erros**: Informações detalhadas de erros e rastreamentos de pilha + +### Recursos de Rastreamento + +- **Cronograma de Execução**: Clique através de diferentes estágios de execução +- **Logs Detalhados**: Acesse logs abrangentes para depuração +- **Análise de Desempenho**: Analise padrões de execução e otimize o desempenho +- **Capacidades de Exportação**: Baixe rastreamentos para análise adicional + +### Problemas de Autenticação + +Se você encontrar problemas de autenticação: + +1. Certifique-se de estar logado: `crewai login` +2. Verifique sua conexão com a internet +3. Verifique sua conta em [app.crewai.com](https://app.crewai.com) + +### Rastreamentos Não Aparecem + +Se os rastreamentos não estiverem aparecendo no painel: + +1. Confirme que `tracing=True` está definido em seu Crew/Flow +2. Verifique se `CREWAI_TRACING_ENABLED=true` se estiver usando variáveis de ambiente +3. Certifique-se de estar autenticado com `crewai login` +4. Verifique se seu crew/flow está realmente executando diff --git a/docs/v1.15.13/pt-BR/observability/truefoundry.mdx b/docs/v1.15.13/pt-BR/observability/truefoundry.mdx new file mode 100644 index 0000000000..f48cb42e83 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/truefoundry.mdx @@ -0,0 +1,146 @@ +--- +title: Integração com a TrueFoundry +icon: chart-line +mode: "wide" +--- + +A TrueFoundry fornece um [AI Gateway](https://www.truefoundry.com/ai-gateway) pronto para uso empresarial, que pode ser usado para governança e observabilidade em frameworks agentivos como o CrewAI. O AI Gateway da TrueFoundry funciona como uma interface unificada para acesso a LLMs, oferecendo: + +- **Acesso unificado à API**: Conecte-se a 250+ LLMs (OpenAI, Claude, Gemini, Groq, Mistral) por meio de uma única API +- **Baixa latência**: Latência interna abaixo de 3 ms com roteamento inteligente e balanceamento de carga +- **Segurança corporativa**: Conformidade com SOC 2, HIPAA e GDPR, com RBAC e auditoria de logs +- **Gestão de cotas e custos**: Cotas baseadas em tokens, rate limiting e rastreamento abrangente de uso +- **Observabilidade**: Registro completo de requisições/respostas, métricas e traces com retenção personalizável + +## Como a TrueFoundry se integra ao CrewAI + + +### Instalação e configuração + + + +```bash +pip install crewai +``` + + + +1. Crie uma conta na [TrueFoundry](https://www.truefoundry.com/register) +2. Siga os passos do [Início rápido](https://docs.truefoundry.com/gateway/quick-start) + + + +![Configuração de código da TrueFoundry](/images/new-code-snippet.png) + +```python +from crewai import LLM + +# Criar uma instância de LLM com o AI Gateway da TrueFoundry +truefoundry_llm = LLM( + model="openai-main/gpt-4o", # Da mesma forma, você pode chamar qualquer modelo de qualquer provedor + base_url="your_truefoundry_gateway_base_url", + api_key="your_truefoundry_api_key" +) + +# Usar nos seus agentes do CrewAI +from crewai import Agent + +@agent +def researcher(self) -> Agent: + return Agent( + config=self.agents_config['researcher'], + llm=truefoundry_llm, + verbose=True + ) +``` + + + +### Exemplo completo do CrewAI + +```python +from crewai import Agent, Task, Crew, LLM + +# Configurar o LLM com a TrueFoundry +llm = LLM( + model="openai-main/gpt-4o", + base_url="your_truefoundry_gateway_base_url", + api_key="your_truefoundry_api_key" +) + +# Criar agentes +researcher = Agent( + role='Analista de Pesquisa', + goal='Conduzir pesquisa de mercado detalhada', + backstory='Analista de mercado especialista com atenção aos detalhes', + llm=llm, + verbose=True +) + +writer = Agent( + role='Redator de Conteúdo', + goal='Criar relatórios abrangentes', + backstory='Redator técnico experiente', + llm=llm, + verbose=True +) + +# Criar tarefas +research_task = Task( + description='Pesquisar tendências do mercado de IA para 2024', + agent=researcher, + expected_output='Resumo de pesquisa abrangente' +) + +writing_task = Task( + description='Criar um relatório de pesquisa de mercado', + agent=writer, + expected_output='Relatório bem estruturado com insights', + context=[research_task] +) + +# Criar e executar a crew +crew = Crew( + agents=[researcher, writer], + tasks=[research_task, writing_task], + verbose=True +) + +result = crew.kickoff() +``` + +### Observabilidade e governança + +Monitore seus agentes do CrewAI pela aba de métricas da TrueFoundry: +![Métricas da TrueFoundry](/images/gateway-metrics.png) + +Com o AI Gateway da TrueFoundry, você pode monitorar e analisar: + +- **Métricas de desempenho**: Acompanhe métricas-chave de latência como Latência da Requisição, Tempo até o Primeiro Token (TTFS) e Latência entre Tokens (ITL), com percentis P99, P90 e P50 +- **Custos e uso de tokens**: Tenha visibilidade dos custos da sua aplicação com detalhamento de tokens de entrada/saída e das despesas associadas a cada modelo +- **Padrões de uso**: Entenda como sua aplicação está sendo utilizada com análises detalhadas sobre atividade de usuários, distribuição de modelos e uso por equipe +- **Limite de taxa e balanceamento de carga**: Você pode configurar rate limiting, balanceamento de carga e fallback para seus modelos + +## Rastreamento + +Para uma compreensão mais detalhada sobre rastreamento, consulte [getting-started-tracing](https://docs.truefoundry.com/docs/tracing/tracing-getting-started). Para rastreamento, você pode adicionar o SDK do Traceloop: + +```bash +pip install traceloop-sdk +``` + +```python +from traceloop.sdk import Traceloop + +# Inicializar rastreamento avançado +Traceloop.init( + api_endpoint="https://your-truefoundry-endpoint/api/tracing", + headers={ + "Authorization": f"Bearer {your_truefoundry_pat_token}", + "TFY-Tracing-Project": "your_project_name", + }, +) +``` + +Isso oferece correlação adicional de rastreamentos em todo o seu fluxo de trabalho com o CrewAI. +![Rastreamento do CrewAI na TrueFoundry](/images/tracing_crewai.png) \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/observability/weave.mdx b/docs/v1.15.13/pt-BR/observability/weave.mdx new file mode 100644 index 0000000000..a3ed92a266 --- /dev/null +++ b/docs/v1.15.13/pt-BR/observability/weave.mdx @@ -0,0 +1,125 @@ +--- +title: Integração com Weave +description: Saiba como usar o Weights & Biases (W&B) Weave para rastrear, experimentar, avaliar e melhorar suas aplicações CrewAI. +icon: radar +mode: "wide" +--- + +# Visão Geral do Weave + +[Weights & Biases (W&B) Weave](https://weave-docs.wandb.ai/) é um framework para rastreamento, experimentação, avaliação, implementação e aprimoramento de aplicações baseadas em LLM. + +![Visão geral do uso do tracing do W&B Weave com CrewAI](/images/weave-tracing.gif) + +O Weave oferece suporte completo para todas as etapas do desenvolvimento da sua aplicação CrewAI: + +- **Rastreamento e Monitoramento**: Acompanhe automaticamente chamadas LLM e a lógica da aplicação para depuração e análise de sistemas em produção +- **Iteração Sistemática**: Aperfeiçoe e itere em prompts, conjuntos de dados e modelos +- **Avaliação**: Utilize avaliadores personalizados ou pré-construídos para avaliar e aprimorar sistematicamente o desempenho dos agentes +- **Guardrails**: Proteja seus agentes com salvaguardas pré e pós-execução para moderação de conteúdo e segurança de prompts + +O Weave captura automaticamente rastreamentos (traces) de suas aplicações CrewAI, permitindo monitorar e analisar o desempenho, as interações e o fluxo de execução dos seus agentes. Isso te ajuda a construir melhores conjuntos de dados para avaliação e a otimizar os fluxos de trabalho dos agentes. + +## Instruções de Configuração + + + + ```shell + pip install crewai weave + ``` + + + Cadastre-se em uma [conta Weights & Biases](https://wandb.ai) caso ainda não tenha uma. Você precisará dela para visualizar rastreamentos e métricas. + + + Adicione o seguinte código à sua aplicação: + + ```python + import weave + + # Inicialize o Weave com o nome do seu projeto + weave.init(project_name="crewai_demo") + ``` + + Após a inicialização, o Weave fornecerá uma URL onde você poderá visualizar seus rastreamentos e métricas. + + + ```python + from crewai import Agent, Task, Crew, LLM, Process + + # Crie um LLM com temperatura 0 para garantir saídas determinísticas + llm = LLM(model="gpt-4o", temperature=0) + + # Crie os agentes + pesquisador = Agent( + role='Analista de Pesquisa', + goal='Encontrar e analisar as melhores oportunidades de investimento', + backstory='Especialista em análise financeira e pesquisa de mercado', + llm=llm, + verbose=True, + allow_delegation=False, + ) + + redator = Agent( + role='Redator de Relatórios', + goal='Escrever relatórios de investimento claros e concisos', + backstory='Experiente na criação de relatórios financeiros detalhados', + llm=llm, + verbose=True, + allow_delegation=False, + ) + + # Crie as tarefas + pesquisa = Task( + description='Pesquisa aprofundada sobre o {tema}', + expected_output='Dados de mercado abrangentes incluindo principais players, tamanho de mercado e tendências de crescimento.', + agent=pesquisador + ) + + redacao = Task( + description='Escreva um relatório detalhado com base na pesquisa', + expected_output='O relatório deve ser fácil de ler e entender. Use tópicos quando aplicável.', + agent=redator + ) + + # Crie o crew + equipe = Crew( + agents=[pesquisador, redator], + tasks=[pesquisa, redacao], + verbose=True, + process=Process.sequential, + ) + + # Execute o crew + resultado = equipe.kickoff(inputs={"tema": "IA em ciência dos materiais"}) + print(resultado) + ``` + + + Após executar sua aplicação CrewAI, acesse a URL do Weave fornecida durante a inicialização para visualizar: + - Chamadas LLM e seus metadados + - Interações dos agentes e fluxo de execução das tarefas + - Métricas de desempenho como latência e uso de tokens + - Quaisquer erros ou problemas ocorridos durante a execução + + + Exemplo de rastreamento do Weave com CrewAI + + + + +## Funcionalidades + +- O Weave captura automaticamente todas as operações do CrewAI: interações dos agentes e execuções das tarefas; chamadas LLM com metadados e uso de tokens; uso de ferramentas e resultados. +- A integração suporta todos os métodos de execução do CrewAI: `kickoff()`, `kickoff_for_each()`, `kickoff_async()` e `kickoff_for_each_async()`. +- Rastreamento automático de todas as [crewAI-tools](https://github.com/crewAIInc/crewAI-tools). +- Suporte ao recurso flow com patching por decorador (`@start`, `@listen`, `@router`, `@or_`, `@and_`). +- Rastreie guardrails personalizados passados para o `Task` do CrewAI com `@weave.op()`. + +Para informações detalhadas sobre o que é suportado, acesse a [documentação do Weave CrewAI](https://weave-docs.wandb.ai/guides/integrations/crewai/#getting-started-with-flow). + +## Recursos + +- [📘 Documentação do Weave](https://weave-docs.wandb.ai) +- [📊 Exemplo de dashboard Weave x CrewAI](https://wandb.ai/ayut/crewai_demo/weave/traces?cols=%7B%22wb_run_id%22%3Afalse%2C%22attributes.weave.client_version%22%3Afalse%2C%22attributes.weave.os_name%22%3Afalse%2C%22attributes.weave.os_release%22%3Afalse%2C%22attributes.weave.os_version%22%3Afalse%2C%22attributes.weave.source%22%3Afalse%2C%22attributes.weave.sys_version%22%3Afalse%7D&peekPath=%2Fayut%2Fcrewai_demo%2Fcalls%2F0195c838-38cb-71a2-8a15-651ecddf9d89) +- [🐦 X](https://x.com/weave_wb) \ No newline at end of file diff --git a/docs/v1.15.13/pt-BR/quickstart.mdx b/docs/v1.15.13/pt-BR/quickstart.mdx new file mode 100644 index 0000000000..32ba1d70a0 --- /dev/null +++ b/docs/v1.15.13/pt-BR/quickstart.mdx @@ -0,0 +1,257 @@ +--- +title: Guia Rápido +description: Crie seu primeiro Flow CrewAI em minutos — orquestração, estado e um crew com um agente que gera um relatório real. +icon: rocket +mode: "wide" +--- + +### Assista: Construindo Agents e Flows CrewAI com Coding Agent Skills + +Instale nossas coding agent skills (Claude Code, Codex, ...) para colocar seus agentes de código para funcionar rapidamente com o CrewAI. + +Você pode instalar com `npx skills add crewaiinc/skills` + + + +Neste guia você vai **criar um Flow** que define um tópico de pesquisa, executa um **crew com um agente** (um pesquisador com busca na web) e termina com um **relatório em Markdown** no disco. Flows são a forma recomendada de estruturar apps em produção: eles controlam **estado** e **ordem de execução**, enquanto os **agentes** fazem o trabalho dentro da etapa do crew. + +Se ainda não instalou o CrewAI, siga primeiro o [guia de instalação](/pt-BR/installation). + +## Pré-requisitos + +- Ambiente Python e a CLI do CrewAI (veja [instalação](/pt-BR/installation)) +- Um LLM configurado com as chaves corretas — veja [LLMs](/pt-BR/concepts/llms#setting-up-your-llm) +- Uma chave de API do [Serper.dev](https://serper.dev/) (`SERPER_API_KEY`) para busca na web neste tutorial + +## Construa seu primeiro Flow + + + + No terminal, gere um projeto Flow (o nome da pasta usa sublinhados, ex.: `latest_ai_flow`): + + + ```shell Terminal + crewai create flow latest-ai-flow + cd latest_ai_flow + ``` + + + Isso cria um app Flow em `src/latest_ai_flow/`, incluindo um crew inicial em `crews/content_crew/` que você substituirá por um crew de pesquisa **com um único agente** nos próximos passos. + + + + Crie `src/latest_ai_flow/crews/content_crew/agents/researcher.jsonc` (crie o diretório `agents/` se necessário). Variáveis como `{topic}` são preenchidas a partir de `crew.kickoff(inputs=...)`. + + ```jsonc agents/researcher.jsonc + { + "role": "Pesquisador(a) Sênior de Dados em {topic}", + "goal": "Descobrir os desenvolvimentos mais recentes em {topic}", + "backstory": "Você é um pesquisador experiente que encontra as informações mais relevantes e apresenta tudo com clareza.", + "tools": ["SerperDevTool"], + "settings": { + "verbose": true + } + } + ``` + + + + + Crie `src/latest_ai_flow/crews/content_crew/crew.jsonc`: + + ```jsonc crew.jsonc + { + "name": "Research Crew", + "agents": ["researcher"], + "tasks": [ + { + "name": "research_task", + "description": "Faça uma pesquisa aprofundada sobre {topic}. Use busca na web para obter informações recentes e confiáveis.", + "expected_output": "Um relatório em markdown com seções claras: tendências principais, ferramentas ou empresas relevantes e implicações. Entre 800 e 1200 palavras. Sem cercas de código em volta do documento inteiro.", + "agent": "researcher", + "output_file": "output/report.md", + "markdown": true + } + ], + "process": "sequential", + "verbose": true + } + ``` + + + + + Substitua o `content_crew.py` gerado por um pequeno loader que transforma `crew.jsonc` em uma `Crew`. + + ```python content_crew.py + # src/latest_ai_flow/crews/content_crew/content_crew.py + from pathlib import Path + + from crewai.project import load_crew + + + def kickoff_content_crew(inputs: dict): + crew, default_inputs = load_crew(Path(__file__).with_name("crew.jsonc")) + return crew.kickoff(inputs={**default_inputs, **inputs}) + ``` + + + + + Conecte o crew a um Flow: um passo `@start()` define o tópico no **estado** e um `@listen` executa o crew. O `output_file` da tarefa continua gravando `output/report.md`. + + ```python main.py + # src/latest_ai_flow/main.py + from pydantic import BaseModel + + from crewai.flow import Flow, listen, start + + from latest_ai_flow.crews.content_crew.content_crew import kickoff_content_crew + + + class ResearchFlowState(BaseModel): + topic: str = "" + report: str = "" + + + class LatestAiFlow(Flow[ResearchFlowState]): + @start() + def prepare_topic(self, crewai_trigger_payload: dict | None = None): + if crewai_trigger_payload: + self.state.topic = crewai_trigger_payload.get("topic", "AI Agents") + else: + self.state.topic = "AI Agents" + print(f"Tópico: {self.state.topic}") + + @listen(prepare_topic) + def run_research(self): + result = kickoff_content_crew(inputs={"topic": self.state.topic}) + self.state.report = result.raw + print("Crew de pesquisa concluído.") + + @listen(run_research) + def summarize(self): + print("Relatório em: output/report.md") + + + def kickoff(): + LatestAiFlow().kickoff() + + + def plot(): + LatestAiFlow().plot() + + + if __name__ == "__main__": + kickoff() + ``` + + + Se o nome do pacote não for `latest_ai_flow`, ajuste o import de `kickoff_content_crew` para o caminho de módulo do seu projeto. + + + + + Na raiz do projeto, no arquivo `.env`, defina: + + - `SERPER_API_KEY` — obtida em [Serper.dev](https://serper.dev/) + - As chaves do provedor de modelo conforme necessário — veja [configuração de LLM](/pt-BR/concepts/llms#setting-up-your-llm) + + + + + ```shell Terminal + crewai install + crewai run + ``` + + + O `crewai run` executa o ponto de entrada do Flow definido no projeto (o mesmo comando dos crews; o tipo do projeto é `"flow"` no `pyproject.toml`). + + + + Você deve ver logs do Flow e do crew. Abra **`output/report.md`** para o relatório gerado (trecho): + + + ```markdown output/report.md + # Agentes de IA: panorama e tendências recentes + + ## Resumo executivo + … + + ## Principais tendências + - **Uso de ferramentas e orquestração** — … + - **Adoção empresarial** — … + + ## Implicações + … + ``` + + + O arquivo real será mais longo e refletirá resultados de busca ao vivo. + + + +## Como isso se encaixa + +1. **Flow** — `LatestAiFlow` executa `prepare_topic`, depois `run_research`, depois `summarize`. O estado (`topic`, `report`) fica no Flow. +2. **Crew** — `kickoff_content_crew` carrega `crew.jsonc` e executa uma tarefa com um agente: o pesquisador usa **Serper** na web e escreve o relatório. +3. **Artefato** — O `output_file` da tarefa grava o relatório em `output/report.md`. + +Para ir além em Flows (roteamento, persistência, human-in-the-loop), veja [Construa seu primeiro Flow](/pt-BR/guides/flows/first-flow) e [Flows](/pt-BR/concepts/flows). Para crews sem Flow, veja [Crews](/pt-BR/concepts/crews). Para um único `Agent` com `kickoff()` sem tarefas, veja [Agents](/pt-BR/concepts/agents#direct-agent-interaction-with-kickoff). + + +Você tem um Flow ponta a ponta com um crew de agente e um relatório salvo — uma base sólida para novas etapas, crews ou ferramentas. + + +### Consistência de nomes + +Os nomes em `crew.jsonc` devem coincidir com os arquivos e referências: + +- `agents: ["researcher"]` carrega `agents/researcher.jsonc` +- `tasks[].agent: "researcher"` atribui a tarefa a esse agente + +## Implantação + +Envie seu Flow para o **[CrewAI AMP](https://app.crewai.com)** quando rodar localmente e o projeto estiver em um repositório **GitHub**. Na raiz do projeto: + + +```bash Autenticar +crewai login +``` + +```bash Criar implantação +crewai deploy create +``` + +```bash Status e logs +crewai deploy status +crewai deploy logs +``` + +```bash Enviar atualizações após mudanças no código +crewai deploy push +``` + +```bash Listar ou remover implantações +crewai deploy list +crewai deploy remove +``` + + + + A primeira implantação costuma levar **cerca de 1 minuto**. Pré-requisitos completos e fluxo na interface web estão em [Implantar no AMP](https://docs-platform.crewai.com/platform/pt-BR/guides/deploy-to-amp). + + + + + AMP passo a passo (CLI e painel). + + + Troque ideias, compartilhe projetos e conecte-se com outros desenvolvedores CrewAI. + + diff --git a/docs/v1.15.13/pt-BR/skills.mdx b/docs/v1.15.13/pt-BR/skills.mdx new file mode 100644 index 0000000000..ef492dee38 --- /dev/null +++ b/docs/v1.15.13/pt-BR/skills.mdx @@ -0,0 +1,50 @@ +--- +title: Skills +description: Instale crewaiinc/skills pelo registro oficial em skills.sh—Flows, Crews e agentes alinhados à documentação para Claude Code, Cursor, Codex e outros. +icon: wand-magic-sparkles +mode: "wide" +--- + +# Skills + +**Dê ao seu agente de código o contexto do CrewAI em um comando.** + +As **Skills** do CrewAI são publicadas em **[skills.sh/crewaiinc/skills](https://skills.sh/crewaiinc/skills)**—o registro oficial de `crewaiinc/skills`, com cada skill (por exemplo **design-agent**, **getting-started**, **design-task** e **ask-docs**), estatísticas de instalação e auditorias. Ensinam agentes de código—como Claude Code, Cursor e Codex—a estruturar Flows, configurar Crews, usar ferramentas e seguir os padrões do CrewAI. Execute o comando abaixo (ou cole no seu agente). + +```shell Terminal +npx skills add crewaiinc/skills +``` + +Isso adiciona o pacote de skills ao fluxo do seu agente para aplicar convenções do CrewAI sem precisar reexplicar o framework a cada sessão. Código-fonte e issues ficam no [GitHub](https://github.com/crewAIInc/skills). + +## O que seu agente ganha + +- **Flows** — apps com estado, passos e kickoffs de crew no estilo CrewAI +- **Crews e agentes** — padrões JSON-first (`crew.jsonc`, `agents/*.jsonc`), papéis, tarefas e delegação +- **Ferramentas e integrações** — conectar agentes a busca, APIs e ferramentas comuns +- **Layout de projeto** — alinhar com scaffolds da CLI e convenções do repositório +- **Padrões atualizados** — skills acompanham a documentação e as práticas recomendadas + +## Saiba mais neste site + + + + Como usar `AGENTS.md` e fluxos de agente de código com o CrewAI. + + + Construa seu primeiro Flow e crew ponta a ponta. + + + Instale a CLI e o pacote Python do CrewAI. + + + Listagem oficial de `crewaiinc/skills`—skills, instalações e auditorias. + + + Fonte, atualizações e issues do pacote de skills. + + + +### Vídeo: CrewAI com coding agent skills + +