mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-09-12 22:29:41 +00:00
Compare commits
1 Commits
1.15.17
...
codex/llm-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5007af866e |
6
.github/codeql/codeql-config.yml
vendored
6
.github/codeql/codeql-config.yml
vendored
@@ -2,7 +2,7 @@ name: "CodeQL Config"
|
||||
|
||||
paths-ignore:
|
||||
# Ignore template files - these are boilerplate code that shouldn't be analyzed
|
||||
- "lib/cli/src/crewai_cli/templates/**"
|
||||
- "lib/crewai/src/crewai/cli/templates/**"
|
||||
# Ignore test cassettes - these are test fixtures/recordings
|
||||
- "lib/crewai/tests/cassettes/**"
|
||||
- "lib/crewai-tools/tests/cassettes/**"
|
||||
@@ -18,16 +18,12 @@ paths:
|
||||
- ".github/workflows/**"
|
||||
- ".github/actions/**"
|
||||
# Include all Python source code from workspace packages
|
||||
- "lib/cli/src/**"
|
||||
- "lib/crewai/src/**"
|
||||
- "lib/crewai-core/src/**"
|
||||
- "lib/crewai-tools/src/**"
|
||||
- "lib/crewai-files/src/**"
|
||||
- "lib/devtools/src/**"
|
||||
# Include tests (but exclude cassettes via paths-ignore)
|
||||
- "lib/cli/tests/**"
|
||||
- "lib/crewai/tests/**"
|
||||
- "lib/crewai-core/tests/**"
|
||||
- "lib/crewai-tools/tests/**"
|
||||
- "lib/crewai-files/tests/**"
|
||||
- "lib/devtools/tests/**"
|
||||
|
||||
18
.github/dependabot.yml
vendored
18
.github/dependabot.yml
vendored
@@ -1,3 +1,6 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
|
||||
version: 2
|
||||
@@ -5,22 +8,9 @@ updates:
|
||||
- package-ecosystem: uv
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: monday
|
||||
open-pull-requests-limit: 10
|
||||
interval: "weekly"
|
||||
groups:
|
||||
security-updates:
|
||||
applies-to: security-updates
|
||||
patterns:
|
||||
- "*"
|
||||
patch-minor-updates:
|
||||
applies-to: version-updates
|
||||
patterns:
|
||||
- "*"
|
||||
update-types:
|
||||
- patch
|
||||
- minor
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
update-types:
|
||||
- version-update:semver-major
|
||||
|
||||
4
.github/workflows/codeql.yml
vendored
4
.github/workflows/codeql.yml
vendored
@@ -15,11 +15,11 @@ on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
paths-ignore:
|
||||
- "lib/cli/src/crewai_cli/templates/**"
|
||||
- "lib/crewai/src/crewai/cli/templates/**"
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths-ignore:
|
||||
- "lib/cli/src/crewai_cli/templates/**"
|
||||
- "lib/crewai/src/crewai/cli/templates/**"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
|
||||
5
.github/workflows/linter.yml
vendored
5
.github/workflows/linter.yml
vendored
@@ -18,14 +18,13 @@ jobs:
|
||||
with:
|
||||
# Exclusion-only patterns match every non-excluded file under the
|
||||
# default "some" quantifier. Require all patterns (including "**")
|
||||
# so docs/markdown/Actions-only PRs correctly set code=false.
|
||||
# so docs-only / markdown-only PRs correctly set code=false.
|
||||
predicate-quantifier: every
|
||||
filters: |
|
||||
code:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!**/*.md'
|
||||
- '!.github/**'
|
||||
|
||||
lint-run:
|
||||
needs: changes
|
||||
@@ -82,7 +81,7 @@ jobs:
|
||||
- name: Check results
|
||||
run: |
|
||||
if [ "${{ needs.changes.outputs.code }}" != "true" ]; then
|
||||
echo "Non-code change, skipping lint"
|
||||
echo "Docs-only change, skipping lint"
|
||||
exit 0
|
||||
fi
|
||||
if [ "${{ needs.lint-run.result }}" == "success" ]; then
|
||||
|
||||
21
.github/workflows/tests.yml
vendored
21
.github/workflows/tests.yml
vendored
@@ -18,14 +18,13 @@ jobs:
|
||||
with:
|
||||
# Exclusion-only patterns match every non-excluded file under the
|
||||
# default "some" quantifier. Require all patterns (including "**")
|
||||
# so docs/markdown/Actions-only PRs correctly set code=false.
|
||||
# so docs-only / markdown-only PRs correctly set code=false.
|
||||
predicate-quantifier: every
|
||||
filters: |
|
||||
code:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!**/*.md'
|
||||
- '!.github/**'
|
||||
|
||||
tests-matrix:
|
||||
name: tests (${{ matrix.python-version }})
|
||||
@@ -122,31 +121,17 @@ jobs:
|
||||
.venv
|
||||
key: uv-main-py${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}
|
||||
|
||||
# Report the required check names (tests 3.10–3.13) when the matrix is skipped.
|
||||
# Branch protection expects these names; a skipped matrix never reports them.
|
||||
tests-skip:
|
||||
name: tests (${{ matrix.python-version }})
|
||||
needs: changes
|
||||
if: needs.changes.outputs.code != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.10', '3.11', '3.12', '3.13']
|
||||
steps:
|
||||
- name: Skip non-code change
|
||||
run: echo "Non-code change, skipping tests"
|
||||
|
||||
# Summary job to provide single status for branch protection
|
||||
tests:
|
||||
name: tests
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changes, tests-matrix, tests-skip]
|
||||
needs: [changes, tests-matrix]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check results
|
||||
run: |
|
||||
if [ "${{ needs.changes.outputs.code }}" != "true" ]; then
|
||||
echo "Non-code change, skipping tests"
|
||||
echo "Docs-only change, skipping tests"
|
||||
exit 0
|
||||
fi
|
||||
if [ "${{ needs.tests-matrix.result }}" == "success" ]; then
|
||||
|
||||
21
.github/workflows/type-checker.yml
vendored
21
.github/workflows/type-checker.yml
vendored
@@ -18,14 +18,13 @@ jobs:
|
||||
with:
|
||||
# Exclusion-only patterns match every non-excluded file under the
|
||||
# default "some" quantifier. Require all patterns (including "**")
|
||||
# so docs/markdown/Actions-only PRs correctly set code=false.
|
||||
# so docs-only / markdown-only PRs correctly set code=false.
|
||||
predicate-quantifier: every
|
||||
filters: |
|
||||
code:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!**/*.md'
|
||||
- '!.github/**'
|
||||
|
||||
type-checker-matrix:
|
||||
name: type-checker (${{ matrix.python-version }})
|
||||
@@ -76,31 +75,17 @@ jobs:
|
||||
.venv
|
||||
key: uv-main-py${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}
|
||||
|
||||
# Report the required check names when the matrix is skipped.
|
||||
# Branch protection expects these names; a skipped matrix never reports them.
|
||||
type-checker-skip:
|
||||
name: type-checker (${{ matrix.python-version }})
|
||||
needs: changes
|
||||
if: needs.changes.outputs.code != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
||||
steps:
|
||||
- name: Skip non-code change
|
||||
run: echo "Non-code change, skipping type checks"
|
||||
|
||||
# Summary job to provide single status for branch protection
|
||||
type-checker:
|
||||
name: type-checker
|
||||
runs-on: ubuntu-latest
|
||||
needs: [changes, type-checker-matrix, type-checker-skip]
|
||||
needs: [changes, type-checker-matrix]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Check results
|
||||
run: |
|
||||
if [ "${{ needs.changes.outputs.code }}" != "true" ]; then
|
||||
echo "Non-code change, skipping type checks"
|
||||
echo "Docs-only change, skipping type checks"
|
||||
exit 0
|
||||
fi
|
||||
if [ "${{ needs.type-checker-matrix.result }}" == "success" ]; then
|
||||
|
||||
10
.github/workflows/vulnerability-scan.yml
vendored
10
.github/workflows/vulnerability-scan.yml
vendored
@@ -26,14 +26,13 @@ jobs:
|
||||
with:
|
||||
# Exclusion-only patterns match every non-excluded file under the
|
||||
# default "some" quantifier. Require all patterns (including "**")
|
||||
# so docs/markdown/Actions-only PRs correctly set code=false.
|
||||
# so docs-only / markdown-only PRs correctly set code=false.
|
||||
predicate-quantifier: every
|
||||
filters: |
|
||||
code:
|
||||
- '**'
|
||||
- '!docs/**'
|
||||
- '!**/*.md'
|
||||
- '!.github/**'
|
||||
- name: Set code output
|
||||
id: set
|
||||
run: |
|
||||
@@ -86,11 +85,8 @@ jobs:
|
||||
--skip-editable
|
||||
--format json
|
||||
--output pip-audit-report.json
|
||||
# chromadb <=1.5.9 (CVE-2026-45829 / GHSA-f4j7-r4q5-qw2c): pre-auth RCE in
|
||||
# the Python HTTP server. Fix merged upstream in chroma-core/chroma#7237
|
||||
# but no PyPI release beyond 1.5.9 yet. CrewAI only uses PersistentClient
|
||||
# (embedded), not the HTTP server.
|
||||
--ignore-vuln GHSA-f4j7-r4q5-qw2c
|
||||
--ignore-vuln GHSA-rrmf-rvhw-rf47 # torch 2.12.0 (CVE-2025-3000): local-only memory corruption in torch.jit.script; no fix available.
|
||||
--ignore-vuln GHSA-f4j7-r4q5-qw2c # chromadb 1.1.1 (CVE-2026-45829): pre-auth RCE in the HTTP server; no fix available.
|
||||
)
|
||||
uv run pip-audit "${pip_audit_args[@]}"
|
||||
continue-on-error: true
|
||||
|
||||
@@ -48,6 +48,7 @@ repos:
|
||||
--ignore-vuln PYSEC-2025-197
|
||||
--ignore-vuln PYSEC-2025-210
|
||||
--ignore-vuln PYSEC-2026-139
|
||||
--ignore-vuln GHSA-rrmf-rvhw-rf47
|
||||
--ignore-vuln PYSEC-2025-211
|
||||
--ignore-vuln PYSEC-2025-212
|
||||
--ignore-vuln PYSEC-2025-213
|
||||
|
||||
@@ -24,5 +24,3 @@ Follow these guidelines when contributing:
|
||||
may reference them.
|
||||
4. If you want to preview your changes locally, use `cd docs && mintlify dev`.
|
||||
To check for broken links, run `cd docs && mintlify broken-links`.
|
||||
5. After editing English docs, sync translations to `ar`, `ko`, and `pt-BR`
|
||||
before finishing the task. Follow [DOCS_TRANSLATIONS.md](DOCS_TRANSLATIONS.md).
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
# Sync Docs Translations
|
||||
|
||||
After English documentation changes, sync the same updates to Arabic (`ar`),
|
||||
Korean (`ko`), and Brazilian Portuguese (`pt-BR`).
|
||||
|
||||
Supported locales: `ar`, `ko`, `pt-BR`.
|
||||
|
||||
## Step 1 — Find changed English files with git
|
||||
|
||||
From the repo root:
|
||||
|
||||
```bash
|
||||
# Uncommitted changes (staged or unstaged)
|
||||
git diff --name-only HEAD -- docs/edge/en/
|
||||
|
||||
# All changes on this branch vs main
|
||||
git diff --name-only main...HEAD -- docs/edge/en/
|
||||
|
||||
# Newly added files
|
||||
git status --porcelain docs/edge/en/
|
||||
```
|
||||
|
||||
Only process `*.mdx` under `docs/edge/en/`. Do not edit `docs/v*/` snapshots.
|
||||
|
||||
## Step 2 — Map each file to locale targets
|
||||
|
||||
For `docs/edge/en/<path>.mdx`, update or create:
|
||||
|
||||
- `docs/edge/ar/<path>.mdx`
|
||||
- `docs/edge/ko/<path>.mdx`
|
||||
- `docs/edge/pt-BR/<path>.mdx`
|
||||
|
||||
If English is a **new page**, also add matching entries in `docs/docs.json`
|
||||
navigation for each locale.
|
||||
|
||||
## Step 3 — Translate
|
||||
|
||||
Use the updated English file as source of truth. When locale files already
|
||||
exist, apply the same semantic change — do not rewrite unrelated sections.
|
||||
|
||||
Rules:
|
||||
|
||||
- Translate prose and frontmatter values (`title`, `description`, `sidebarTitle`)
|
||||
- Keep MDX/JSX tags, code blocks, URLs, and identifiers unchanged
|
||||
- Keep terms like Agent, Crew, Task, Flow, LLM, API, CLI, MCP in English where
|
||||
appropriate
|
||||
- Rewrite internal links: `/en/` → `/{lang}/` (`/ar/`, `/ko/`, `/pt-BR/`)
|
||||
- Do not add translator notes
|
||||
|
||||
## Step 4 — Verify (optional)
|
||||
|
||||
```bash
|
||||
cd docs && mintlify broken-links
|
||||
```
|
||||
|
||||
Commit English and locale files together.
|
||||
|
||||
## Checklist
|
||||
|
||||
```markdown
|
||||
- [ ] Git: listed changed docs/edge/en/*.mdx files
|
||||
- [ ] ar: updated/created matching files
|
||||
- [ ] ko: updated/created matching files
|
||||
- [ ] pt-BR: updated/created matching files
|
||||
- [ ] Links use /{lang}/ prefix; code blocks unchanged
|
||||
- [ ] docs/docs.json updated if new English page added
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
`git diff --name-only HEAD -- docs/edge/en/` returns:
|
||||
|
||||
```text
|
||||
docs/edge/en/concepts/llms.mdx
|
||||
```
|
||||
|
||||
Update:
|
||||
|
||||
- `docs/edge/ar/concepts/llms.mdx`
|
||||
- `docs/edge/ko/concepts/llms.mdx`
|
||||
- `docs/edge/pt-BR/concepts/llms.mdx`
|
||||
102
README.md
102
README.md
@@ -66,7 +66,7 @@ standard for production-ready agentic automation.
|
||||
|
||||
# CrewAI AMP Suite
|
||||
|
||||
For organizations that need a commercial control plane around CrewAI, [CrewAI AMP Suite](https://crewai.com/amp) adds managed deployment, observability, governance, security, and enterprise support.
|
||||
For organizations that need a commercial control plane around CrewAI, [CrewAI AMP Suite](https://www.crewai.com/enterprise) adds managed deployment, observability, governance, security, and enterprise support.
|
||||
|
||||
You can try one part of the suite, the [Crew Control Plane, for free](https://app.crewai.com).
|
||||
|
||||
@@ -88,12 +88,8 @@ intelligent automations.
|
||||
- [Build with AI](#build-with-ai)
|
||||
- [Why CrewAI?](#why-crewai)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Learning Resources](#learning-resources)
|
||||
- [Understanding Flows and Crews](#understanding-flows-and-crews)
|
||||
- [Installation](#1-installation)
|
||||
- [Setting Up Your Crew](#2-setting-up-your-crew-with-the-yaml-configuration)
|
||||
- [Running Your Crew](#3-running-your-crew)
|
||||
- [Key Features](#key-features)
|
||||
- [Understanding Flows and Crews](#understanding-flows-and-crews)
|
||||
- [Examples](#examples)
|
||||
- [Quick Tutorial](#quick-tutorial)
|
||||
- [Write Job Descriptions](#write-job-descriptions)
|
||||
@@ -155,7 +151,9 @@ Setup and run your first CrewAI agents by following this tutorial.
|
||||
|
||||
[](https://www.youtube.com/watch?v=-kSOTtYzgEw "CrewAI Getting Started Tutorial")
|
||||
|
||||
### Learning Resources
|
||||
###
|
||||
|
||||
Learning Resources
|
||||
|
||||
Learn CrewAI through our comprehensive courses:
|
||||
|
||||
@@ -309,7 +307,7 @@ research_task:
|
||||
description: >
|
||||
Conduct a thorough research about {topic}
|
||||
Make sure you find any interesting and relevant information given
|
||||
the current year is 2026.
|
||||
the current year is 2025.
|
||||
expected_output: >
|
||||
A list with 10 bullet points of the most relevant information about {topic}
|
||||
agent: researcher
|
||||
@@ -319,7 +317,7 @@ reporting_task:
|
||||
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 fledged report with the main topics, each with a full section of information.
|
||||
A fully fledge reports with the mains topics, each with a full section of information.
|
||||
Formatted as markdown without '```'
|
||||
agent: reporting_analyst
|
||||
output_file: report.md
|
||||
@@ -432,7 +430,7 @@ crewai update
|
||||
|
||||
You should see the output in the console and the `report.md` file should be created in the root of your project with the full final report.
|
||||
|
||||
In addition to the sequential process, you can use the hierarchical process, which automatically assigns a manager to the defined crew to properly coordinate the planning and execution of tasks through delegation and validation of results. [See more about the processes here](https://docs.crewai.com/en/concepts/processes).
|
||||
In addition to the sequential process, you can use the hierarchical process, which automatically assigns a manager to the defined crew to properly coordinate the planning and execution of tasks through delegation and validation of results. [See more about the processes here](https://docs.crewai.com/core-concepts/Processes/).
|
||||
|
||||
## Key Features
|
||||
|
||||
@@ -453,7 +451,7 @@ Choose CrewAI to build powerful, adaptable, and production-ready AI automations.
|
||||
You can test different real life examples of AI crews in the [CrewAI-examples repo](https://github.com/crewAIInc/crewAI-examples?tab=readme-ov-file):
|
||||
|
||||
- [Landing Page Generator](https://github.com/crewAIInc/crewAI-examples/tree/main/crews/landing_page_generator)
|
||||
- [Having Human input on the execution](https://docs.crewai.com/en/learn/human-input-on-execution)
|
||||
- [Having Human input on the execution](https://docs.crewai.com/how-to/Human-Input-on-Execution)
|
||||
- [Trip Planner](https://github.com/crewAIInc/crewAI-examples/tree/main/crews/trip_planner)
|
||||
- [Stock Analysis](https://github.com/crewAIInc/crewAI-examples/tree/main/crews/stock_analysis)
|
||||
|
||||
@@ -485,7 +483,7 @@ CrewAI's power truly shines when combining Crews with Flows to create sophistica
|
||||
CrewAI flows support logical operators like `or_` and `and_` to combine multiple conditions. This can be used with `@start`, `@listen`, or `@router` decorators to create complex triggering conditions.
|
||||
|
||||
- `or_`: Triggers when any of the specified conditions are met.
|
||||
- `and_`: Triggers when all of the specified conditions are met.
|
||||
- `and_`Triggers when all of the specified conditions are met.
|
||||
|
||||
Here's how you can orchestrate multiple Crews within a Flow:
|
||||
|
||||
@@ -582,7 +580,7 @@ This example demonstrates how to:
|
||||
|
||||
CrewAI supports using various LLMs through a variety of connection options. By default your agents will use the OpenAI API when querying the model. However, there are several other ways to allow your agents to connect to models. For example, you can configure your agents to use a local model via the Ollama tool.
|
||||
|
||||
Please refer to the [Connect CrewAI to LLMs](https://docs.crewai.com/en/learn/llm-connections) page for details on configuring your agents' connections to models.
|
||||
Please refer to the [Connect CrewAI to LLMs](https://docs.crewai.com/how-to/LLM-Connections/) page for details on configuring your agents' connections to models.
|
||||
|
||||
## When to Use CrewAI
|
||||
|
||||
@@ -598,26 +596,13 @@ CrewAI is especially useful when you want to:
|
||||
|
||||
## Contribution
|
||||
|
||||
CrewAI is open-source and we welcome contributions. See
|
||||
[`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) for the full setup guide,
|
||||
branching conventions, and PR checklist.
|
||||
CrewAI is open-source and we welcome contributions. If you're looking to contribute, please:
|
||||
|
||||
Quick start:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/crewAIInc/crewAI.git
|
||||
cd crewAI
|
||||
uv sync --all-groups --all-extras
|
||||
uv run pre-commit install
|
||||
```
|
||||
|
||||
```bash
|
||||
# Tests
|
||||
uv run pytest lib/crewai/tests/ -x -q
|
||||
|
||||
# Type checks
|
||||
uv run mypy lib/
|
||||
```
|
||||
- Fork the repository.
|
||||
- Create a new branch for your feature.
|
||||
- Add your feature or improvement.
|
||||
- Send a pull request.
|
||||
- We appreciate your input!
|
||||
|
||||
### Contributing to the docs
|
||||
|
||||
@@ -629,8 +614,51 @@ immediately and are frozen into a new versioned snapshot under
|
||||
`docs/v<X.Y.Z>/` at the next release cut. Frozen snapshots are immutable — CI
|
||||
rejects PRs that modify them without a `[docs-freeze]` title prefix. The
|
||||
release CLI (`devtools release`) handles the freeze automatically; see
|
||||
[`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) for contributor guidance and
|
||||
[`lib/devtools/README.md`](lib/devtools/README.md) for release tooling.
|
||||
[`AGENTS.md`](AGENTS.md) for the full contributor guide and
|
||||
[`RELEASING.md`](RELEASING.md) for the release-cut runbook.
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
```bash
|
||||
uv lock
|
||||
uv sync
|
||||
```
|
||||
|
||||
### Virtual Env
|
||||
|
||||
```bash
|
||||
uv venv
|
||||
```
|
||||
|
||||
### Pre-commit hooks
|
||||
|
||||
```bash
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
uv run pytest .
|
||||
```
|
||||
|
||||
### Running static type checks
|
||||
|
||||
```bash
|
||||
uvx mypy src
|
||||
```
|
||||
|
||||
### Packaging
|
||||
|
||||
```bash
|
||||
uv build
|
||||
```
|
||||
|
||||
### Installing Locally
|
||||
|
||||
```bash
|
||||
uv pip install dist/*.tar.gz
|
||||
```
|
||||
|
||||
## Telemetry
|
||||
|
||||
@@ -701,7 +729,7 @@ A: CrewAI is a lean, fast Python framework built specifically for orchestrating
|
||||
|
||||
### Q: How do I install CrewAI?
|
||||
|
||||
A: Install CrewAI with [UV](https://docs.astral.sh/uv/):
|
||||
A: Install CrewAI using pip:
|
||||
|
||||
```shell
|
||||
uv pip install crewai
|
||||
@@ -723,7 +751,7 @@ A: Yes. CrewAI excels at both simple and highly complex real-world scenarios, of
|
||||
|
||||
### Q: Can I use CrewAI with local AI models?
|
||||
|
||||
A: Absolutely! CrewAI supports various language models, including local ones. Tools like Ollama and LM Studio allow seamless integration. Check the [LLM Connections documentation](https://docs.crewai.com/en/learn/llm-connections) for more details.
|
||||
A: Absolutely! CrewAI supports various language models, including local ones. Tools like Ollama and LM Studio allow seamless integration. Check the [LLM Connections documentation](https://docs.crewai.com/how-to/LLM-Connections/) for more details.
|
||||
|
||||
### Q: What makes Crews different from Flows?
|
||||
|
||||
@@ -743,7 +771,7 @@ A: Check out practical examples in the [CrewAI-examples repository](https://gith
|
||||
|
||||
### Q: How can I contribute to CrewAI?
|
||||
|
||||
A: Contributions are warmly welcomed! Fork the repository, create your branch, implement your changes, and submit a pull request. See [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) for detailed guidelines.
|
||||
A: Contributions are warmly welcomed! Fork the repository, create your branch, implement your changes, and submit a pull request. See the Contribution section of the README for detailed guidelines.
|
||||
|
||||
### Q: What additional features does CrewAI AMP offer?
|
||||
|
||||
|
||||
10507
docs/docs.json
10507
docs/docs.json
File diff suppressed because it is too large
Load Diff
@@ -4,192 +4,6 @@ description: "تحديثات المنتج والتحسينات وإصلاحات
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="19 أغسطس 2026">
|
||||
## v1.15.17
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.17)
|
||||
|
||||
## ما الذي تغيّر
|
||||
|
||||
### الميزات
|
||||
- إضافة وثائق تدفقات المحادثة التصريحية
|
||||
- توليف طرق المحادثة المدمجة للتصريحات
|
||||
- تمكين التصريحات من قيادة وضع المحادثة
|
||||
- جعل خيار الانضمام إلى المحادثة لا لبس فيه
|
||||
- حمل شريحة AMP على الأدوات المستخرجة من مرجع الشريحة
|
||||
- التعامل مع الرسائل الفردية الكبيرة أثناء تقسيمها
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- إصلاح استخدام اسم المضيف URL كاسم خادم MCP HTTP و SSE
|
||||
- إغلاق نطاق الوكيل في كل محاولة فاشلة
|
||||
- نسب أخطاء الأدوات إلى الأداة التي فشلت
|
||||
- تثبيت فحوصات SSRF على كل خطوة إعادة توجيه وعنوان IP النظير
|
||||
- حل المشكلات المتعلقة بالاستدعاءات الأصلية للأدوات المعطلة عبر واجهة برمجة تطبيقات استجابات OpenAI
|
||||
|
||||
### الوثائق
|
||||
- تحديث الوثائق مع لقطة وتغيير السجل للإصدار v1.15.16
|
||||
|
||||
## المساهمون
|
||||
|
||||
@Copilot, @Vidit-Ostwal, @github-code-quality[bot], @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="13 أغسطس 2026">
|
||||
## v1.15.16
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.16)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### الميزات
|
||||
- تقديم إدارة سياق التنفيذ مع دعم UUID
|
||||
- تسجيل نوع الاستثناء الذي أنهى تدفق العمل
|
||||
- تسجيل متى تم مشاركة دفعة تتبع مع AMP
|
||||
- عد عمليات النشر من أي مصدر وتسجيل مكان بدايتها
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- تسجيل الإصدار الجاري على كل نطاق تم إصداره
|
||||
- إصلاح التحقق من صحة اسم جدول البحث في MySQL
|
||||
- منع فشل دورة من تحديد الدورة التالية على أنها فاشلة
|
||||
|
||||
### الوثائق
|
||||
- إضافة أدلة الواجهة الأمامية لـ CopilotKit و AG-UI
|
||||
|
||||
## المساهمون
|
||||
|
||||
@joaomdmoura, @lorenzejay, @ranst91, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="11 أغسطس 2026">
|
||||
## v1.15.15
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.15)
|
||||
|
||||
## ما الذي تغيّر
|
||||
|
||||
### الميزات
|
||||
- الإبلاغ عن نتيجة التدفق، والمدة، وإشارات الإنسان في الحلقة.
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- إصدار FlowStartedEvent عندما يقوم خطاف الحدود بإلغاء التدفق.
|
||||
- تحديد نطاق تصدير النطاق لمزود المتعقب الخاص بنا.
|
||||
- ترقية torch إلى الإصدار 2.13.0 لمعالجة ثغرة أمنية.
|
||||
- ترقية gitpython إلى الإصدار 3.1.58 في crewai-tools[github].
|
||||
|
||||
### إعادة الهيكلة
|
||||
- تحديث وظيفة حقن التاريخ في الوكلاء.
|
||||
- توحيد علامات CLI إلى صيغة kebab-case.
|
||||
|
||||
### الوثائق
|
||||
- لقطة وتغيير السجل للإصدار v1.15.14.
|
||||
|
||||
## المساهمون
|
||||
|
||||
@Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="8 أغسطس 2026">
|
||||
## v1.15.14
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.14)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### الميزات
|
||||
- فصل سياق وقت التشغيل عن وكيل الترميز وإضافة معرف المشروع
|
||||
|
||||
### الوثائق
|
||||
- تحديث اللقطة وسجل التغييرات للإصدار v1.15.13
|
||||
|
||||
## المساهمون
|
||||
|
||||
@joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="7 أغسطس 2026">
|
||||
## 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
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="5 أغسطس 2026">
|
||||
## v1.15.12
|
||||
|
||||
[عرض الإصدار على GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.12)
|
||||
|
||||
## ما الذي تغير
|
||||
|
||||
### الميزات
|
||||
- زيادة إصدار Flow canary عند الإصدار
|
||||
- إضافة URLReadTool لقراءة عناوين URL العشوائية
|
||||
- إضافة بيانات التعريف الخاصة بالتطبيق إلى أدوات إجراءات المنصة
|
||||
- توحيد الهيكل تحت `crewai create <resource>`
|
||||
|
||||
### إصلاحات الأخطاء
|
||||
- توضيح أخطاء تصادم أسماء المسارات/المعالجين في المحادثات
|
||||
|
||||
### الوثائق
|
||||
- تحديث ملف AGENTS.md للهيكل الموحد لأداة سطر الأوامر لإنشاء
|
||||
|
||||
### تغييرات كبيرة
|
||||
- لا شيء
|
||||
|
||||
## المساهمون
|
||||
|
||||
@Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="4 أغسطس 2026">
|
||||
## 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
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="31 يوليو 2026">
|
||||
## v1.15.10
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ mode: "wide"
|
||||
| **احترام نافذة السياق** _(اختياري)_ | `respect_context_window` | `bool` | إبقاء الرسائل تحت حجم نافذة السياق عبر التلخيص. الافتراضي True. |
|
||||
| **وضع تنفيذ الكود** _(اختياري)_ | `code_execution_mode` | `Literal["safe", "unsafe"]` | وضع تنفيذ الكود: 'safe' (باستخدام Docker) أو 'unsafe' (مباشر). الافتراضي 'safe'. |
|
||||
| **متعدد الوسائط** _(اختياري)_ | `multimodal` | `bool` | ما إذا كان الوكيل يدعم القدرات متعددة الوسائط. الافتراضي False. |
|
||||
| **حقن التاريخ** _(اختياري)_ | `inject_date` | `bool` | ما إذا كان يتم حقن التاريخ الحالي تلقائيًا في أمر الوكيل. الافتراضي False. |
|
||||
| **حقن التاريخ** _(اختياري)_ | `inject_date` | `bool` | ما إذا كان يتم حقن التاريخ الحالي تلقائيًا في المهام. الافتراضي False. |
|
||||
| **تنسيق التاريخ** _(اختياري)_ | `date_format` | `str` | سلسلة تنسيق التاريخ عند تفعيل inject_date. الافتراضي "%Y-%m-%d" (تنسيق ISO). |
|
||||
| **الاستدلال** _(اختياري)_ | `reasoning` | `bool` | ما إذا كان يجب على الوكيل التأمل وإنشاء خطة قبل تنفيذ المهمة. الافتراضي False. |
|
||||
| **الحد الأقصى لمحاولات الاستدلال** _(اختياري)_ | `max_reasoning_attempts` | `Optional[int]` | الحد الأقصى لمحاولات الاستدلال قبل تنفيذ المهمة. إذا None، سيحاول حتى الاستعداد. |
|
||||
@@ -287,7 +287,7 @@ analysis_agent = Agent(
|
||||
|
||||
- `multimodal`: تفعيل القدرات متعددة الوسائط لمعالجة النص والمحتوى المرئي
|
||||
- `reasoning`: تمكين الوكيل من التأمل وإنشاء خطط قبل تنفيذ المهام
|
||||
- `inject_date`: حقن التاريخ الحالي تلقائيًا في أمر الوكيل
|
||||
- `inject_date`: حقن التاريخ الحالي تلقائيًا في أوصاف المهام
|
||||
|
||||
#### القوالب
|
||||
|
||||
|
||||
@@ -54,16 +54,6 @@ 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`.
|
||||
|
||||
#### أسماء مستعار قديمة للأعلام (مهملة)
|
||||
|
||||
لا تزال أعلام snake_case القديمة تعمل، لكنها مخفية من `--help`. يُفضّل استخدام صيغ kebab-case الموثّقة في أقسام الأوامر أدناه.
|
||||
|
||||
| مهمل | استخدم بدلاً منه |
|
||||
| :--- | :--- |
|
||||
| `--skip_provider` (في `crewai create crew`) | `--skip-provider` |
|
||||
| `--n_iterations` (في `crewai train`، `crewai test`) | `--n-iterations` |
|
||||
| `--task_id` (في `crewai replay`) | `--task-id` |
|
||||
|
||||
### 2. الإصدار
|
||||
|
||||
عرض الإصدار المثبت من CrewAI.
|
||||
@@ -82,7 +72,7 @@ crewai version [OPTIONS]
|
||||
crewai train [OPTIONS]
|
||||
```
|
||||
|
||||
- `-n, --n-iterations INTEGER`: عدد تكرارات التدريب (افتراضي: 5)
|
||||
- `-n, --n_iterations INTEGER`: عدد تكرارات التدريب (افتراضي: 5)
|
||||
- `-f, --filename TEXT`: مسار ملف مخصص للتدريب (افتراضي: "trained_agents_data.pkl")
|
||||
|
||||
### 4. الإعادة
|
||||
@@ -93,7 +83,7 @@ crewai train [OPTIONS]
|
||||
crewai replay [OPTIONS]
|
||||
```
|
||||
|
||||
- `-t, --task-id TEXT`: إعادة تنفيذ الطاقم من معرّف المهمة هذا، بما في ذلك جميع المهام اللاحقة
|
||||
- `-t, --task_id TEXT`: إعادة تنفيذ الطاقم من معرّف المهمة هذا، بما في ذلك جميع المهام اللاحقة
|
||||
|
||||
### 5. سجل مخرجات المهام
|
||||
|
||||
@@ -127,7 +117,7 @@ crewai reset-memories [OPTIONS]
|
||||
crewai test [OPTIONS]
|
||||
```
|
||||
|
||||
- `-n, --n-iterations INTEGER`: عدد تكرارات الاختبار (افتراضي: 3)
|
||||
- `-n, --n_iterations INTEGER`: عدد تكرارات الاختبار (افتراضي: 3)
|
||||
- `-m, --model TEXT`: نموذج LLM لتشغيل الاختبارات (افتراضي: "gpt-4o-mini")
|
||||
|
||||
### 8. التشغيل
|
||||
|
||||
@@ -172,8 +172,6 @@ class YourCrewName:
|
||||
|
||||
بعد تنفيذ الطاقم، يمكنك الوصول إلى خاصية `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()
|
||||
|
||||
@@ -266,24 +266,6 @@ print(flow.usage_metrics)
|
||||
كلما احتجت إلى الإجمالي **الكامل** للتوكنات لتنفيذ التدفق.
|
||||
</Note>
|
||||
|
||||
### دلالات حقول 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()`؛ قراءتها أثناء التنفيذ تُرجع المجموع الجزئي المتراكم حتى تلك اللحظة.
|
||||
|
||||
## إدارة حالة التدفق
|
||||
|
||||
@@ -392,22 +392,6 @@ mode: "wide"
|
||||
- تتبع استخدام الرموز
|
||||
- محادثات استخدام أدوات متعددة الأدوار
|
||||
|
||||
**استخدام الرموز والتخزين المؤقت للمطالبة:**
|
||||
|
||||
يُبلّغ 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`
|
||||
|
||||
@@ -20,7 +20,7 @@ crewai test
|
||||
إذا أردت تشغيل المزيد من التكرارات أو استخدام نموذج مختلف، يمكنك تحديد المعاملات هكذا:
|
||||
|
||||
```bash
|
||||
crewai test --n-iterations 5 --model gpt-4o
|
||||
crewai test --n_iterations 5 --model gpt-4o
|
||||
```
|
||||
|
||||
أو باستخدام الصيغة المختصرة:
|
||||
@@ -29,11 +29,6 @@ crewai test --n-iterations 5 --model gpt-4o
|
||||
crewai test -n 5 -m gpt-4o
|
||||
```
|
||||
|
||||
<Note>
|
||||
العلم القديم `--n_iterations` لا يزال يعمل، لكنه مهمل ومخفي من `--help`.
|
||||
استخدم `--n-iterations` (أو `-n`) بدلاً من ذلك.
|
||||
</Note>
|
||||
|
||||
عند تشغيل أمر `crewai test`، سيتم تنفيذ الطاقم للعدد المحدد من التكرارات، وستُعرض مقاييس الأداء في نهاية التشغيل.
|
||||
|
||||
سيظهر جدول الدرجات في النهاية لعرض أداء الطاقم من حيث المقاييس التالية:
|
||||
|
||||
@@ -426,70 +426,6 @@ class SupportFlow(Flow[ConversationState]):
|
||||
|
||||
يمكن لـ `ConversationConfig.visible_agent_outputs` رفع النتائج الخاصة لـ agents محددين إلى عامة عالمياً (`"all"` أو قائمة بالأسماء).
|
||||
|
||||
## تعريف تدفق محادثاتي بصيغة JSON/YAML
|
||||
|
||||
يمكن لـ [التدفق التعريفي](/edge/en/concepts/cli) أن يكون محادثاتيًا أيضًا. أضف كتلة `conversational` في المستوى الأعلى وعرّف مساراتك الخاصة كطرق تستمع (`listen`) إلى تسمية مسار:
|
||||
|
||||
```yaml
|
||||
schema: crewai.flow/v1
|
||||
name: SupportFlow
|
||||
|
||||
conversational:
|
||||
system_prompt: You are a terse support assistant.
|
||||
llm: gpt-4o-mini
|
||||
router:
|
||||
llm: gpt-4o-mini
|
||||
|
||||
methods:
|
||||
handle_order:
|
||||
description: Order status, shipping and delivery questions.
|
||||
listen: order
|
||||
do:
|
||||
call: agent
|
||||
with:
|
||||
role: Support specialist
|
||||
goal: Answer order questions accurately
|
||||
backstory: Knows the fulfilment pipeline.
|
||||
input: "${state.current_user_message}"
|
||||
```
|
||||
|
||||
تعريف الكتلة هو الاشتراك نفسه — القيمة الافتراضية لـ `enabled` هي `true`. اضبطها على `enabled: false` للاحتفاظ بالإعدادات مع إيقاف المحادثة.
|
||||
|
||||
تُوفَّر لك ثلاثة أشياء:
|
||||
|
||||
| المُوفَّر | التفاصيل |
|
||||
|----------|--------|
|
||||
| الرسم البياني المدمج | تُضاف `route_conversation` و`converse_turn` و`end_conversation` و`answer_from_history_turn` تلقائيًا. عرّف طريقة بأحد هذه الأسماء لتجاوزها. |
|
||||
| حالة المحادثة | تُستخدم `ConversationState` عندما لا تحتوي التعريفة على كتلة `state`. لإضافة حقول، وجّه `state` إلى نموذج Pydantic يرث من `ConversationState`. |
|
||||
| كتالوج المسارات | يُبنى من الطرق التي تعلن تسمية `listen`. وصف كل طريقة (`description`) هو ما يقرأه نموذج التوجيه عند الاختيار بين المسارات. |
|
||||
|
||||
شغّله من Python بنفس واجهات الجولة المستخدمة مع تدفق محادثاتي معرّف بصنف:
|
||||
|
||||
```python
|
||||
from crewai.flow import Flow
|
||||
|
||||
flow = Flow.from_declaration(path="flow.yaml")
|
||||
|
||||
try:
|
||||
flow.handle_turn("Where is my order?", session_id="session-1")
|
||||
finally:
|
||||
flow.finalize_session_traces()
|
||||
```
|
||||
|
||||
### تسمية المسارات
|
||||
|
||||
تتشارك تسميات المسارات وأسماء الطرق مساحة اسم واحدة للمشغّلات، لذا يجب ألا يحمل المعالج اسم المسار الذي يستمع إليه — يُرفض `create_video` الذي يستمع إلى `create_video` عند بناء التدفق. استخدم بادئة `handle_*`.
|
||||
|
||||
### ما لا يمكن للتعريفة التعبير عنه
|
||||
|
||||
| غير قابل للتعبير | استخدم بدلًا منه |
|
||||
|-----------------|-------------|
|
||||
| مثيل `LLM` حي أو `BaseLLM` مخصص | سلسلة معرّف النموذج، مثل `gpt-4o-mini` |
|
||||
| `router.response_format` كصنف نموذج | احذفه؛ يولّد الإطار واحدًا. يُتجاهل المرجع أو المخطط مع تحذير |
|
||||
| تجاوزات `route_turn()` / `can_answer_from_history()` | اكتب التدفق بلغة Python، أو وجّه `do` لطريقة إلى مرجع `call: code` |
|
||||
|
||||
لا يملك `crewai run` حلقة محادثة بعد: فهو يبلّغ أن التدفق محادثاتي ويخرج بدلًا من تنفيذ جولة واحدة. شغّل التدفق المحادثاتي التعريفي من Python عبر `handle_turn()` أو `stream_turn()` أو `chat()`.
|
||||
|
||||
## التتبع عبر الجولات
|
||||
|
||||
مع `defer_trace_finalization=True` (افتراضي في `ConversationalConfig`):
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
---
|
||||
title: خطافات حدود التنفيذ
|
||||
description: اعتراض بداية تنفيذ الـ Crew والـ Flow ومدخلاته ومخرجاته ونهايته باستخدام المزخرف @on
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
تعترض خطافات حدود التنفيذ الأطراف الخارجية للتشغيل — قبل بدء أي عمل، وعند
|
||||
حسم المدخلات، وعند جاهزية النتيجة النهائية، وعند انتهاء التنفيذ. وهي تعمل مع
|
||||
الـ Crew والـ Flow على حد سواء، وتُعد المكان المناسب لفحوصات السياسة على
|
||||
مستوى التشغيل وإعادة كتابة المدخلات وتنقية المخرجات.
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
أربع نقاط اعتراض تغطي الحدود:
|
||||
|
||||
| النقطة | التوقيت | `ctx.payload` |
|
||||
|--------|---------|---------------|
|
||||
| `EXECUTION_START` | Crew أو Flow على وشك البدء | `dict` المدخلات |
|
||||
| `INPUT` | المدخلات المحسومة للتنفيذ | `dict` المدخلات |
|
||||
| `OUTPUT` | النتيجة النهائية جاهزة | كائن المخرجات |
|
||||
| `EXECUTION_END` | انتهى التنفيذ (نجاحًا أو فشلًا) | كائن المخرجات، أو `None` عند الفشل |
|
||||
|
||||
بالنسبة إلى الـ Crew، يكون payload المخرجات `CrewOutput`. أما في الـ Flow فهو
|
||||
النتيجة النهائية لدالة الـ Flow.
|
||||
|
||||
## توقيع الخطاف
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
تتبع خطافات الحدود العقد القياسي: المتابعة (`return None`)، أو التعديل في
|
||||
المكان، أو الاستبدال بإرجاع قيمة، أو الإجهاض برفع `HookAborted`. أي إجهاض
|
||||
عند أي حد ينتشر خارج `kickoff()` مع سببه.
|
||||
|
||||
## مخطط السياق
|
||||
|
||||
تتلقى كل نقطة سياقًا منمّطًا. تشترك جميع السياقات في الحقول الأساسية:
|
||||
|
||||
```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)
|
||||
```
|
||||
|
||||
تضيف سياقات كل نقطة اسمًا بديلًا للـ 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"
|
||||
```
|
||||
|
||||
<Note>
|
||||
`ctx.inputs` هو اسم بديل لقاموس المدخلات **الأصلي**، لذا فإن التعديلات في
|
||||
المكان عبر أي من الاسمين متكافئة. إذا *استبدل* خطاف سابق الـ payload بإرجاع
|
||||
dict جديد، فإن `ctx.payload` وحده يُعاد ربطه — اقرأ واكتب دائمًا عبر
|
||||
`ctx.payload` عندما يمكن أن تتسلسل الخطافات.
|
||||
</Note>
|
||||
|
||||
## تشغيلات الـ Crew مقابل تشغيلات الـ Flow
|
||||
|
||||
تعمل خطافات الحدود على كلا وقتي التشغيل، وتنفيذ الـ Crew يجري داخليًا فوق وقت
|
||||
تشغيل Flow. لذلك أثناء `crew.kickoff()` يُطلق الخطاف الحدودي العام لحدّ الـ
|
||||
Crew (`ctx.crew` مضبوط و`ctx.flow` يساوي `None`) **و** للـ Flow الداخلي
|
||||
(`ctx.flow` مضبوط و`ctx.crew` يساوي `None`). ميّز حسب وقت التشغيل:
|
||||
|
||||
```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()
|
||||
```
|
||||
|
||||
## حالات استخدام شائعة
|
||||
|
||||
### فحص السياسة عند البدء
|
||||
|
||||
```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")
|
||||
```
|
||||
|
||||
### إعادة كتابة المدخلات
|
||||
|
||||
```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()
|
||||
```
|
||||
|
||||
تتدفق المدخلات المعاد كتابتها إلى استيفاء الـ Task، فيتصرف التشغيل كما لو
|
||||
بدأ بالقاموس المعدل.
|
||||
|
||||
فضّل `INPUT` لإعادة الكتابة وعامل `EXECUTION_START` كبوابة سماح/منع. إعادة
|
||||
الكتابة عند `EXECUTION_START` تظل مُحترمة — في الـ Crew تغذي أيضًا استدعاءات
|
||||
`before_kickoff`؛ وفي الـ Flow تُطبق تمامًا كإعادة كتابة `INPUT`.
|
||||
|
||||
### تنقية المخرجات
|
||||
|
||||
```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` قبل `EXECUTION_END`، وكلاهما يرى الـ payload (الذي ربما
|
||||
استُبدل) من الخطافات السابقة؛ والقيمة النهائية المعاد كتابتها هي ما يعيده
|
||||
`kickoff()`.
|
||||
|
||||
### مراقبة الإخفاقات
|
||||
|
||||
يُطلق `EXECUTION_END` مرة واحدة بالضبط لكل تنفيذ، عند النجاح والفشل على حد
|
||||
سواء. عندما يرفع التشغيل استثناءً — خطأ في Task، أو استثناء في دالة Flow، أو
|
||||
`HookAborted` من نقطة سابقة — يتلقى الخطاف `status="failed"` مع الاستثناء في
|
||||
`ctx.error`، ويظل الاستثناء الأصلي ينتشر خارج `kickoff()` دون تغيير:
|
||||
|
||||
```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")
|
||||
```
|
||||
|
||||
تنبيهان: لا يُطلق `EXECUTION_END` عندما لا يكون `EXECUTION_START` قد أُرسل
|
||||
أصلًا (الإجهاض عند البدء يعني أن الحد لم يُفتح قط، فلا توجد نهاية تقابله)،
|
||||
ورفع `HookAborted` من إرسال `EXECUTION_END` في مسار الفشل يُتجاهل — لم يعد
|
||||
هناك ما يُجهض، والخطأ الأصلي هو الغالب.
|
||||
|
||||
## الترتيب
|
||||
|
||||
لتشغيل Crew يكون ترتيب الحدود:
|
||||
|
||||
```
|
||||
EXECUTION_START → before_kickoff callbacks → INPUT → tasks execute → OUTPUT → EXECUTION_END
|
||||
```
|
||||
|
||||
لتشغيل Flow، تحسم خطافات الحدود المدخلات قبل أن تبدأ أحداث دورة الحياة:
|
||||
|
||||
```
|
||||
EXECUTION_START → INPUT → FlowStartedEvent → flow methods execute → OUTPUT → EXECUTION_END → FlowFinishedEvent
|
||||
```
|
||||
|
||||
يحمل `FlowStartedEvent` المدخلات كما حسمتها الخطافات، وإعادة كتابة
|
||||
`inputs["id"]` داخل خطاف حدودي تعيد توجيه استعادة الحالة. يظهر الإجهاض عند
|
||||
`EXECUTION_START` مع ذلك كحدث `FlowStartedEvent` يتبعه `FlowFailedEvent`،
|
||||
ويُبثان عند الإجهاض مع الحمولة كما حسمتها الخطافات التي عملت قبله.
|
||||
|
||||
تعمل الخطافات في النقطة نفسها حسب ترتيب التسجيل، الخطافات العامة أولًا ثم
|
||||
الخطافات المحدودة بالـ Crew. تُبث القياسات (`HookDispatchedEvent`) مع كل
|
||||
إرسال.
|
||||
|
||||
## إدارة الخطافات في الاختبارات
|
||||
|
||||
```python
|
||||
from crewai.hooks import clear_all_hooks
|
||||
|
||||
clear_all_hooks() # Clears every point, including boundaries
|
||||
```
|
||||
|
||||
## وثائق ذات صلة
|
||||
|
||||
- [نظرة عامة على خطافات التنفيذ →](/edge/ar/learn/execution-hooks)
|
||||
- [خطافات استدعاء LLM →](/edge/ar/learn/llm-hooks)
|
||||
- [خطافات استدعاء الأدوات →](/edge/ar/learn/tool-hooks)
|
||||
@@ -34,20 +34,6 @@ os.environ['CREWAI_DISABLE_TELEMETRY'] = 'true'
|
||||
os.environ['OTEL_SDK_DISABLED'] = 'true'
|
||||
```
|
||||
|
||||
### العزل عن إعداد OpenTelemetry الخاص بك
|
||||
|
||||
يعمل القياس عن بُعد الخاص بـ CrewAI على `TracerProvider` خاص به ولا يسجل نفسه
|
||||
أبدًا كمزوّد عام. هذا يفصل الاتجاهين:
|
||||
|
||||
- لا تُرسَل أبدًا إلى CrewAI الامتدادات (spans) الصادرة عن المكتبات الأخرى
|
||||
المزوّدة بأدوات القياس في عمليتك — أطر الويب، وعملاء قواعد البيانات،
|
||||
وعملاء HTTP.
|
||||
- لا تُرسَل امتدادات القياس عن بُعد الخاصة بـ CrewAI إلى نظام المراقبة لديك، لذا
|
||||
لن تظهر في Langfuse أو Braintrust أو Phoenix أو أي مُجمِّع آخر تقوم بإعداده.
|
||||
|
||||
لا تتأثر تكاملات المراقبة: فهي تقيس CrewAI عبر مزوّد التتبع الخاص بها، وهو
|
||||
مستقل عن المزوّد الموصوف هنا.
|
||||
|
||||
### شرح البيانات:
|
||||
| افتراضي | البيانات | السبب والتفاصيل |
|
||||
|:----------|:------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------|
|
||||
@@ -59,10 +45,7 @@ os.environ['OTEL_SDK_DISABLED'] = 'true'
|
||||
| نعم | بيانات تنفيذ الاختبار | تشمل: مفتاح ومعرّف الطاقم المُولّد عشوائياً، عدد التكرارات، اسم النموذج المستخدم، درجة الجودة (عدد عشري)، وقت التنفيذ (بالثواني). كلها غير شخصية. |
|
||||
| نعم | بيانات دورة حياة المهمة | تشمل: أوقات الإنشاء وبدء/انتهاء التنفيذ، معرّفات الطاقم والمهمة. مخزنة كنطاقات مع طوابع زمنية. لا بيانات شخصية. |
|
||||
| نعم | سمات LLM | تشمل: الاسم، model_name، model، top_k، temperature، واسم فئة LLM. كلها بيانات تقنية غير شخصية. |
|
||||
| نعم | محاولة نشر الطاقم باستخدام CLI الخاص بـ CrewAI | تشمل: حقيقة إجراء النشر ومعرّف الطاقم، وما إذا كان يحاول سحب السجلات، وما إذا بدأ النشر من أمر CLI أو من واجهة التشغيل TUI. لا تُسجَّل محتويات المشروع أو الطاقم. لا توجد بيانات شخصية. |
|
||||
| نعم | بيئة التنفيذ | تشمل: مساعد البرمجة بالذكاء الاصطناعي الذي يشغّل العملية إن وُجد (واحد من قائمة ثابتة مثل `claude_code` أو `codex` أو `cursor` أو `unknown`)، ومكان تشغيل العملية (واحد من قائمة ثابتة مثل `ci` أو `container` أو `serverless` أو `interactive`)، و`project_id` من ملف `pyproject.toml` عند ضبطه. يتحقق الاكتشاف فقط مما إذا كانت متغيرات البيئة المعروفة مضبوطة، ولا يقرأ قيمها أبدًا. لا بيانات شخصية. |
|
||||
| نعم | إشارات دورة حياة التدفق | تشمل: بدء التدفق، وما إذا اكتمل أو فشل، وما إذا فشلت إحدى طرقه، وما إذا توقف مؤقتًا لانتظار إدخال أو ملاحظات بشرية، وما إذا كان البدء تشغيلًا مستأنفًا، وما إذا فشل دور محادثة، ومدة تشغيل التدفق، وما إذا كان التدفق مما تشغّله CrewAI داخليًا أو مما كتبته أنت. ويُسجَّل اسم التدفق، كما هو الحال بالفعل لإنشاء التدفق وتنفيذه. وعند فشل تدفق أو إحدى طرقه، يُسجَّل **اسم فئة** الاستثناء (مثل `TimeoutError`) لتشخيص الأعطال — ولا تُسجَّل أبدًا رسالة الخطأ، التي قد تحتوي على مطالبات أو مخرجات النموذج أو مسارات ملفات أو بيانات اعتماد. ولا تُسجَّل أبدًا أسماء الطرق أو حالة التدفق. لا توجد بيانات شخصية. |
|
||||
| نعم | إشارة مشاركة التتبع | تشمل: نجاح مشاركة دفعة من عمليات التتبع مع CrewAI AMP، وما إذا تمت المشاركة بشكل مجهول (قبل إنشاء حساب) أو مرتبطة بحسابك. ومثل كل span، تحمل أيضًا سمات بيئة التنفيذ الموضحة أعلاه (`project_id` عند تكوينه، ومساعد البرمجة، وبيئة التشغيل). يصف هذا الصف بيانات القياس عن بُعد الخاصة بالمشاركة فقط — وليس محتويات التتبع أو الوصول الذي تمنحه روابط التتبع المشتركة. لا تُسجَّل محتويات التتبع أو المدخلات أو المخرجات في هذه الإشارة. قبل مشاركة التتبعات، راجع الأسرار والبيانات الشخصية وإعدادات التنقيح والاحتفاظ في AMP. |
|
||||
| نعم | محاولة نشر الطاقم باستخدام CLI الخاص بـ CrewAI | تشمل: حقيقة إجراء النشر ومعرّف الطاقم، وما إذا كان يحاول سحب السجلات، لا بيانات أخرى. |
|
||||
| لا | بيانات الوكيل الموسّعة | تشمل: وصف الهدف، نص الخلفية، معرّف ملف موجهات i18n. يجب على المستخدمين التأكد من عدم تضمين معلومات شخصية في حقول النص. |
|
||||
| لا | معلومات المهمة التفصيلية | تشمل: وصف المهمة، وصف المخرجات المتوقعة، مراجع السياق. يجب على المستخدمين التأكد من عدم تضمين معلومات شخصية في هذه الحقول. |
|
||||
| لا | معلومات البيئة | تشمل: المنصة، الإصدار، النظام، الإصدار، وعدد وحدات المعالجة المركزية. مثال: 'Windows 10'، 'x86_64'. لا بيانات شخصية. |
|
||||
|
||||
@@ -9,7 +9,7 @@ mode: "wide"
|
||||
|
||||
## الوصف
|
||||
|
||||
أداة `ScrapeElementFromWebsiteTool` مصممة لاستخراج عناصر محددة من المواقع باستخدام محددات CSS. تسمح هذه الأداة لوكلاء CrewAI باستخراج محتوى مستهدف من صفحات الويب، مما يجعلها مفيدة لمهام استخراج البيانات حيث تكون أجزاء محددة فقط من صفحة الويب مطلوبة. تمر الطلبات عبر مساعد HTTP الآمن ضد SSRF في CrewAI: يتم فحص عنوان URL المطلوب وكل قفزة إعادة توجيه مقابل النطاقات الخاصة والمحجوزة (بما في ذلك بيانات تعريف السحابة)، ويُثبَّت اتصال TCP على عنوان IP الذي اجتاز هذا الفحص.
|
||||
أداة `ScrapeElementFromWebsiteTool` مصممة لاستخراج عناصر محددة من المواقع باستخدام محددات CSS. تسمح هذه الأداة لوكلاء CrewAI باستخراج محتوى مستهدف من صفحات الويب، مما يجعلها مفيدة لمهام استخراج البيانات حيث تكون أجزاء محددة فقط من صفحة الويب مطلوبة.
|
||||
|
||||
## التثبيت
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ mode: "wide"
|
||||
أداة مصممة لاستخراج وقراءة محتوى موقع محدد. قادرة على التعامل مع أنواع مختلفة من صفحات الويب عن طريق إجراء طلبات HTTP وتحليل محتوى HTML المستلم.
|
||||
يمكن أن تكون هذه الأداة مفيدة بشكل خاص لمهام استخراج البيانات من الويب وجمع البيانات أو استخراج معلومات محددة من المواقع.
|
||||
|
||||
تمر الطلبات عبر مساعد HTTP الآمن ضد SSRF في CrewAI: يتم فحص عنوان URL المطلوب وكل قفزة إعادة توجيه مقابل النطاقات الخاصة والمحجوزة (بما في ذلك بيانات تعريف السحابة)، ويُثبَّت اتصال TCP على عنوان IP الذي اجتاز هذا الفحص.
|
||||
|
||||
## التثبيت
|
||||
|
||||
ثبّت حزمة crewai_tools
|
||||
|
||||
@@ -4,192 +4,6 @@ description: "Product updates, improvements, and bug fixes for CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="Aug 19, 2026">
|
||||
## v1.15.17
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.17)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Add declarative conversational flows documentation
|
||||
- Synthesize built-in conversational methods for declarations
|
||||
- Enable declarations to drive conversational mode
|
||||
- Make conversational opt-in unmistakable
|
||||
- Carry the AMP slug on tools resolved from a slug reference
|
||||
- Handle oversized single messages during chunking
|
||||
|
||||
### Bug Fixes
|
||||
- Fix usage of the URL hostname as MCP HTTP and SSE server_name
|
||||
- Close the agent scope on every failed attempt
|
||||
- Attribute tool errors to the tool that failed
|
||||
- Pin SSRF checks to each redirect hop and peer IP
|
||||
- Resolve issues with native tool calls broken over OpenAI Responses API
|
||||
|
||||
### Documentation
|
||||
- Update documentation with a snapshot and changelog for v1.15.16
|
||||
|
||||
## Contributors
|
||||
|
||||
@Copilot, @Vidit-Ostwal, @github-code-quality[bot], @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Aug 13, 2026">
|
||||
## v1.15.16
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.16)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Introduce execution context management with UUID support
|
||||
- Record what kind of exception ended a flow
|
||||
- Record when a trace batch is shared with AMP
|
||||
- Count deployments from any origin and record where they started
|
||||
|
||||
### Bug Fixes
|
||||
- Record the running release on every emitted span
|
||||
- Fix MySQL search table name validation
|
||||
- Stop a failed turn from marking the next one as failed
|
||||
|
||||
### Documentation
|
||||
- Add Frontend guides for CopilotKit and AG-UI
|
||||
|
||||
## Contributors
|
||||
|
||||
@joaomdmoura, @lorenzejay, @ranst91, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Aug 11, 2026">
|
||||
## v1.15.15
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.15)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Report flow outcome, duration, and human-in-the-loop signals.
|
||||
|
||||
### Bug Fixes
|
||||
- Emit FlowStartedEvent when a boundary hook aborts the flow.
|
||||
- Scope span export to our own tracer provider.
|
||||
- Bump torch to version 2.13.0 to address security vulnerability.
|
||||
- Bump gitpython to version 3.1.58 in crewai-tools[github].
|
||||
|
||||
### Refactoring
|
||||
- Update date injection functionality in agents.
|
||||
- Standardize CLI flags to kebab-case.
|
||||
|
||||
### Documentation
|
||||
- Snapshot and changelog for v1.15.14.
|
||||
|
||||
## Contributors
|
||||
|
||||
@Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Aug 08, 2026">
|
||||
## v1.15.14
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.14)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Split runtime context from coding agent and add project ID
|
||||
|
||||
### Documentation
|
||||
- Update snapshot and changelog for v1.15.13
|
||||
|
||||
## Contributors
|
||||
|
||||
@joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Aug 07, 2026">
|
||||
## 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
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Aug 05, 2026">
|
||||
## v1.15.12
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.12)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Bump Flow canary on release
|
||||
- Add URLReadTool for reading arbitrary URLs
|
||||
- Add app metadata to platform action tools
|
||||
- Unify scaffolding under `crewai create <resource>`
|
||||
|
||||
### Bug Fixes
|
||||
- Clarify conversational route/handler name collision errors
|
||||
|
||||
### Documentation
|
||||
- Update scaffold AGENTS.md for unified create CLI
|
||||
|
||||
### Breaking Changes
|
||||
- None
|
||||
|
||||
## Contributors
|
||||
|
||||
@Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Aug 04, 2026">
|
||||
## v1.15.11
|
||||
|
||||
[View release on GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.11)
|
||||
|
||||
## What's Changed
|
||||
|
||||
### Features
|
||||
- Track interception-hook dispatches in telemetry
|
||||
- Add project_id to link OSS usage to an enterprise account
|
||||
- Surface AMP in AGENTS.md and detect coding agents in telemetry
|
||||
- Add IBM Db2 search tool
|
||||
|
||||
### Bug Fixes
|
||||
- Clear CodeQL incomplete URL substring sanitization alerts
|
||||
- Bump aiohttp and cryptography to clear six GHSA advisories
|
||||
- Report the real CEL error for failures inside map literals
|
||||
- Correctly skip code CI for docs-only PRs
|
||||
|
||||
### Documentation
|
||||
- Snapshot and changelog for v1.15.10
|
||||
|
||||
## Contributors
|
||||
|
||||
@PawanThakurIBM, @Vidit-Ostwal, @gabemilani, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="Jul 31, 2026">
|
||||
## v1.15.10
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ The Visual Agent Builder enables:
|
||||
| **Respect Context Window** _(optional)_ | `respect_context_window` | `bool` | Keep messages under context window size by summarizing. Default is True. |
|
||||
| **Code Execution Mode** _(optional)_ | `code_execution_mode` | `Literal["safe", "unsafe"]` | Mode for code execution: 'safe' (using Docker) or 'unsafe' (direct). Default is 'safe'. |
|
||||
| **Multimodal** _(optional)_ | `multimodal` | `bool` | Whether the agent supports multimodal capabilities. Default is False. |
|
||||
| **Inject Date** _(optional)_ | `inject_date` | `bool` | Whether to automatically inject the current date into the agent's prompt. Default is False. |
|
||||
| **Inject Date** _(optional)_ | `inject_date` | `bool` | Whether to automatically inject the current date into tasks. Default is False. |
|
||||
| **Date Format** _(optional)_ | `date_format` | `str` | Format string for date when inject_date is enabled. Default is "%Y-%m-%d" (ISO format). |
|
||||
| **Reasoning** _(optional)_ | `reasoning` | `bool` | Whether the agent should reflect and create a plan before executing a task. Default is False. |
|
||||
| **Max Reasoning Attempts** _(optional)_ | `max_reasoning_attempts` | `Optional[int]` | Maximum number of reasoning attempts before executing the task. If None, will try until ready. |
|
||||
@@ -236,7 +236,7 @@ strategic_agent = Agent(
|
||||
role="Market Analyst",
|
||||
goal="Track market movements with precise date references and strategic planning",
|
||||
backstory="Expert in time-sensitive financial analysis and strategic reporting",
|
||||
inject_date=True, # Automatically inject current date into the prompt
|
||||
inject_date=True, # Automatically inject current date into tasks
|
||||
date_format="%B %d, %Y", # Format as "May 21, 2025"
|
||||
reasoning=True, # Enable strategic planning
|
||||
max_reasoning_attempts=2, # Limit planning iterations
|
||||
@@ -303,7 +303,7 @@ multimodal_agent = Agent(
|
||||
|
||||
- `multimodal`: Enable multimodal capabilities for processing text and visual content
|
||||
- `reasoning`: Enable agent to reflect and create plans before executing tasks
|
||||
- `inject_date`: Automatically inject current date into the agents prompt
|
||||
- `inject_date`: Automatically inject current date into task descriptions
|
||||
|
||||
#### Templates
|
||||
|
||||
|
||||
@@ -36,83 +36,24 @@ crewai [COMMAND] [OPTIONS] [ARGUMENTS]
|
||||
|
||||
### 1. Create
|
||||
|
||||
Create a new crew, flow, tool, skill, or template project.
|
||||
Create a new crew or flow.
|
||||
|
||||
```shell Terminal
|
||||
crewai create [OPTIONS] TYPE NAME
|
||||
```
|
||||
|
||||
- `TYPE`: `crew`, `flow`, `tool`, `skill`, or `template`
|
||||
- `NAME`: Name of the project, tool handle, skill, or template
|
||||
- `TYPE`: Choose between "crew" or "flow"
|
||||
- `NAME`: Name of the crew or flow
|
||||
|
||||
#### Crew
|
||||
Example:
|
||||
|
||||
```shell Terminal
|
||||
crewai create crew my_new_crew
|
||||
crewai create crew my_new_crew --classic
|
||||
crewai create flow my_new_flow
|
||||
```
|
||||
|
||||
By default, `crewai create crew` creates a JSON-first crew project with `crew.jsonc` and `agents/*.jsonc`. Use `crewai create crew my_new_crew --classic` only when you want the older Python/YAML scaffold with `crew.py`, `config/agents.yaml`, and `config/tasks.yaml`.
|
||||
|
||||
#### Flow
|
||||
|
||||
```shell Terminal
|
||||
crewai create flow my_new_flow
|
||||
crewai create flow my_new_flow --declarative
|
||||
```
|
||||
|
||||
#### Tool
|
||||
|
||||
Scaffold a custom tool repository:
|
||||
|
||||
```shell Terminal
|
||||
crewai create tool my_tool
|
||||
```
|
||||
|
||||
#### Skill
|
||||
|
||||
Scaffold an agent skill. Inside a crew project (where `pyproject.toml` exists), the skill is created under `./skills/`:
|
||||
|
||||
```shell Terminal
|
||||
crewai create skill my-skill
|
||||
crewai create skill my-skill --no-project
|
||||
```
|
||||
|
||||
Use `--no-project` to create the skill in the current directory instead of `./skills/`.
|
||||
|
||||
#### Template
|
||||
|
||||
Add a remote project template to the current directory:
|
||||
|
||||
```shell Terminal
|
||||
crewai create template my-template
|
||||
crewai create template my-template --output-dir custom_dir
|
||||
```
|
||||
|
||||
Use `--output-dir` to override the output folder name (defaults to the template name).
|
||||
|
||||
#### Deprecated create aliases
|
||||
|
||||
These older commands still work but print a yellow deprecation warning. Prefer the `crewai create <type>` forms above.
|
||||
|
||||
| Deprecated | Use instead |
|
||||
| :--- | :--- |
|
||||
| `crewai tool create <handle>` | `crewai create tool <handle>` |
|
||||
| `crewai skill create <name>` | `crewai create skill <name>` |
|
||||
| `crewai template add <name>` | `crewai create template <name>` |
|
||||
|
||||
Lifecycle commands are unchanged — for example `crewai tool install`, `crewai skill publish`, and `crewai template list` stay under their resource groups.
|
||||
|
||||
#### Deprecated flag aliases
|
||||
|
||||
These older snake_case flags still work but are hidden from `--help`. Prefer the kebab-case forms documented in each command section below.
|
||||
|
||||
| Deprecated | Use instead |
|
||||
| :--- | :--- |
|
||||
| `--skip_provider` (on `crewai create crew`) | `--skip-provider` |
|
||||
| `--n_iterations` (on `crewai train`, `crewai test`) | `--n-iterations` |
|
||||
| `--task_id` (on `crewai replay`) | `--task-id` |
|
||||
|
||||
### 2. Version
|
||||
|
||||
Show the installed version of CrewAI.
|
||||
@@ -138,7 +79,7 @@ Train the crew for a specified number of iterations.
|
||||
crewai train [OPTIONS]
|
||||
```
|
||||
|
||||
- `-n, --n-iterations INTEGER`: Number of iterations to train the crew (default: 5)
|
||||
- `-n, --n_iterations INTEGER`: Number of iterations to train the crew (default: 5)
|
||||
- `-f, --filename TEXT`: Path to a custom file for training (default: "trained_agents_data.pkl")
|
||||
|
||||
Example:
|
||||
@@ -155,7 +96,7 @@ Replay the crew execution from a specific task.
|
||||
crewai replay [OPTIONS]
|
||||
```
|
||||
|
||||
- `-t, --task-id TEXT`: Replay the crew from this task ID, including all subsequent tasks
|
||||
- `-t, --task_id TEXT`: Replay the crew from this task ID, including all subsequent tasks
|
||||
|
||||
Example:
|
||||
|
||||
@@ -202,7 +143,7 @@ Test the crew and evaluate the results.
|
||||
crewai test [OPTIONS]
|
||||
```
|
||||
|
||||
- `-n, --n-iterations INTEGER`: Number of iterations to test the crew (default: 3)
|
||||
- `-n, --n_iterations INTEGER`: Number of iterations to test the crew (default: 3)
|
||||
- `-m, --model TEXT`: LLM Model to run the tests on the Crew (default: "gpt-4o-mini")
|
||||
|
||||
Example:
|
||||
|
||||
@@ -322,8 +322,6 @@ Caches can be employed to store the results of tools' execution, making the proc
|
||||
|
||||
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])
|
||||
|
||||
@@ -267,27 +267,7 @@ print(flow.usage_metrics)
|
||||
execution.
|
||||
</Note>
|
||||
|
||||
### 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.
|
||||
Each entry in the returned [`UsageMetrics`](https://github.com/crewAIInc/crewAI/blob/main/lib/crewai/src/crewai/types/usage_metrics.py) 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
|
||||
|
||||
|
||||
@@ -418,27 +418,6 @@ In this section, you'll find detailed examples that help you select, configure,
|
||||
- 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`
|
||||
|
||||
@@ -32,10 +32,10 @@ You often need **both**: skills for expertise, tools for action. They are config
|
||||
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
|
||||
crewai skill create 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`):
|
||||
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`):
|
||||
|
||||
```
|
||||
skills/
|
||||
@@ -178,16 +178,12 @@ agent = Agent(
|
||||
|
||||
## 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.
|
||||
|
||||
<Note>
|
||||
`crewai skill create` is deprecated and still works with a warning. Use `crewai create skill` instead.
|
||||
</Note>
|
||||
Skills have a full lifecycle managed by the CLI: **create them with `crewai skill create`, 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.
|
||||
|
||||
### Create
|
||||
|
||||
```shell Terminal
|
||||
crewai create skill my-skill
|
||||
crewai skill create 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.
|
||||
|
||||
@@ -20,7 +20,7 @@ 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
|
||||
crewai test --n_iterations 5 --model gpt-4o
|
||||
```
|
||||
|
||||
or using the short forms:
|
||||
@@ -29,11 +29,6 @@ or using the short forms:
|
||||
crewai test -n 5 -m gpt-4o
|
||||
```
|
||||
|
||||
<Note>
|
||||
The older `--n_iterations` flag still works but is deprecated and hidden from
|
||||
`--help`. Use `--n-iterations` (or `-n`) instead.
|
||||
</Note>
|
||||
|
||||
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:
|
||||
|
||||
@@ -21,13 +21,9 @@ crewai create crew my_crew
|
||||
crewai create flow my_flow
|
||||
|
||||
# Tool repository
|
||||
crewai create tool my_tool
|
||||
crewai tool create my_tool
|
||||
```
|
||||
|
||||
<Note>
|
||||
`crewai tool create` is deprecated and still works with a warning. Use `crewai create tool` instead.
|
||||
</Note>
|
||||
|
||||
## Tool Setup: Point Assistants to AGENTS.md
|
||||
|
||||
### Codex
|
||||
|
||||
@@ -376,27 +376,6 @@ def handle_internet_search(self) -> str:
|
||||
...
|
||||
```
|
||||
|
||||
### 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:
|
||||
|
||||
```
|
||||
@@ -491,70 +470,6 @@ Inside a `@listen(label)` handler, choose:
|
||||
|
||||
`ConversationConfig.visible_agent_outputs` can promote specific agents' private results to public globally (`"all"`, or a list of agent names).
|
||||
|
||||
## Declaring a conversational flow in JSON/YAML
|
||||
|
||||
A [declarative Flow](/edge/en/concepts/cli) can be conversational too. Add a top-level `conversational` block and declare your own routes as methods that `listen` to a route label:
|
||||
|
||||
```yaml
|
||||
schema: crewai.flow/v1
|
||||
name: SupportFlow
|
||||
|
||||
conversational:
|
||||
system_prompt: You are a terse support assistant.
|
||||
llm: gpt-4o-mini
|
||||
router:
|
||||
llm: gpt-4o-mini
|
||||
|
||||
methods:
|
||||
handle_order:
|
||||
description: Order status, shipping and delivery questions.
|
||||
listen: order
|
||||
do:
|
||||
call: agent
|
||||
with:
|
||||
role: Support specialist
|
||||
goal: Answer order questions accurately
|
||||
backstory: Knows the fulfilment pipeline.
|
||||
input: "${state.current_user_message}"
|
||||
```
|
||||
|
||||
Declaring the block is the opt-in — `enabled` defaults to `true`. Set `enabled: false` to keep the configuration while turning chat off.
|
||||
|
||||
Three things are supplied for you:
|
||||
|
||||
| Supplied | Detail |
|
||||
|----------|--------|
|
||||
| The built-in graph | `route_conversation`, `converse_turn`, `end_conversation` and `answer_from_history_turn` are added automatically. Declare a method under one of those names to override it. |
|
||||
| Conversation state | `ConversationState` is used when the declaration has no `state` block. To add fields, point `state` at a Pydantic model that extends `ConversationState`. |
|
||||
| The route catalog | Built from the methods that declare a `listen` label. Each method's `description` is what the routing model reads when choosing between routes. |
|
||||
|
||||
Run it from Python with the same turn APIs as a class-based conversational Flow:
|
||||
|
||||
```python
|
||||
from crewai.flow import Flow
|
||||
|
||||
flow = Flow.from_declaration(path="flow.yaml")
|
||||
|
||||
try:
|
||||
flow.handle_turn("Where is my order?", session_id="session-1")
|
||||
finally:
|
||||
flow.finalize_session_traces()
|
||||
```
|
||||
|
||||
### Naming routes
|
||||
|
||||
Route labels and method names share one trigger namespace, so a handler must not be named after the route it listens to — `create_video` listening to `create_video` is rejected when the flow is built. Use a `handle_*` prefix.
|
||||
|
||||
### What a declaration cannot express
|
||||
|
||||
| Not expressible | Use instead |
|
||||
|-----------------|-------------|
|
||||
| A live `LLM` instance or a custom `BaseLLM` | A model id string, such as `gpt-4o-mini` |
|
||||
| `router.response_format` as a model class | Omit it; the framework synthesizes one. A ref or schema is ignored with a warning |
|
||||
| `route_turn()` / `can_answer_from_history()` overrides | Author the Flow in Python, or point a method's `do` at a `call: code` ref |
|
||||
|
||||
`crewai run` has no chat loop yet: it reports that the flow is conversational and exits rather than running a single turn. Drive a declarative conversational flow from Python with `handle_turn()`, `stream_turn()` or `chat()`.
|
||||
|
||||
## Tracing across turns
|
||||
|
||||
With `defer_trace_finalization=True` (default in `ConversationConfig`):
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
---
|
||||
title: A2UI
|
||||
description: The declarative tier of generative UI — the agent assembles a surface from a catalog of components you own.
|
||||
icon: table-cells
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## The agent assembles the UI
|
||||
|
||||
[Tool-based rendering](/edge/en/guides/frontend/tool-based-generative-ui) maps one tool to one component: the agent picks a component, you draw it. A2UI is the **declarative** tier of the [generative-UI spectrum](/edge/en/guides/frontend/generative-ui#declarative) — instead of picking a single component, the agent **assembles a surface** by combining building blocks from a catalog you define.
|
||||
|
||||
You still own the components. The agent can only use what is in your catalog, so it can never render something you did not ship. What the agent decides is the **layout and the data** — how those building blocks come together into a panel, and what goes in them.
|
||||
|
||||
<Note>
|
||||
A2UI works with [Flows](/en/concepts/flows). Both modes below — dynamic and fixed-schema — run as Flows served over AG-UI, exactly like the rest of this section.
|
||||
</Note>
|
||||
|
||||
## The catalog (same for every mode)
|
||||
|
||||
The frontend wiring is identical no matter which backend mode you use: you register a **catalog** on the `<CopilotKit>` provider with the `a2ui` prop.
|
||||
|
||||
```tsx
|
||||
import { CopilotKit } from "@copilotkit/react-core";
|
||||
import { catalog } from "@/a2ui-catalog";
|
||||
|
||||
<CopilotKit runtimeUrl="/api/copilotkit" agent="assistant" a2ui={{ catalog }}>
|
||||
{/* ... */}
|
||||
</CopilotKit>
|
||||
```
|
||||
|
||||
The catalog is your set of React components keyed by a catalog id — a `FlightCard`, a `HotelCard`, a `Chart`, whatever your app needs. The agent references catalog ids; CopilotKit paints your components with the data the agent supplies.
|
||||
|
||||
<Note>
|
||||
Authoring the catalog itself — the id schema, prop mapping, and composition rules — is deeper than this page covers. See the [CopilotKit A2UI docs](https://docs.copilotkit.ai) for the full authoring reference. Here we focus on the two backend modes and when to reach for each.
|
||||
</Note>
|
||||
|
||||
## Two backend modes
|
||||
|
||||
A2UI backends come in two shapes. In **dynamic** mode the agent designs the surface; in **fixed-schema** mode you pre-author the layout and the agent only fills in data.
|
||||
|
||||
| Mode | Who designs the layout | Backend | Predictability |
|
||||
| --- | --- | --- | --- |
|
||||
| **[Dynamic](#dynamic)** | The agent, from the conversation | No A2UI tool — auto-injected | Novel layouts, LLM layout step |
|
||||
| **[Fixed-schema](#fixed-schema)** | You, up front | Backend tools return an envelope | Deterministic, no layout step |
|
||||
|
||||
### Dynamic
|
||||
|
||||
The Flow wires **no** A2UI tool. Enable A2UI on the runtime for this agent and it gains a `generate_a2ui` tool automatically. A sub-agent designs a surface from the conversation against your catalog, streams it to the frontend progressively, and self-heals invalid output through a validate-then-retry recovery pass. You write a normal agentic-chat Flow; the tool is injected for you.
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Register the catalog on the provider">
|
||||
|
||||
Same as above — pass your catalog through the `a2ui` prop:
|
||||
|
||||
```tsx
|
||||
<CopilotKit runtimeUrl="/api/copilotkit" agent="assistant" a2ui={{ catalog }}>
|
||||
{/* ... */}
|
||||
</CopilotKit>
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Serve a normal Flow">
|
||||
|
||||
Your backend is a plain agentic-chat Flow. You do not define an A2UI tool — the runtime injects `generate_a2ui` when A2UI is enabled for the agent, and the sub-agent invents the layout from the conversation.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Let the agent compose">
|
||||
|
||||
When a turn calls for UI, the agent assembles a surface from your catalog, streams the components in as it designs them, and repairs any invalid output before it reaches the screen. Your registered components render in the layout the agent chose.
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
### Fixed-schema
|
||||
|
||||
When you already know the layout and only the data changes per call, pre-author the surface and let the agent fill it. The Flow wires backend tools (for example `search_flights`, `search_hotels`). Each tool returns an **A2UI operations envelope** as its result — `createSurface` -> `updateComponents` -> `updateDataModel` — which the frontend paints. There is no sub-agent, no generation, and no recovery pass: the layout JSON is authored by you, and only the data varies.
|
||||
|
||||
Install the toolkit that provides the envelope helpers:
|
||||
|
||||
```bash
|
||||
pip install ag-ui-a2ui-toolkit
|
||||
```
|
||||
|
||||
Build the envelope with the toolkit helpers and emit it as the tool result:
|
||||
|
||||
```python
|
||||
from ag_ui_a2ui_toolkit import (
|
||||
A2UI_OPERATIONS_KEY,
|
||||
create_surface,
|
||||
update_components,
|
||||
update_data_model,
|
||||
)
|
||||
from ag_ui_crewai.sdk import copilotkit_emit_tool_result, copilotkit_stream
|
||||
```
|
||||
|
||||
The tool assembles the `createSurface` -> `updateComponents` -> `updateDataModel` operations into an envelope keyed by `A2UI_OPERATIONS_KEY`, then hands it back with `copilotkit_emit_tool_result(...)`. Because the layout is fixed, the same tool always produces the same shape — only the values differ from call to call.
|
||||
|
||||
## When to use which
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Dynamic" icon="wand-magic-sparkles">
|
||||
The layout is not known ahead of time and you want the agent to compose novel surfaces from your primitives. You gain flexibility and pay for an LLM layout step.
|
||||
</Card>
|
||||
<Card title="Fixed-schema" icon="table-cells">
|
||||
The layout is known and only the data varies. More predictable and deterministic — no generation, no recovery, no LLM in the layout path.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
Both modes share the same frontend: one catalog, registered once on the provider. Start with fixed-schema when your surfaces are stable, and reach for dynamic when you want the agent to design layouts you did not anticipate.
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Generative UI" icon="wand-magic-sparkles" href="/edge/en/guides/frontend/generative-ui">
|
||||
The full spectrum — A2UI is its declarative tier.
|
||||
</Card>
|
||||
<Card title="Tool-Based Generative UI" icon="puzzle-piece" href="/edge/en/guides/frontend/tool-based-generative-ui">
|
||||
Map one tool to one component (controlled).
|
||||
</Card>
|
||||
<Card title="Agentic Generative UI" icon="list-check" href="/edge/en/guides/frontend/agentic-generative-ui">
|
||||
Render live agent state (controlled).
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,208 +0,0 @@
|
||||
---
|
||||
title: Agentic Generative UI
|
||||
description: Render your CrewAI Flow's live state as UI that updates as the agent works through multi-step tasks.
|
||||
icon: list-check
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Render the agent's live state
|
||||
|
||||
Some work does not fit into a single tool call. A research task, a multi-step plan, a long-running job: the interesting thing to show the user is not one result, but *progress*. Agentic generative UI renders the agent's **state** and re-renders it every time that state changes.
|
||||
|
||||
The pattern has two halves:
|
||||
|
||||
1. Your Flow writes progress into its own state as it works.
|
||||
2. Your frontend reads that state with `useAgent` and paints it, re-rendering as the state streams in.
|
||||
|
||||
The Flow's state reaches the frontend over AG-UI without you wiring up any transport. A state snapshot is emitted automatically at each step (method) boundary of the Flow, and you can push intermediate updates during a long-running step by calling `copilotkit_emit_state` explicitly. You subclass the state to add your own fields, update them in the Flow, and read them in React.
|
||||
|
||||
<Note>
|
||||
State-driven rendering requires a **Flow** with custom state (`Flow[AgentState]`). Crews are chat-oriented and do not expose custom state this way, so with a Crew use [tool rendering](/edge/en/guides/frontend/tool-based-generative-ui) instead.
|
||||
</Note>
|
||||
|
||||
## Build a live task planner
|
||||
|
||||
This example builds a planner that breaks a request into about ten steps and streams them to the UI as a checklist. It assumes you already have a CrewAI server and a CopilotKit frontend wired up. If you do not, start with the [Frontend Overview](/edge/en/guides/frontend/overview).
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Add your own fields to the agent state">
|
||||
|
||||
Subclass `CopilotKitState` to declare the state your UI needs. `CopilotKitState` already carries the conversation (`messages`); you add whatever else you want to render, here a list of task steps.
|
||||
|
||||
```python
|
||||
from typing import List, Literal
|
||||
from pydantic import BaseModel, Field
|
||||
from ag_ui_crewai.sdk import CopilotKitState
|
||||
|
||||
|
||||
class TaskStep(BaseModel):
|
||||
description: str
|
||||
status: Literal["enabled", "disabled"]
|
||||
|
||||
|
||||
class AgentState(CopilotKitState):
|
||||
steps: List[TaskStep] = Field(default_factory=list)
|
||||
```
|
||||
|
||||
Everything on `AgentState` is included in the state snapshot the frontend receives. A snapshot is emitted automatically at each step boundary, so writing to `self.state` is enough for the UI to pick it up between steps. To update the UI *during* a long step, emit explicitly (shown below).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Write progress into state from the Flow">
|
||||
|
||||
Type your Flow with the custom state (`Flow[AgentState]`) and let the model fill it in. Here the LLM calls a `generate_task_steps` tool; the streamed tool call lands in the conversation and the steps become visible in state.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from litellm import acompletion
|
||||
from ag_ui_crewai.sdk import copilotkit_stream
|
||||
|
||||
GENERATE_TASK_STEPS_TOOL = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "generate_task_steps",
|
||||
"description": "Break a task into about 10 short imperative steps.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"steps": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {"type": "string"},
|
||||
"status": {"type": "string", "enum": ["enabled"]},
|
||||
},
|
||||
"required": ["description", "status"],
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": ["steps"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class TaskPlannerFlow(Flow[AgentState]):
|
||||
@start()
|
||||
async def chat(self):
|
||||
response = await copilotkit_stream(
|
||||
await acompletion(
|
||||
model="openai/gpt-4o",
|
||||
messages=[
|
||||
{"role": "system", "content": "Plan the task the user asks for."},
|
||||
*self.state.messages,
|
||||
],
|
||||
tools=[GENERATE_TASK_STEPS_TOOL],
|
||||
parallel_tool_calls=False,
|
||||
stream=True,
|
||||
)
|
||||
)
|
||||
message = response.choices[0].message
|
||||
self.state.messages.append(message)
|
||||
```
|
||||
|
||||
Wrapping the LLM call in `copilotkit_stream` streams the assistant's tokens and tool call to the frontend as they are produced. The `steps` you write to `self.state` are sent in the state snapshot emitted at the end of this step.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Stream progress during a long step (optional)">
|
||||
|
||||
The automatic snapshot fires at step boundaries. If a single step does substantial work and you want the checklist to fill in *as it happens*, emit intermediate state yourself with `copilotkit_emit_state`. Each call pushes the current state to the frontend immediately.
|
||||
|
||||
```python
|
||||
from ag_ui_crewai.sdk import copilotkit_emit_state
|
||||
|
||||
class TaskPlannerFlow(Flow[AgentState]):
|
||||
@start()
|
||||
async def execute(self):
|
||||
for step in self.state.steps:
|
||||
step.status = "disabled" # mark done as you go
|
||||
await copilotkit_emit_state(self.state) # push update now
|
||||
await do_work(step)
|
||||
```
|
||||
|
||||
Import `copilotkit_emit_state` from `ag_ui_crewai.sdk`. It requires the CopilotKit SDK (`pip install "copilotkit[crewai]"`). Reach for it only when a step is long enough that waiting for its boundary snapshot would feel unresponsive.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Serve the Flow over AG-UI">
|
||||
|
||||
Register the Flow exactly as any other, on its own path:
|
||||
|
||||
```python
|
||||
# server.py
|
||||
from fastapi import FastAPI
|
||||
from ag_ui_crewai.endpoint import add_crewai_flow_fastapi_endpoint
|
||||
from my_agents.task_planner import TaskPlannerFlow
|
||||
|
||||
app = FastAPI(title="CrewAI Agent Server")
|
||||
|
||||
add_crewai_flow_fastapi_endpoint(
|
||||
app=app,
|
||||
flow=TaskPlannerFlow(),
|
||||
path="/task_planner",
|
||||
)
|
||||
```
|
||||
|
||||
See the [Frontend Overview](/edge/en/guides/frontend/overview) for the full server, runtime, and provider setup, and remember to register the agent (here `task_planner`) in your CopilotKit runtime route.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Read the live state in React">
|
||||
|
||||
On the frontend, `useAgent` gives you the agent's live state. Subscribe to state changes so your component re-renders every time the Flow writes an update.
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { useAgent, UseAgentUpdate } from "@copilotkit/react-core/v2";
|
||||
|
||||
function TaskPlan() {
|
||||
const { agent } = useAgent({
|
||||
agentId: "task_planner",
|
||||
updates: [UseAgentUpdate.OnStateChanged],
|
||||
});
|
||||
|
||||
const steps = agent?.state?.steps ?? [];
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{steps.map((s, i) => (
|
||||
<li key={i}>{s.description}</li>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
`useAgent` returns `{ agent }`. A few things to know:
|
||||
|
||||
- `agent.state` is the live Flow state. Its shape matches the fields you added to `AgentState`, so `agent.state.steps` is your list of task steps.
|
||||
- `agent.isRunning` tells you when the agent is actively working, useful for showing a spinner or disabling input.
|
||||
- `updates: [UseAgentUpdate.OnStateChanged]` re-renders the component whenever state changes, so the checklist fills in as the Flow streams its steps.
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Where this goes next
|
||||
|
||||
Reading state is the foundation. Two guides build directly on it:
|
||||
|
||||
- [Shared State](/edge/en/guides/frontend/shared-state) adds the other direction: editing the agent's state from the UI and having the Flow pick up the change.
|
||||
- [Predictive State](/edge/en/guides/frontend/predictive-state-updates) streams a tool's in-progress arguments into state so the UI reflects work before it is committed.
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Shared State" icon="arrows-rotate" href="/edge/en/guides/frontend/shared-state">
|
||||
Sync agent state and app UI in both directions.
|
||||
</Card>
|
||||
<Card title="Predictive State" icon="gauge-high" href="/edge/en/guides/frontend/predictive-state-updates">
|
||||
Stream in-progress tool arguments into state.
|
||||
</Card>
|
||||
<Card title="Tool-Based Generative UI" icon="puzzle-piece" href="/edge/en/guides/frontend/tool-based-generative-ui">
|
||||
Map agent tool calls to components.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,125 +0,0 @@
|
||||
---
|
||||
title: Channels
|
||||
description: Run the same CrewAI agent as a chat bot on Slack and Discord with the CopilotKit Channels SDK.
|
||||
icon: slack
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Meet your users where they already are
|
||||
|
||||
The CrewAI agent you built in the [Overview](/edge/en/guides/frontend/overview) does not have to live behind a web app. The same Crew or Flow can run as a bot inside a messaging platform. No rebuild, no second copy of your agent logic: the agent stays exposed over the [AG-UI protocol](https://docs.ag-ui.com), and a bot process drives it.
|
||||
|
||||
CopilotKit's [Channels SDK](https://docs.copilotkit.ai/reference/channels) provides that bot process. It ships a platform-agnostic engine plus per-platform adapters.
|
||||
|
||||
## How it fits together
|
||||
|
||||
Nothing about your agent server changes. It keeps serving your Crew or Flow over AG-UI exactly as in the Overview. What you add is a separate **bot process**: it connects to a platform adapter, listens for messages, and runs your agent when it is messaged. The reply streams back into the channel.
|
||||
|
||||
```
|
||||
Slack / Discord ──► Channels bot process ──► CrewAI server (AG-UI) ──► Crew / Flow
|
||||
```
|
||||
|
||||
Your agent server can keep serving the web frontend from the Overview at the same time. The web app and the bot are just two clients of one AG-UI endpoint.
|
||||
|
||||
## Slack
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Install the Channels packages">
|
||||
|
||||
```bash
|
||||
npm install @copilotkit/channels @copilotkit/channels-slack @ag-ui/crewai
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Create a Slack app and get tokens">
|
||||
|
||||
Create an app in the Slack API dashboard for your workspace, enable Socket Mode, and grant it the message and event scopes it needs to read and post in channels. Then expose its tokens to the bot process:
|
||||
|
||||
```bash
|
||||
export SLACK_BOT_TOKEN=xoxb-... # bot user token
|
||||
export SLACK_APP_TOKEN=xapp-... # app-level token (Socket Mode)
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Point the bot at your CrewAI agent">
|
||||
|
||||
`createBot` wires a Slack adapter to your agent. The `agent` factory returns a `CrewAIAgent` pointed at the AG-UI path your server exposes (the same URL you registered in the runtime in the Overview).
|
||||
|
||||
```ts
|
||||
// bot.ts
|
||||
import { createBot } from "@copilotkit/channels";
|
||||
import { slack, defaultSlackTools, defaultSlackContext } from "@copilotkit/channels-slack";
|
||||
import { CrewAIAgent } from "@ag-ui/crewai";
|
||||
|
||||
const bot = createBot({
|
||||
adapters: [
|
||||
slack({
|
||||
botToken: process.env.SLACK_BOT_TOKEN!, // xoxb-…
|
||||
appToken: process.env.SLACK_APP_TOKEN!, // xapp-… (Socket Mode)
|
||||
}),
|
||||
],
|
||||
agent: (threadId) => new CrewAIAgent({ url: "http://localhost:8000/recipe" }),
|
||||
tools: [...defaultSlackTools],
|
||||
context: [...defaultSlackContext],
|
||||
});
|
||||
|
||||
bot.start();
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Run the bot">
|
||||
|
||||
Start the bot process alongside your agent server:
|
||||
|
||||
```bash
|
||||
uvicorn server:app --port 8000 # terminal 1 — CrewAI agent server
|
||||
node bot.ts # terminal 2 — Slack bot
|
||||
```
|
||||
|
||||
Message the bot in Slack and it runs your Crew or Flow, streaming the reply back into the thread.
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
Slack app scopes, Socket Mode setup, and the full adapter options are maintained by CopilotKit. Follow the [Slack channel reference](https://docs.copilotkit.ai/reference/channels/slack) together with Slack's own app setup guide for the authoritative steps.
|
||||
</Note>
|
||||
|
||||
## Discord
|
||||
|
||||
Discord uses the same `createBot` engine with the Discord adapter from `@copilotkit/channels-discord`:
|
||||
|
||||
```ts
|
||||
import { createBot } from "@copilotkit/channels";
|
||||
import { discord } from "@copilotkit/channels-discord";
|
||||
import { CrewAIAgent } from "@ag-ui/crewai";
|
||||
|
||||
const bot = createBot({
|
||||
adapters: [discord({ token: process.env.DISCORD_BOT_TOKEN! })],
|
||||
agent: (threadId) => new CrewAIAgent({ url: "http://localhost:8000/recipe" }),
|
||||
});
|
||||
|
||||
bot.start();
|
||||
```
|
||||
|
||||
See the [Discord channel reference](https://docs.copilotkit.ai/reference/channels/discord) for the exact adapter options and bot setup.
|
||||
|
||||
## Platform support
|
||||
|
||||
Slack and Discord have official Channels adapters (`@copilotkit/channels-slack`, `@copilotkit/channels-discord`). Microsoft Teams is available through CopilotKit's managed offering (currently waitlisted). Check the [Channels reference](https://docs.copilotkit.ai/reference/channels) for the current list before promising a platform.
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Frontend Overview" icon="browser" href="/edge/en/guides/frontend/overview">
|
||||
Serve your Crew or Flow over AG-UI — the foundation every channel builds on.
|
||||
</Card>
|
||||
<Card title="Human-in-the-Loop" icon="user-check" href="/edge/en/guides/frontend/human-in-the-loop">
|
||||
Pause the agent to collect user approval or input mid-run.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,106 +0,0 @@
|
||||
---
|
||||
title: Conversational Flows
|
||||
description: Serve native, session-aware CrewAI Flows over AG-UI with managed conversation state and full frontend parity.
|
||||
icon: comments
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Three execution shapes, one bridge
|
||||
|
||||
Behind the AG-UI bridge, a CrewAI backend can take one of three shapes. Knowing which one you are serving decides how you author the backend, not how you build the frontend.
|
||||
|
||||
| Shape | What it is | How it is entered |
|
||||
| --- | --- | --- |
|
||||
| **Regular Flows** | Author-controlled `@start`/`@listen`/`@router` graphs. The default used throughout these guides. | `kickoff` / `astream` |
|
||||
| **Conversational Flows** | Native, session-aware, turn-based Flows with managed conversation state. | `stream_turn(message, session_id=...)` |
|
||||
| **Crews** | Closed autonomous task/agent loops. Basic chat only, a separate compatibility path. | Not the focus here. |
|
||||
|
||||
Conversational Flows are a newer CrewAI capability, and an important thing to be clear about up front: **they are Flows, not Crews.** They now run at full regular-Flow feature parity. This page introduces them and shows how they fit the rest of the frontend guides.
|
||||
|
||||
<Note>
|
||||
Reach for a Conversational Flow when you want native multi-turn conversation with CrewAI managing session state and history for you, rather than wiring turn and state handling into a regular Flow yourself. If you are new here, start with the [Frontend Overview](/edge/en/guides/frontend/overview) for the base server, runtime, and provider setup.
|
||||
</Note>
|
||||
|
||||
## Register a Conversational Flow
|
||||
|
||||
You register a Conversational Flow through the same endpoint helper as any other Flow, with one extra argument: `conversational=True`.
|
||||
|
||||
```python
|
||||
# server.py
|
||||
from ag_ui_crewai.endpoint import add_crewai_flow_fastapi_endpoint
|
||||
|
||||
add_crewai_flow_fastapi_endpoint(
|
||||
app,
|
||||
flow,
|
||||
"/conversation",
|
||||
conversational=True,
|
||||
)
|
||||
```
|
||||
|
||||
Two requirements must hold for this to work:
|
||||
|
||||
- The Flow instance declares `conversational = True`.
|
||||
- The Flow exposes CrewAI's public, callable `stream_turn(message, session_id=...)`.
|
||||
|
||||
Detection is capability-based, not version-gated: the bridge checks that the Flow actually offers turn-based conversation, rather than keying off a version number.
|
||||
|
||||
<Warning>
|
||||
If those requirements are not met, the request fails loudly with a `RUN_ERROR` (code `AGUI_CREWAI_CONVERSATIONAL_FLOW_UNSUPPORTED`). It never silently falls back to regular kickoff semantics, so you always know exactly which path you are on.
|
||||
</Warning>
|
||||
|
||||
Authoring the Flow itself, including how you implement `stream_turn`, belongs to CrewAI's Conversational Flows documentation. This page stays at the registration and integration boundary.
|
||||
|
||||
## Session and state
|
||||
|
||||
Conversational Flows manage session state and history for you across turns. You do not re-thread history manually.
|
||||
|
||||
- The AG-UI `threadId` **is** the CrewAI conversation `session_id`. The same thread is the same conversation.
|
||||
- Before each turn the bridge hydrates the Flow's state and conversation history, then calls `stream_turn`. CrewAI restores the stored session state, and a per-request overlay reapplies the incoming AG-UI state and history so the browser's latest edits win over stale storage.
|
||||
|
||||
The result: from the backend author's side, each turn arrives already carrying the conversation's state, and CrewAI persists what you write for the next turn.
|
||||
|
||||
## Frontend parity
|
||||
|
||||
This is the point to hold onto: **Conversational Flows run through the same event pipeline as regular Flows, so the frontend code is identical.**
|
||||
|
||||
There is no Conversational-Flow-specific frontend API. Every feature in these guides works exactly the same way with a Conversational Flow as it does with a regular Flow, using the same hooks and components:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Tool-Based Generative UI" icon="puzzle-piece" href="/edge/en/guides/frontend/tool-based-generative-ui">
|
||||
Map agent tool calls to your React components.
|
||||
</Card>
|
||||
<Card title="Agentic Generative UI" icon="list-check" href="/edge/en/guides/frontend/agentic-generative-ui">
|
||||
Render the Flow's live state as it works.
|
||||
</Card>
|
||||
<Card title="Shared State" icon="arrows-rotate" href="/edge/en/guides/frontend/shared-state">
|
||||
Keep agent state and app UI in two-way sync.
|
||||
</Card>
|
||||
<Card title="Human-in-the-Loop" icon="user-check" href="/edge/en/guides/frontend/human-in-the-loop">
|
||||
Pause the agent for user approval or input mid-turn.
|
||||
</Card>
|
||||
<Card title="Predictive State" icon="gauge-high" href="/edge/en/guides/frontend/predictive-state-updates">
|
||||
Stream in-progress tool arguments into state.
|
||||
</Card>
|
||||
<Card title="Reasoning" icon="brain" href="/edge/en/guides/frontend/reasoning">
|
||||
Show the model's thinking in the chat.
|
||||
</Card>
|
||||
<Card title="A2UI" icon="table-cells" href="/edge/en/guides/frontend/a2ui">
|
||||
Render agent-authored UI from a component catalog.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
The only difference is on the backend: how you author the Flow (turn-based `stream_turn` with managed session state) and the `conversational=True` registration. Once the endpoint is up, everything you already know about building the frontend applies unchanged.
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Frontend Overview" icon="browser" href="/edge/en/guides/frontend/overview">
|
||||
Wire a Crew or Flow to a Next.js frontend end to end.
|
||||
</Card>
|
||||
<Card title="Generative UI" icon="wand-magic-sparkles" href="/edge/en/guides/frontend/generative-ui">
|
||||
Render tool calls and agent state as custom components.
|
||||
</Card>
|
||||
<Card title="Human-in-the-Loop" icon="user-check" href="/edge/en/guides/frontend/human-in-the-loop">
|
||||
Gate agent actions behind user approval.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,121 +0,0 @@
|
||||
---
|
||||
title: Frontend Actions
|
||||
description: Let your CrewAI agent call functions that run in the user's browser, from switching themes to navigating your app.
|
||||
icon: bolt
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Let the agent act on the app
|
||||
|
||||
A frontend action is a tool the agent calls that runs code in the browser instead of on the server. The model decides to invoke it; your handler switches the theme, navigates, highlights an element, or updates your app data; and the result flows back to the agent.
|
||||
|
||||
It uses the same hook as tool-based generative UI, `useFrontendTool`. The difference is what you give it: a `handler` that runs code, instead of (or alongside) a `render` that draws UI.
|
||||
|
||||
<Note>
|
||||
Frontend actions work with both Crews and Flows. Any agent that binds `copilotkit.actions` into its LLM call can invoke them.
|
||||
</Note>
|
||||
|
||||
## Build a frontend action
|
||||
|
||||
The example below lets the agent switch the app into dark mode on request.
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Register the action on the frontend">
|
||||
|
||||
Call `useFrontendTool` with a `handler`. The handler runs in the browser when the agent invokes the tool, and the string it returns is fed back to the agent.
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { useFrontendTool } from "@copilotkit/react-core/v2";
|
||||
import { z } from "zod";
|
||||
|
||||
useFrontendTool({
|
||||
agentId: "assistant",
|
||||
name: "set_theme",
|
||||
description: "Switch the app between light and dark mode.",
|
||||
parameters: z.object({
|
||||
theme: z.enum(["light", "dark"]),
|
||||
}),
|
||||
followUp: false,
|
||||
handler: async ({ theme }) => {
|
||||
document.documentElement.dataset.theme = theme; // runs in the browser
|
||||
return `Theme set to ${theme}.`;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The arguments:
|
||||
|
||||
- **`name`** — the tool name the model calls (`set_theme`).
|
||||
- **`description`** — a short explanation of what the tool does. The model reads it to decide *when* to call the tool, so make it specific. Omitting it leaves the model guessing from the name alone.
|
||||
- **`parameters`** — a [zod](https://zod.dev) schema describing the arguments the model must supply. CopilotKit turns this into the tool's JSON schema and validates the incoming call.
|
||||
- **`handler(args)`** — runs in the browser with the parsed arguments. Do your side effect here (set the theme, navigate, update state). The string you return is handed back to the agent as the tool result.
|
||||
- **`followUp: false`** — stops the agent from taking another turn after the action runs. Leave it out (or set `true`) when you want the agent to respond after acting.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Bind the frontend tools on the backend">
|
||||
|
||||
The agent can only call a tool it has been given. In your Flow, pass the frontend-registered tools into the LLM `tools` list with `*self.state.copilotkit.actions`.
|
||||
|
||||
```python
|
||||
from crewai.flow.flow import Flow, start
|
||||
from litellm import acompletion
|
||||
from ag_ui_crewai.sdk import copilotkit_stream, CopilotKitState
|
||||
|
||||
class AssistantFlow(Flow[CopilotKitState]):
|
||||
@start()
|
||||
async def chat(self):
|
||||
response = await copilotkit_stream(
|
||||
await acompletion(
|
||||
model="openai/gpt-4o",
|
||||
messages=[
|
||||
{"role": "system", "content": "Help the user. Use the tools available to control the app."},
|
||||
*self.state.messages,
|
||||
],
|
||||
tools=[*self.state.copilotkit.actions], # tools the frontend registered
|
||||
parallel_tool_calls=False,
|
||||
stream=True,
|
||||
)
|
||||
)
|
||||
message = response.choices[0].message
|
||||
self.state.messages.append(message)
|
||||
```
|
||||
|
||||
`self.state.copilotkit.actions` holds the tool definitions for every frontend action registered with `useFrontendTool`. Spreading them into the LLM `tools` list is what makes the agent able to invoke browser-side actions. `copilotkit_stream` streams the response, including the tool call, back to the frontend, where CopilotKit runs the matching handler.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Serve the Flow">
|
||||
|
||||
Expose the Flow over AG-UI with `add_crewai_flow_fastapi_endpoint(...)` and register it in the CopilotKit runtime, exactly as in the [Frontend Overview](/edge/en/guides/frontend/overview). Once both are running, asking the assistant to "switch to dark mode" triggers `set_theme`, and the page flips.
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Actions vs. generative UI
|
||||
|
||||
`useFrontendTool` covers both ends of a spectrum, and you pick per tool:
|
||||
|
||||
| You provide | What it does |
|
||||
| --- | --- |
|
||||
| **`handler`** | Runs code in the browser (a frontend action) |
|
||||
| **`render`** | Draws UI for the tool call (generative UI) |
|
||||
|
||||
You can supply either one, or both. A `handler` with a `render` alongside it performs the action and draws UI while it runs. For render-only tools that just display the result of an agent action, see [Tool-Based Generative UI](/edge/en/guides/frontend/tool-based-generative-ui).
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Tool-Based Generative UI" icon="puzzle-piece" href="/edge/en/guides/frontend/tool-based-generative-ui">
|
||||
Map agent tool calls to React components.
|
||||
</Card>
|
||||
<Card title="Human-in-the-Loop" icon="user-check" href="/edge/en/guides/frontend/human-in-the-loop">
|
||||
Gate agent actions behind user approval.
|
||||
</Card>
|
||||
<Card title="Shared State" icon="arrows-rotate" href="/edge/en/guides/frontend/shared-state">
|
||||
Keep agent state and your app UI in two-way sync.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,107 +0,0 @@
|
||||
---
|
||||
title: Generative UI
|
||||
description: Render your CrewAI agent's work as live React components, across the full spectrum from author-controlled to agent-invented UI.
|
||||
icon: wand-magic-sparkles
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Beyond the chat bubble
|
||||
|
||||
Generative UI means the agent's work shows up as real interface, not just text. When your Crew or Flow calls a tool, updates its state, or reasons about a problem, you decide what the user sees: a progress checklist, a recipe card, a chart, a whole assembled panel.
|
||||
|
||||
CopilotKit renders generative UI along a **spectrum**, from fully author-controlled (you decide every pixel) to agent-invented (the agent assembles the surface):
|
||||
|
||||
| Tier | Who decides the UI | CrewAI mechanism |
|
||||
| --- | --- | --- |
|
||||
| **[Controlled](#controlled)** | You — a fixed set of components the agent picks from | `useRenderTool`, `useAgent`, reasoning |
|
||||
| **[Declarative](#declarative)** | The agent — assembles a surface from *your* component catalog | [A2UI](/edge/en/guides/frontend/a2ui) |
|
||||
| **[Open-ended](#open-ended)** | An external tool/server invents the surface | MCP tools |
|
||||
|
||||
The tiers compose freely; a single app usually mixes them.
|
||||
|
||||
## Controlled
|
||||
|
||||
You own the components. The agent chooses which to show and with what data. This is the most predictable tier and where most apps start.
|
||||
|
||||
### Tool rendering
|
||||
|
||||
The agent calls a tool on the backend. You register a matching component on the frontend with `useRenderTool`, and CopilotKit renders it, streaming the arguments in as they arrive.
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { useRenderTool } from "@copilotkit/react-core/v2";
|
||||
import { z } from "zod";
|
||||
|
||||
useRenderTool({
|
||||
name: "generate_recipe",
|
||||
parameters: z.object({
|
||||
title: z.string(),
|
||||
ingredients: z.array(z.string()),
|
||||
}),
|
||||
render: ({ args }) => <RecipeCard title={args.title} ingredients={args.ingredients} />,
|
||||
});
|
||||
```
|
||||
|
||||
<Note>
|
||||
`useRenderTool` renders a tool call. When a tool also needs to *run* code in the browser, use [`useFrontendTool`](/edge/en/guides/frontend/frontend-actions) (a `handler`, with optional `render`).
|
||||
</Note>
|
||||
|
||||
See [Tool-Based Generative UI](/edge/en/guides/frontend/tool-based-generative-ui) for the full walkthrough, including progressive rendering as arguments stream, and [Backend Tool Rendering](/edge/en/guides/frontend/tool-based-generative-ui#backend-tools) for tools your Crew or Flow executes server-side.
|
||||
|
||||
### State rendering
|
||||
|
||||
Instead of reacting to a single tool call, render the agent's **state** as it changes. This is the right pattern for multi-step work: read the agent's working state with `useAgent` and paint it however you like.
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { useAgent } from "@copilotkit/react-core/v2";
|
||||
|
||||
function TaskProgress() {
|
||||
const { agent } = useAgent({ agentId: "task_runner" });
|
||||
const steps = agent?.state?.steps ?? [];
|
||||
return <StepList steps={steps} />;
|
||||
}
|
||||
```
|
||||
|
||||
See [Agentic Generative UI](/edge/en/guides/frontend/agentic-generative-ui) for streaming state from a Flow, and [Shared State](/edge/en/guides/frontend/shared-state) for editing that state from the UI.
|
||||
|
||||
### Reasoning
|
||||
|
||||
When the model reasons before answering, that thinking renders in the chat automatically. No component to write. See [Reasoning](/edge/en/guides/frontend/reasoning).
|
||||
|
||||
## Declarative
|
||||
|
||||
The agent goes beyond picking a component: it **assembles a surface** by combining building blocks from a catalog *you* define. You still own the components (the agent can only use what is in your catalog), but the layout is the agent's.
|
||||
|
||||
This is [A2UI](/edge/en/guides/frontend/a2ui). You register a catalog on the provider:
|
||||
|
||||
```tsx
|
||||
<CopilotKit runtimeUrl="/api/copilotkit" agent="assistant" a2ui={{ catalog }}>
|
||||
{/* ... */}
|
||||
</CopilotKit>
|
||||
```
|
||||
|
||||
The agent then builds surfaces from that catalog — either dynamically (it designs the layout from the conversation) or from a fixed schema your backend fills with data. See [A2UI](/edge/en/guides/frontend/a2ui) for both modes and error recovery.
|
||||
|
||||
## Open-ended
|
||||
|
||||
At the far end, the surface is invented outside your app entirely. For CrewAI this comes through **MCP**: tools served by an MCP server the agent connects to render as tool calls in the chat, the same way backend tools do. This is the least constrained and the least predictable tier.
|
||||
|
||||
MCP tool calls surface as standard tool-call UI — render them with `useRenderTool` like any other tool. Full agent-invented "MCP App" surfaces are an emerging capability; see the [CopilotKit docs](https://docs.copilotkit.ai) for the current state.
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Tool-Based Generative UI" icon="puzzle-piece" href="/edge/en/guides/frontend/tool-based-generative-ui">
|
||||
Map agent tool calls to components (controlled).
|
||||
</Card>
|
||||
<Card title="Agentic Generative UI" icon="list-check" href="/edge/en/guides/frontend/agentic-generative-ui">
|
||||
Render live agent state (controlled).
|
||||
</Card>
|
||||
<Card title="A2UI" icon="table-cells" href="/edge/en/guides/frontend/a2ui">
|
||||
Let the agent assemble surfaces from your catalog (declarative).
|
||||
</Card>
|
||||
<Card title="Reasoning" icon="brain" href="/edge/en/guides/frontend/reasoning">
|
||||
Render the agent's thinking.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,191 +0,0 @@
|
||||
---
|
||||
title: Human-in-the-Loop
|
||||
description: Pause your CrewAI agent mid-run to collect a user decision, then resume the agent with their answer.
|
||||
icon: user-check
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Put the user in the loop
|
||||
|
||||
Some steps should not happen without a human saying yes. Human-in-the-loop pauses the agent mid-run, renders an interactive component in the frontend, and waits. The user makes a choice; the agent resumes with that choice and continues.
|
||||
|
||||
The mechanism is a tool the frontend registers. When the model calls it, the run halts at that tool call until the user responds. Nothing happens automatically: the agent stays parked until `respond()` hands control back.
|
||||
|
||||
In the example below, the agent proposes a list of task steps. The user enables or disables each step and confirms. The agent then continues, respecting exactly what the user approved.
|
||||
|
||||
<Note>
|
||||
This pattern works with Flows. It relies on the Flow's chat loop re-entering after `respond()`: the returned value comes back as a tool result, and the agent's next turn acts on it.
|
||||
</Note>
|
||||
|
||||
## Build it
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Bind the frontend actions into the model's tools">
|
||||
|
||||
In your Flow, add the frontend-registered actions to the model's tool list with `*self.state.copilotkit.actions`. Those actions are the tools your frontend registered (via `useHumanInTheLoop`). Binding them lets the model call them; the run pauses at that tool call until the user responds.
|
||||
|
||||
```python
|
||||
# human_in_the_loop_flow.py
|
||||
from crewai.flow.flow import Flow, start, router, listen
|
||||
from litellm import acompletion
|
||||
from ag_ui_crewai.sdk import copilotkit_stream, CopilotKitState
|
||||
|
||||
|
||||
class HumanInTheLoopFlow(Flow[CopilotKitState]):
|
||||
@start()
|
||||
@listen("route_follow_up")
|
||||
async def start_flow(self):
|
||||
pass
|
||||
|
||||
@router(start_flow)
|
||||
async def chat(self):
|
||||
system_prompt = (
|
||||
"You perform tasks for the user. When asked to do a task, call the "
|
||||
"tool the frontend provides so the user can approve or adjust the steps "
|
||||
"before you continue."
|
||||
)
|
||||
|
||||
response = await copilotkit_stream(
|
||||
await acompletion(
|
||||
model="openai/gpt-4o",
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
*self.state.messages,
|
||||
],
|
||||
tools=[*self.state.copilotkit.actions], # tools registered by the frontend
|
||||
parallel_tool_calls=False,
|
||||
stream=True,
|
||||
)
|
||||
)
|
||||
|
||||
message = response.choices[0].message
|
||||
self.state.messages.append(message)
|
||||
return "route_end"
|
||||
|
||||
@listen("route_end")
|
||||
async def end(self):
|
||||
pass
|
||||
```
|
||||
|
||||
`CopilotKitState` carries the frontend-registered actions on `self.state.copilotkit.actions`. When the model calls one, the run pauses there. After the user responds, the returned value lands in `self.state.messages` as the tool result, and the Flow loops back through `chat` so the model can act on the decision.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Serve the Flow over AG-UI">
|
||||
|
||||
Expose the Flow from your FastAPI server with `add_crewai_flow_fastapi_endpoint`, the same way as every other agent. See [Frontend Overview](/edge/en/guides/frontend/overview) for the full server, runtime, and provider setup.
|
||||
|
||||
```python
|
||||
# server.py
|
||||
from fastapi import FastAPI
|
||||
from ag_ui_crewai.endpoint import add_crewai_flow_fastapi_endpoint
|
||||
from my_agents.human_in_the_loop_flow import HumanInTheLoopFlow
|
||||
|
||||
app = FastAPI(title="CrewAI Agent Server")
|
||||
|
||||
add_crewai_flow_fastapi_endpoint(
|
||||
app=app,
|
||||
flow=HumanInTheLoopFlow(),
|
||||
path="/human_in_the_loop",
|
||||
)
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Register the interactive tool on the frontend">
|
||||
|
||||
`useHumanInTheLoop` registers the tool the agent pauses on and gives you a `render` function to draw the interactive UI. When the agent calls the tool, your component appears; when the user acts, you call `respond()` to resume the agent.
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { useHumanInTheLoop } from "@copilotkit/react-core/v2";
|
||||
import { z } from "zod";
|
||||
|
||||
useHumanInTheLoop({
|
||||
agentId: "human_in_the_loop",
|
||||
name: "generate_task_steps",
|
||||
parameters: z.object({
|
||||
steps: z.array(
|
||||
z.object({
|
||||
description: z.string(),
|
||||
status: z.enum(["enabled", "disabled", "executing"]),
|
||||
})
|
||||
),
|
||||
}),
|
||||
render: ({ args, respond, status }) => (
|
||||
<StepReview
|
||||
steps={args.steps ?? []}
|
||||
// `status === "executing"` means the agent is waiting for the user
|
||||
waiting={status === "executing"}
|
||||
onConfirm={(chosen) => respond?.(chosen)}
|
||||
/>
|
||||
),
|
||||
});
|
||||
```
|
||||
|
||||
The `render` function receives:
|
||||
|
||||
- **`args`** — the tool arguments the model produced (here, the proposed `steps`). These stream in as the model generates them.
|
||||
- **`status`** — the tool call's lifecycle. While it is `"executing"`, the agent is paused and waiting on the human.
|
||||
- **`respond(value)`** — resumes the agent with the user's decision. The agent's next turn sees the returned value and acts on it.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Let the user decide, then respond">
|
||||
|
||||
Your component reads `args.steps`, lets the user toggle each one, and calls `respond()` with the final selection. That value is what the agent continues with.
|
||||
|
||||
```tsx
|
||||
function StepReview({ steps, waiting, onConfirm }) {
|
||||
const [choices, setChoices] = useState(steps);
|
||||
|
||||
const toggle = (i) =>
|
||||
setChoices((prev) =>
|
||||
prev.map((s, idx) =>
|
||||
idx === i
|
||||
? { ...s, status: s.status === "enabled" ? "disabled" : "enabled" }
|
||||
: s
|
||||
)
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{choices.map((step, i) => (
|
||||
<label key={i}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={step.status === "enabled"}
|
||||
disabled={!waiting}
|
||||
onChange={() => toggle(i)}
|
||||
/>
|
||||
{step.description}
|
||||
</label>
|
||||
))}
|
||||
<button disabled={!waiting} onClick={() => onConfirm(choices)}>
|
||||
Confirm
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Once the user clicks Confirm, `respond()` fires, the run resumes, and the Flow's `chat` step runs again with the user's choices in the message history.
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Frontend Actions" icon="bolt" href="/edge/en/guides/frontend/frontend-actions">
|
||||
Let the agent call functions that run in the browser.
|
||||
</Card>
|
||||
<Card title="Shared State" icon="arrows-rotate" href="/edge/en/guides/frontend/shared-state">
|
||||
Keep agent state and your app UI in two-way sync.
|
||||
</Card>
|
||||
<Card title="Agentic Generative UI" icon="list-check" href="/edge/en/guides/frontend/agentic-generative-ui">
|
||||
Render live agent state as custom components.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,238 +0,0 @@
|
||||
---
|
||||
title: Frontend Overview
|
||||
description: Build interactive user interfaces for your CrewAI agents with CopilotKit and the AG-UI protocol.
|
||||
icon: browser
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Give your agents a user interface
|
||||
|
||||
CrewAI runs your agents. [CopilotKit](https://copilotkit.ai) gives them a frontend. Together they let you build applications where users chat with a Crew or Flow, watch it work in real time, approve its decisions, and see its output rendered as live UI instead of walls of text.
|
||||
|
||||
The two connect through the [AG-UI protocol](https://docs.ag-ui.com). The `ag-ui-crewai` package exposes any Crew or Flow as an AG-UI endpoint. CopilotKit's React hooks and components consume that endpoint. This unlocks experiences that go well beyond a chat box:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Generative UI" icon="wand-magic-sparkles" href="/edge/en/guides/frontend/generative-ui">
|
||||
Render agent tool calls and state as your own React components.
|
||||
</Card>
|
||||
<Card title="Human-in-the-Loop" icon="user-check" href="/edge/en/guides/frontend/human-in-the-loop">
|
||||
Pause the agent to collect user approval or input mid-run.
|
||||
</Card>
|
||||
<Card title="Shared State" icon="arrows-rotate" href="/edge/en/guides/frontend/shared-state">
|
||||
Keep agent state and your app UI in two-way sync.
|
||||
</Card>
|
||||
<Card title="Channels" icon="slack" href="/edge/en/guides/frontend/channels">
|
||||
Run the same agent as a Slack, Discord, or Teams bot.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
This guide gets a Crew or Flow talking to a Next.js frontend end to end. The rest of the section builds on the app you set up here.
|
||||
|
||||
## Architecture
|
||||
|
||||
There are three pieces:
|
||||
|
||||
1. **CrewAI agent server** — a Python process that serves your Crew or Flow over AG-UI (FastAPI + `ag-ui-crewai`).
|
||||
2. **CopilotKit runtime** — a Next.js route that registers your agent and proxies requests to it.
|
||||
3. **React frontend** — the `<CopilotKit>` provider plus chat and generative-UI components.
|
||||
|
||||
```
|
||||
React app ──► CopilotKit runtime (/api/copilotkit) ──► CrewAI server (AG-UI) ──► Crew / Flow
|
||||
```
|
||||
|
||||
<Note>
|
||||
This guide covers the **self-hosted** path: you run the CrewAI agent server yourself with `ag-ui-crewai`, and it works locally with no managed service. CopilotKit also offers a **managed** path (CopilotKit Cloud / Enterprise Intelligence) with hosted threads and an inspector — see the [CopilotKit CrewAI quickstart](https://docs.copilotkit.ai/crewai-crews/quickstart) if you want that instead. The frontend code in this section is the same either way; only how the agent is hosted and registered differs.
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
CrewAI runs behind AG-UI in three shapes: regular **Flows** (used throughout these guides), **[Conversational Flows](/edge/en/guides/frontend/conversational-flows)** (native, session-aware, turn-based, at full feature parity), and **Crews** (basic chat). The frontend in this section is identical across them — only the backend authoring and registration differ.
|
||||
</Note>
|
||||
|
||||
## Integration guide
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Serve your agent over AG-UI">
|
||||
|
||||
Install the integration package into your CrewAI project:
|
||||
|
||||
```bash
|
||||
pip install ag-ui-crewai
|
||||
```
|
||||
|
||||
Expose your agent from a FastAPI app. Flows use `add_crewai_flow_fastapi_endpoint`; Crews use `add_crewai_crew_fastapi_endpoint`. You can register as many as you want, each on its own path.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Flow
|
||||
# server.py
|
||||
from fastapi import FastAPI
|
||||
from ag_ui_crewai.endpoint import add_crewai_flow_fastapi_endpoint
|
||||
from my_agents.recipe_flow import RecipeFlow
|
||||
|
||||
app = FastAPI(title="CrewAI Agent Server")
|
||||
|
||||
add_crewai_flow_fastapi_endpoint(
|
||||
app=app,
|
||||
flow=RecipeFlow(),
|
||||
path="/recipe",
|
||||
)
|
||||
```
|
||||
|
||||
```python Crew
|
||||
# server.py
|
||||
from fastapi import FastAPI
|
||||
from ag_ui_crewai.endpoint import add_crewai_crew_fastapi_endpoint
|
||||
from my_agents.research_crew import ResearchCrew
|
||||
|
||||
app = FastAPI(title="CrewAI Agent Server")
|
||||
|
||||
add_crewai_crew_fastapi_endpoint(
|
||||
app=app,
|
||||
crew=ResearchCrew().crew(),
|
||||
path="/research",
|
||||
)
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
Run it:
|
||||
|
||||
```bash
|
||||
uvicorn server:app --port 8000
|
||||
```
|
||||
|
||||
<Note>
|
||||
Set the environment variables for your LLM provider (for example `OPENAI_API_KEY`) before starting the server.
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Create a Next.js app">
|
||||
|
||||
If you do not have a frontend yet, scaffold one:
|
||||
|
||||
```bash
|
||||
npx create-next-app@latest my-app
|
||||
cd my-app
|
||||
```
|
||||
|
||||
Install CopilotKit and the CrewAI AG-UI client:
|
||||
|
||||
```bash
|
||||
npm install @copilotkit/react-core @copilotkit/react-ui @copilotkit/runtime @ag-ui/crewai
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Add the CopilotKit runtime">
|
||||
|
||||
Create a route that registers your CrewAI agent(s) with the CopilotKit runtime. Each agent points at a path on your Python server via `CrewAIAgent`.
|
||||
|
||||
```ts
|
||||
// app/api/copilotkit/route.ts
|
||||
import {
|
||||
CopilotRuntime,
|
||||
InMemoryAgentRunner,
|
||||
createCopilotEndpoint,
|
||||
} from "@copilotkit/runtime/v2";
|
||||
import { CrewAIAgent } from "@ag-ui/crewai";
|
||||
import { handle } from "hono/vercel";
|
||||
|
||||
const runtime = new CopilotRuntime({
|
||||
agents: {
|
||||
recipe: new CrewAIAgent({ url: "http://localhost:8000/recipe" }),
|
||||
},
|
||||
runner: new InMemoryAgentRunner(),
|
||||
});
|
||||
|
||||
const app = createCopilotEndpoint({
|
||||
runtime,
|
||||
basePath: "/api/copilotkit",
|
||||
});
|
||||
|
||||
const handler = handle(app);
|
||||
export const GET = handler;
|
||||
export const POST = handler;
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Wrap your app with the provider">
|
||||
|
||||
Point `<CopilotKit>` at the runtime route and name the agent you registered.
|
||||
|
||||
```tsx
|
||||
// app/page.tsx
|
||||
"use client";
|
||||
import { CopilotKit } from "@copilotkit/react-core";
|
||||
import { CopilotSidebar } from "@copilotkit/react-core/v2";
|
||||
import "@copilotkit/react-core/v2/styles.css";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<CopilotKit runtimeUrl="/api/copilotkit" agent="recipe">
|
||||
<YourApp />
|
||||
<CopilotSidebar agentId="recipe" labels={{ modalHeaderTitle: "Assistant" }} />
|
||||
</CopilotKit>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Run it">
|
||||
|
||||
Start both processes and open the app. Chatting in the sidebar now runs your Crew or Flow.
|
||||
|
||||
```bash
|
||||
uvicorn server:app --port 8000 # terminal 1
|
||||
npm run dev # terminal 2
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Chat UI options
|
||||
|
||||
CopilotKit ships three interchangeable chat surfaces. Swap the component; the wiring is identical.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```tsx Sidebar
|
||||
import { CopilotSidebar } from "@copilotkit/react-core/v2";
|
||||
|
||||
<CopilotSidebar agentId="recipe" />
|
||||
```
|
||||
|
||||
```tsx Popup
|
||||
import { CopilotPopup } from "@copilotkit/react-core/v2";
|
||||
|
||||
<CopilotPopup agentId="recipe" />
|
||||
```
|
||||
|
||||
```tsx Inline
|
||||
import { CopilotChat } from "@copilotkit/react-core/v2";
|
||||
|
||||
<CopilotChat agentId="recipe" />
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Where to go next
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Generative UI" icon="wand-magic-sparkles" href="/edge/en/guides/frontend/generative-ui">
|
||||
Render tool calls and agent state as custom components.
|
||||
</Card>
|
||||
<Card title="Frontend Actions" icon="bolt" href="/edge/en/guides/frontend/frontend-actions">
|
||||
Let the agent call functions that run in the browser.
|
||||
</Card>
|
||||
<Card title="Human-in-the-Loop" icon="user-check" href="/edge/en/guides/frontend/human-in-the-loop">
|
||||
Gate agent actions behind user approval.
|
||||
</Card>
|
||||
<Card title="Predictive State" icon="gauge-high" href="/edge/en/guides/frontend/predictive-state-updates">
|
||||
Stream in-progress state to the UI as the agent works.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,142 +0,0 @@
|
||||
---
|
||||
title: Predictive State Updates
|
||||
description: Stream an in-progress tool call's arguments into agent state so the UI updates optimistically while the agent is still generating.
|
||||
icon: gauge-high
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Show the work as it happens
|
||||
|
||||
Normally a tool call is atomic from the UI's point of view: the agent decides what to write, and your interface only sees the result once the call finishes. For a tool that produces a large document that means a long pause followed by everything snapping into place at once.
|
||||
|
||||
Predictive state updates remove the wait. You project a streaming tool argument onto a field of the agent's state, so as the model generates the argument token by token, that state field fills in live. A document the agent is writing appears in the editor as it is typed, not after.
|
||||
|
||||
<Note>
|
||||
Predictive state relies on a Flow with custom state (`Flow[AgentState]`). It projects a streaming tool argument onto a state field, so there is no equivalent for a bare Crew.
|
||||
</Note>
|
||||
|
||||
## How it compares to Shared State
|
||||
|
||||
Both patterns read the agent's state from the frontend, but they solve different problems:
|
||||
|
||||
| Pattern | What it does |
|
||||
| --- | --- |
|
||||
| **Predictive state** | One-way. Streams an in-progress tool argument into a state field so the UI updates *during* generation, before the call completes. |
|
||||
| **[Shared State](/edge/en/guides/frontend/shared-state)** | Two-way. The UI reads *and writes* the agent's committed state, keeping app and agent in sync across turns. |
|
||||
|
||||
Reach for predictive state when you want an optimistic, in-flight preview of what the agent is producing. Reach for [Shared State](/edge/en/guides/frontend/shared-state) when the user needs to edit that state back.
|
||||
|
||||
## Walkthrough
|
||||
|
||||
This assumes you already have a Crew or Flow served over AG-UI and a CopilotKit frontend wired up. If not, start with the [Frontend Overview](/edge/en/guides/frontend/overview).
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Define a Flow with custom state">
|
||||
|
||||
Predictive state projects a tool argument onto a state field, so your Flow needs a typed state field to receive it. Add the field you want to stream into to your `CopilotKitState` subclass.
|
||||
|
||||
```python
|
||||
from typing import Optional
|
||||
from crewai.flow.flow import Flow, start, router, listen
|
||||
from litellm import acompletion
|
||||
from ag_ui_crewai.sdk import copilotkit_stream, copilotkit_predict_state, CopilotKitState
|
||||
|
||||
WRITE_DOCUMENT_TOOL = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "write_document",
|
||||
"description": "Write the full document in markdown.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"document": {"type": "string", "description": "The document to write"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
class AgentState(CopilotKitState):
|
||||
document: Optional[str] = None
|
||||
|
||||
class DocumentFlow(Flow[AgentState]):
|
||||
@start()
|
||||
@listen("route_follow_up")
|
||||
async def start_flow(self):
|
||||
pass
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Map a state field to a tool argument">
|
||||
|
||||
Call `copilotkit_predict_state` **before** you start streaming the completion. It tells the runtime to project the named tool argument onto the named state field: as the `write_document` call streams its `document` argument, the `document` state field updates live.
|
||||
|
||||
```python
|
||||
@router(start_flow)
|
||||
async def chat(self):
|
||||
# Map the `document` state field to the `document` argument of write_document.
|
||||
# As the tool call streams, the state field updates live.
|
||||
await copilotkit_predict_state({
|
||||
"document": {"tool_name": "write_document", "tool_argument": "document"},
|
||||
})
|
||||
|
||||
response = await copilotkit_stream(
|
||||
await acompletion(
|
||||
model="openai/gpt-4o",
|
||||
messages=[
|
||||
{"role": "system", "content": "Write and edit the document with write_document."},
|
||||
*self.state.messages,
|
||||
],
|
||||
tools=[*self.state.copilotkit.actions, WRITE_DOCUMENT_TOOL],
|
||||
parallel_tool_calls=False,
|
||||
stream=True,
|
||||
)
|
||||
)
|
||||
message = response.choices[0].message
|
||||
self.state.messages.append(message)
|
||||
```
|
||||
|
||||
The key is `copilotkit_predict_state({ "<state_field>": {"tool_name": ..., "tool_argument": ...} })`. Without it, the frontend would only see `document` once the tool call completed. With it, the partial argument streams onto the field while the agent is still generating.
|
||||
|
||||
Serve the Flow with `add_crewai_flow_fastapi_endpoint(...)` as shown in the [Frontend Overview](/edge/en/guides/frontend/overview).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Read the predicted state on the frontend">
|
||||
|
||||
On the frontend, read the field with `useAgent` and subscribe to state changes. Because the backend is projecting the streaming argument onto `document`, this component re-renders as the agent types.
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { useAgent, UseAgentUpdate } from "@copilotkit/react-core/v2";
|
||||
|
||||
function DocumentView() {
|
||||
const { agent } = useAgent({
|
||||
agentId: "document",
|
||||
updates: [UseAgentUpdate.OnStateChanged],
|
||||
});
|
||||
const document = (agent?.state as { document?: string })?.document ?? "";
|
||||
return <article>{document}</article>; // updates as the agent types
|
||||
}
|
||||
```
|
||||
|
||||
The `document` field fills in progressively as the agent generates the `write_document` call, so the editor updates in real time rather than snapping in at the end.
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Shared State" icon="arrows-rotate" href="/edge/en/guides/frontend/shared-state">
|
||||
Read and write the agent's state two-way.
|
||||
</Card>
|
||||
<Card title="Agentic Generative UI" icon="list-check" href="/edge/en/guides/frontend/agentic-generative-ui">
|
||||
Render live agent state as it changes.
|
||||
</Card>
|
||||
<Card title="Tool-Based Generative UI" icon="puzzle-piece" href="/edge/en/guides/frontend/tool-based-generative-ui">
|
||||
Map agent tool calls to components.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,68 +0,0 @@
|
||||
---
|
||||
title: Reasoning
|
||||
description: Show the model's thinking in the chat automatically, with no component to build.
|
||||
icon: brain
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Thinking, rendered for free
|
||||
|
||||
When a reasoning-capable model thinks before it answers, CopilotKit renders that thinking right in the chat. This is the simplest generative-UI pattern in the whole section: there is nothing to build. No hook, no component, no props. Use a reasoning-capable model, keep the streaming wrapper your Flows already have, and the chat surface from the [Overview](/edge/en/guides/frontend/overview) does the rest.
|
||||
|
||||
## Use a reasoning-capable model
|
||||
|
||||
Reasoning is surfaced automatically by `copilotkit_stream`, which every Flow example already wraps the model call in. The bridge reads the model's reasoning deltas and emits them to the frontend. It is provider-agnostic and works over both of CrewAI's streaming transports, so the only thing you change is the model.
|
||||
|
||||
```python
|
||||
# recipe_flow.py
|
||||
from crewai.flow.flow import Flow, start
|
||||
from ag_ui_crewai.sdk import copilotkit_stream, CopilotKitState
|
||||
from litellm import acompletion
|
||||
|
||||
|
||||
class RecipeFlow(Flow[CopilotKitState]):
|
||||
@start()
|
||||
async def chat(self):
|
||||
response = await copilotkit_stream(
|
||||
acompletion(
|
||||
# any reasoning-capable model, e.g. deepseek-reasoner
|
||||
model="deepseek/deepseek-reasoner",
|
||||
messages=self.state.messages,
|
||||
stream=True,
|
||||
)
|
||||
)
|
||||
message = response.choices[0].message
|
||||
self.state.messages.append(message)
|
||||
```
|
||||
|
||||
Models that emit reasoning over the standard channel include DeepSeek `deepseek-reasoner`, Anthropic extended thinking (Claude), and Gemini thinking, among others. Swap the `model` for one of these and its thinking starts streaming through.
|
||||
|
||||
This works the same for both Crews and Flows, since both run their model calls through `copilotkit_stream`.
|
||||
|
||||
## Render it
|
||||
|
||||
There is no frontend step. The `CopilotChat`, `CopilotSidebar`, or `CopilotPopup` surface you already mounted shows the reasoning as it streams, above the answer it produced.
|
||||
|
||||
```tsx
|
||||
import { CopilotChat } from "@copilotkit/react-core/v2";
|
||||
|
||||
<CopilotChat agentId="recipe" />
|
||||
```
|
||||
|
||||
<Note>
|
||||
There is no `useReasoning` hook and no reasoning component to write. Reasoning is not something you wire up on the frontend; it renders automatically as long as the model emits it.
|
||||
</Note>
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Generative UI" icon="wand-magic-sparkles" href="/edge/en/guides/frontend/generative-ui">
|
||||
The full spectrum, from author-controlled to agent-invented UI.
|
||||
</Card>
|
||||
<Card title="Agentic Generative UI" icon="list-check" href="/edge/en/guides/frontend/agentic-generative-ui">
|
||||
Render live agent state as the Flow works.
|
||||
</Card>
|
||||
<Card title="Frontend Overview" icon="browser" href="/edge/en/guides/frontend/overview">
|
||||
Set up the chat surface and runtime.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,210 +0,0 @@
|
||||
---
|
||||
title: Shared State
|
||||
description: Keep your CrewAI agent's state and your app's UI in two-way sync, so edits on either side flow to the other.
|
||||
icon: arrows-rotate
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## One state, both directions
|
||||
|
||||
Shared state is a single state object that the agent and the UI both read and write. The agent updates it as it works and your React components render it live. When the user edits that same state in the UI, the change flows back so the agent sees it on its next turn.
|
||||
|
||||
The classic example is a recipe: the agent drafts it, the user tweaks an ingredient or an instruction, and the agent picks up from the edited version. Neither side owns the state; they share it.
|
||||
|
||||
<Note>
|
||||
Shared state relies on a Flow with custom state. Define an `AgentState` that subclasses `CopilotKitState` and type your Flow as `Flow[AgentState]`. Crews do not carry custom state, so this pattern is Flow-only.
|
||||
</Note>
|
||||
|
||||
## How it works
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Define the shared state on your Flow">
|
||||
|
||||
Subclass `CopilotKitState` so the agent keeps CopilotKit's message plumbing, then add your own fields. Here the shared field is `recipe`.
|
||||
|
||||
```python
|
||||
# recipe_flow.py
|
||||
import json
|
||||
from typing import List, Optional
|
||||
from pydantic import BaseModel, Field
|
||||
from crewai.flow.flow import Flow, start, router, listen
|
||||
from litellm import acompletion
|
||||
from ag_ui_crewai.sdk import copilotkit_stream, CopilotKitState
|
||||
|
||||
|
||||
class Ingredient(BaseModel):
|
||||
name: str
|
||||
amount: str
|
||||
|
||||
|
||||
class Recipe(BaseModel):
|
||||
title: str
|
||||
ingredients: List[Ingredient] = Field(default_factory=list)
|
||||
instructions: List[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class AgentState(CopilotKitState):
|
||||
recipe: Optional[Recipe] = None
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Read and write the state from the agent">
|
||||
|
||||
The agent reads the current state by dumping it into the system prompt, and writes it back by assigning to `self.state.recipe`. A `generate_recipe` tool lets the model return the updated recipe as structured arguments.
|
||||
|
||||
```python
|
||||
GENERATE_RECIPE_TOOL = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "generate_recipe",
|
||||
"description": "Generate or modify the recipe.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {"recipe": {"type": "object"}},
|
||||
"required": ["recipe"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class SharedStateFlow(Flow[AgentState]):
|
||||
@start()
|
||||
@listen("route_follow_up")
|
||||
async def start_flow(self):
|
||||
pass
|
||||
|
||||
@router(start_flow)
|
||||
async def chat(self):
|
||||
# The current shared state is visible to the model.
|
||||
system_prompt = f"""You help the user build a recipe.
|
||||
Current recipe: {self.state.model_dump_json(indent=2)}
|
||||
Modify it by calling generate_recipe."""
|
||||
|
||||
response = await copilotkit_stream(
|
||||
await acompletion(
|
||||
model="openai/gpt-4o",
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
*self.state.messages,
|
||||
],
|
||||
tools=[*self.state.copilotkit.actions, GENERATE_RECIPE_TOOL],
|
||||
parallel_tool_calls=False,
|
||||
stream=True,
|
||||
)
|
||||
)
|
||||
message = response.choices[0].message
|
||||
self.state.messages.append(message)
|
||||
|
||||
if message.tool_calls:
|
||||
call = message.tool_calls[0]
|
||||
if call.function.name == "generate_recipe":
|
||||
args = json.loads(call.function.arguments)
|
||||
self.state.recipe = Recipe(**args["recipe"]) # write to shared state
|
||||
self.state.messages.append({
|
||||
"role": "tool",
|
||||
"content": "Recipe updated.",
|
||||
"tool_call_id": call.id,
|
||||
})
|
||||
return "route_follow_up"
|
||||
return "route_end"
|
||||
|
||||
@listen("route_end")
|
||||
async def end(self):
|
||||
pass
|
||||
```
|
||||
|
||||
Two things make this shared rather than one-way: dumping `self.state` into the prompt means the agent always works from the latest recipe (including edits the user made in the UI), and assigning `self.state.recipe` puts the new value into the state snapshot sent to connected clients at the end of the step. For updates during a long step, emit explicitly with `copilotkit_emit_state` (see [Agentic Generative UI](/edge/en/guides/frontend/agentic-generative-ui)).
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Serve the Flow over AG-UI">
|
||||
|
||||
Expose the Flow from your FastAPI app with `add_crewai_flow_fastapi_endpoint`, then register it in the CopilotKit runtime. See the [Frontend Overview](/edge/en/guides/frontend/overview) for the full server and runtime setup.
|
||||
|
||||
```python
|
||||
# server.py
|
||||
from fastapi import FastAPI
|
||||
from ag_ui_crewai.endpoint import add_crewai_flow_fastapi_endpoint
|
||||
from recipe_flow import SharedStateFlow
|
||||
|
||||
app = FastAPI(title="CrewAI Agent Server")
|
||||
|
||||
add_crewai_flow_fastapi_endpoint(
|
||||
app=app,
|
||||
flow=SharedStateFlow(),
|
||||
path="/shared_state",
|
||||
)
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Read and write the state from the UI">
|
||||
|
||||
`useAgent` gives you both directions in one hook. Read the shared state off `agent.state`, and write it back with `agent.setState(...)`. Subscribe to `OnStateChanged` so your component re-renders whenever the agent updates the state.
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { useAgent, UseAgentUpdate } from "@copilotkit/react-core/v2";
|
||||
|
||||
function RecipeEditor() {
|
||||
const { agent } = useAgent({
|
||||
agentId: "shared_state",
|
||||
updates: [UseAgentUpdate.OnStateChanged],
|
||||
});
|
||||
|
||||
const state = agent?.state as { recipe?: Recipe } | undefined;
|
||||
const isLoading = agent?.isRunning;
|
||||
|
||||
const recipe = state?.recipe;
|
||||
|
||||
// setState replaces the whole state object, so spread the current
|
||||
// state and override only the field you changed. Passing just
|
||||
// `{ recipe }` would drop messages and other runtime fields.
|
||||
const updateRecipe = (patch: Partial<Recipe>) =>
|
||||
agent?.setState({ ...(agent.state ?? {}), recipe: { ...(recipe ?? {}), ...patch } });
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
value={recipe?.title ?? ""}
|
||||
disabled={isLoading}
|
||||
onChange={(e) => updateRecipe({ title: e.target.value })}
|
||||
/>
|
||||
{/* render inputs for ingredients and instructions the same way */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
`agent.state` reads the shared state, `agent.setState(...)` writes it back so the agent sees the change on its next turn, and `agent.isRunning` reflects whether the agent is currently working.
|
||||
|
||||
<Note>
|
||||
`setState` **replaces** the entire state object rather than merging. Always spread the current state (`{ ...agent.state, ... }`) and override only the fields you are changing, or you will drop the conversation and other runtime fields the agent depends on.
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## The two-way loop
|
||||
|
||||
Putting the pieces together, a single recipe object is kept in sync in both directions:
|
||||
|
||||
- **Agent edits, UI updates.** The Flow assigns `self.state.recipe`, the new value ships in the step's state snapshot, and `OnStateChanged` re-renders your inputs.
|
||||
- **User edits, agent sees it.** A change in the UI calls `agent.setState(...)`, and because the Flow dumps `self.state` into its prompt, the agent works from the edited recipe on its next turn.
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Agentic Generative UI" icon="list-check" href="/edge/en/guides/frontend/agentic-generative-ui">
|
||||
Render live agent state as it changes.
|
||||
</Card>
|
||||
<Card title="Predictive State" icon="gauge-high" href="/edge/en/guides/frontend/predictive-state-updates">
|
||||
Stream in-progress state to the UI as the agent works.
|
||||
</Card>
|
||||
<Card title="Human-in-the-Loop" icon="user-check" href="/edge/en/guides/frontend/human-in-the-loop">
|
||||
Pause the agent to collect user approval or input mid-run.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,235 +0,0 @@
|
||||
---
|
||||
title: Tool-Based Generative UI
|
||||
description: Map a CrewAI agent's tool calls to React components and stream the arguments in as they arrive.
|
||||
icon: puzzle-piece
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## Render tool calls as components
|
||||
|
||||
When your Crew or Flow calls a tool, you rarely want the raw arguments dumped into the chat. Tool-based generative UI maps each tool the agent calls to a React component you own. The agent decides *when* to call the tool; you decide what the user sees.
|
||||
|
||||
Because CopilotKit streams the tool call to the frontend as the model generates it, the arguments fill in progressively. Your component can paint the moment the first field arrives and update as the rest stream in.
|
||||
|
||||
This guide builds a haiku generator: the agent calls a `generate_haiku` tool, and the frontend renders each haiku as a card. It assumes you already have a Crew or Flow talking to a Next.js app. If not, start with the [Frontend Overview](/edge/en/guides/frontend/overview) for the full server, runtime, and provider setup.
|
||||
|
||||
<Note>
|
||||
Tool rendering works with both Crews and Flows. The example below uses a Flow, but the frontend wiring is identical either way.
|
||||
</Note>
|
||||
|
||||
## Walkthrough
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step title="Define the tool on the backend">
|
||||
|
||||
Declare the tool with a JSON schema and pass it to the model. The `copilotkit_stream` wrapper together with `stream=True` is what streams the tool call to the frontend as it is generated, one argument chunk at a time.
|
||||
|
||||
```python
|
||||
# haiku_flow.py
|
||||
from crewai.flow.flow import Flow, start
|
||||
from litellm import acompletion
|
||||
from ag_ui_crewai.sdk import copilotkit_stream, CopilotKitState
|
||||
|
||||
GENERATE_HAIKU_TOOL = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "generate_haiku",
|
||||
"description": "Generate a haiku in Japanese and its English translation",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"japanese": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Three lines in Japanese",
|
||||
},
|
||||
"english": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "Three lines in English",
|
||||
},
|
||||
},
|
||||
"required": ["japanese", "english"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class HaikuFlow(Flow[CopilotKitState]):
|
||||
@start()
|
||||
async def chat(self):
|
||||
system_prompt = "You help the user write haikus. Use the generate_haiku tool."
|
||||
|
||||
response = await copilotkit_stream(
|
||||
await acompletion(
|
||||
model="openai/gpt-4o",
|
||||
messages=[
|
||||
{"role": "system", "content": system_prompt},
|
||||
*self.state.messages,
|
||||
],
|
||||
tools=[GENERATE_HAIKU_TOOL],
|
||||
parallel_tool_calls=False,
|
||||
stream=True,
|
||||
)
|
||||
)
|
||||
|
||||
message = response.choices[0].message
|
||||
self.state.messages.append(message)
|
||||
|
||||
if message.tool_calls:
|
||||
self.state.messages.append({
|
||||
"tool_call_id": message.tool_calls[0].id,
|
||||
"role": "tool",
|
||||
"content": "Haiku generated.",
|
||||
})
|
||||
```
|
||||
|
||||
The tool has no Python implementation. It exists only so the model emits a structured call the frontend can render. After the call, append a short tool result so the conversation stays well-formed for the next turn.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Serve the Flow over AG-UI">
|
||||
|
||||
Expose the Flow from your FastAPI app on its own path:
|
||||
|
||||
```python
|
||||
# server.py
|
||||
from fastapi import FastAPI
|
||||
from ag_ui_crewai.endpoint import add_crewai_flow_fastapi_endpoint
|
||||
from haiku_flow import HaikuFlow
|
||||
|
||||
app = FastAPI(title="CrewAI Agent Server")
|
||||
|
||||
add_crewai_flow_fastapi_endpoint(
|
||||
app=app,
|
||||
flow=HaikuFlow(),
|
||||
path="/haiku",
|
||||
)
|
||||
```
|
||||
|
||||
Register the agent with the CopilotKit runtime and point `<CopilotKit>` at it exactly as shown in the [Frontend Overview](/edge/en/guides/frontend/overview). The rest of this guide assumes the agent is registered under the id `haiku`.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Register the rendering component">
|
||||
|
||||
On the frontend, call `useRenderTool` with the same `name` the backend declared. `useRenderTool` is the hook for *rendering* a tool call: it takes a `render` function and nothing to execute, because this tool is pure display.
|
||||
|
||||
<Note>
|
||||
Use `useRenderTool` when the tool only draws UI. If the tool also needs to *run* something in the browser, use [`useFrontendTool`](/edge/en/guides/frontend/frontend-actions) instead, which pairs a `handler` with an optional `render`.
|
||||
</Note>
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import { useRenderTool } from "@copilotkit/react-core/v2";
|
||||
import { z } from "zod";
|
||||
|
||||
useRenderTool({
|
||||
name: "generate_haiku",
|
||||
parameters: z.object({
|
||||
japanese: z.array(z.string()),
|
||||
english: z.array(z.string()),
|
||||
}),
|
||||
render: ({ args, status }) => {
|
||||
if (!args.japanese) return <></>; // still streaming
|
||||
return <HaikuCard japanese={args.japanese} english={args.english} />;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The tool is scoped to the active agent by the `<CopilotKit agent="haiku">` provider, so no `agentId` is needed here. A few things to note:
|
||||
|
||||
- **`name` must match the backend tool name** exactly (`generate_haiku`). That match is how CopilotKit routes the call to this component.
|
||||
- **`render` receives `{ args, status }`.** `args` fills in progressively as the model streams the call; early on it may be empty or partial. `status` moves through `"inProgress"` / `"executing"` to `"complete"` if you want to show a loading state while arguments stream.
|
||||
- **Guard against partial args.** Return an empty fragment until the fields you need exist. Here we wait for `args.japanese` before rendering the card.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Render the haiku">
|
||||
|
||||
The `render` function delegates to an ordinary React component. Nothing about it is CopilotKit-specific: it takes props and returns markup.
|
||||
|
||||
```tsx
|
||||
function HaikuCard({
|
||||
japanese,
|
||||
english,
|
||||
}: {
|
||||
japanese: string[];
|
||||
english: string[];
|
||||
}) {
|
||||
return (
|
||||
<div className="haiku-card">
|
||||
{japanese.map((line, i) => (
|
||||
<div key={i} className="haiku-line">
|
||||
<span className="jp">{line}</span>
|
||||
<span className="en">{english?.[i]}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Because `english` streams in alongside `japanese`, use optional access (`english?.[i]`) so the card renders cleanly while the translation is still arriving.
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Run it">
|
||||
|
||||
Start both processes and ask the assistant for a haiku. The card renders as the arguments stream in, filling out line by line.
|
||||
|
||||
```bash
|
||||
uvicorn server:app --port 8000 # terminal 1
|
||||
npm run dev # terminal 2
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
## How progressive rendering works
|
||||
|
||||
The model does not emit the tool call all at once. It streams tokens, and CopilotKit re-invokes your `render` function every time a new chunk of arguments arrives:
|
||||
|
||||
1. The call begins. `args` is empty, so your guard returns an empty fragment.
|
||||
2. `args.japanese` fills in line by line. The card appears and grows.
|
||||
3. `args.english` fills in. Translations slot into place.
|
||||
4. The call completes. `args` holds the final, fully-validated object.
|
||||
|
||||
This is why the partial-args guard matters: `render` runs against incomplete data by design. Read only the fields you have, and let the rest paint as they arrive.
|
||||
|
||||
## Backend tools
|
||||
|
||||
The `generate_haiku` tool above has no Python implementation — it exists only so the model emits a structured call the frontend renders. But a **real tool your Crew or Flow runs server-side** renders the same way.
|
||||
|
||||
When an Agent or Crew executes a tool during its run, the bridge surfaces that tool call along with its **result**. Register a `useRenderTool` for the tool's name and read `result` in the render:
|
||||
|
||||
```tsx
|
||||
useRenderTool({
|
||||
name: "get_weather",
|
||||
parameters: z.object({ location: z.string() }),
|
||||
render: ({ args, result, status }) => {
|
||||
if (status !== "complete") return <WeatherSkeleton location={args.location} />;
|
||||
return <WeatherCard data={JSON.parse(result)} />;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
<Note>
|
||||
A backend tool must return a **JSON string**, not a Python dict. The bridge stringifies tool output, so a raw dict arrives as a Python repr the browser cannot `JSON.parse`. Return `json.dumps(...)` from the tool.
|
||||
</Note>
|
||||
|
||||
## Related
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Agentic Generative UI" icon="list-check" href="/edge/en/guides/frontend/agentic-generative-ui">
|
||||
Render live agent state as it changes across a multi-step run.
|
||||
</Card>
|
||||
<Card title="Human-in-the-Loop" icon="user-check" href="/edge/en/guides/frontend/human-in-the-loop">
|
||||
Pause the agent to collect user approval or input mid-run.
|
||||
</Card>
|
||||
<Card title="Frontend Actions" icon="bolt" href="/edge/en/guides/frontend/frontend-actions">
|
||||
Let the agent call functions that run in the browser.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -120,11 +120,6 @@ def add_defaults(ctx):
|
||||
Rewritten inputs flow into task interpolation, so the run behaves as if it was
|
||||
kicked off with the modified dict.
|
||||
|
||||
Prefer `INPUT` for rewriting and treat `EXECUTION_START` as the allow/deny
|
||||
gate. Rewrites at `EXECUTION_START` are still honored — on crews they also
|
||||
feed the `before_kickoff` callbacks; on flows they land exactly like an
|
||||
`INPUT` rewrite.
|
||||
|
||||
### Output Sanitization
|
||||
|
||||
```python
|
||||
@@ -161,10 +156,9 @@ def report_outcome(ctx):
|
||||
```
|
||||
|
||||
Two caveats: `EXECUTION_END` does not fire when `EXECUTION_START` never
|
||||
dispatched (an abort at start means the boundary never opened, so there is no
|
||||
end to pair), and raising `HookAborted` from a failure-path `EXECUTION_END`
|
||||
dispatch is ignored — there is nothing left to abort, and the original error
|
||||
wins.
|
||||
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
|
||||
|
||||
@@ -174,19 +168,6 @@ For a crew run the boundary order is:
|
||||
EXECUTION_START → before_kickoff callbacks → INPUT → tasks execute → OUTPUT → EXECUTION_END
|
||||
```
|
||||
|
||||
For a flow run, the boundary hooks resolve the inputs before the lifecycle
|
||||
events begin:
|
||||
|
||||
```
|
||||
EXECUTION_START → INPUT → FlowStartedEvent → flow methods execute → OUTPUT → EXECUTION_END → FlowFinishedEvent
|
||||
```
|
||||
|
||||
`FlowStartedEvent` carries the hook-resolved inputs, and rewriting
|
||||
`inputs["id"]` in a boundary hook redirects state restoration. An abort at
|
||||
`EXECUTION_START` still surfaces as `FlowStartedEvent` followed by
|
||||
`FlowFailedEvent`, emitted at the abort with the payload as resolved by the
|
||||
hooks that ran before it.
|
||||
|
||||
Hooks at the same point run in registration order, global hooks first, then
|
||||
crew-scoped hooks. Telemetry (`HookDispatchedEvent`) is emitted per dispatch.
|
||||
|
||||
|
||||
@@ -34,20 +34,6 @@ os.environ['CREWAI_DISABLE_TELEMETRY'] = 'true'
|
||||
os.environ['OTEL_SDK_DISABLED'] = 'true'
|
||||
```
|
||||
|
||||
### Isolation from your own OpenTelemetry setup
|
||||
|
||||
CrewAI's telemetry runs on its own private `TracerProvider` and never registers
|
||||
itself as the global one. This keeps the two directions separate:
|
||||
|
||||
- Spans from other instrumented libraries in your process — web frameworks,
|
||||
database clients, HTTP clients — are never sent to CrewAI.
|
||||
- CrewAI's telemetry spans are never sent to your observability backend, so they
|
||||
will not appear in Langfuse, Braintrust, Phoenix, or any other collector you
|
||||
configure.
|
||||
|
||||
Observability integrations are unaffected: they instrument CrewAI through their
|
||||
own tracer provider, which is independent of the one described here.
|
||||
|
||||
### Data Explanation:
|
||||
| Defaulted | Data | Reason and Specifics |
|
||||
|:----------|:------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------|
|
||||
@@ -59,10 +45,7 @@ own tracer provider, which is independent of the one described here.
|
||||
| Yes | Test Execution Data | Includes: crew's randomly generated key and ID, number of iterations, model name used, quality score (float), execution time (in seconds). All non-personal. |
|
||||
| Yes | Task Lifecycle Data | Includes: creation and execution start/end times, crew and task identifiers. Stored as spans with timestamps. No personal data. |
|
||||
| Yes | LLM Attributes | Includes: name, model_name, model, top_k, temperature, and class name of the LLM. All technical, non-personal data. |
|
||||
| Yes | Crew Deployment attempt using crewAI CLI | Includes: The fact a deploy is being made and crew id, whether it's trying to pull logs, and whether the deploy was started from a CLI command or from the run TUI. No project or crew contents. No personal data. |
|
||||
| Yes | Execution Environment | Includes: which AI coding assistant is running the process, if any (one of a fixed list such as `claude_code`, `codex`, `cursor`, or `unknown`), where the process runs (one of a fixed list such as `ci`, `container`, `serverless`, `interactive`), and the `project_id` from your `pyproject.toml` when one is configured. Detection reads only whether known environment variables are set, never their values. No personal data. |
|
||||
| Yes | Flow Lifecycle Signals | Includes: that a flow started, whether it completed or failed, whether one of its methods failed, whether it paused for human input or feedback, whether the start was a resumed run, whether a conversation turn failed, how long the flow ran, and whether the flow is one CrewAI runs internally or one you wrote. The flow name is recorded, as it already is for flow creation and execution. When a flow or one of its methods fails, the **class name** of the exception is recorded (for example `TimeoutError`) so that failures can be diagnosed — never the error message, which can contain prompts, model output, file paths or credentials. Method names and flow state are never recorded. No personal data. |
|
||||
| Yes | Trace Sharing Signal | Includes: that a batch of traces was successfully shared with CrewAI AMP, and whether it was shared anonymously (before you have an account) or linked to your account. Like every span, it also carries the Execution Environment attributes described above (`project_id` when configured, the coding assistant, and the runtime). This row describes sharing telemetry only — not the trace contents or access granted by shared trace links. Trace contents, inputs, and outputs are never recorded on this signal. Before sharing traces, review secrets, personal data, and AMP redaction and retention settings. |
|
||||
| Yes | Crew Deployment attempt using crewAI CLI | Includes: The fact a deploy is being made and crew id, and if it's trying to pull logs, no other data. |
|
||||
| No | Agent's Expanded Data | Includes: goal description, backstory text, i18n prompt file identifier. Users should ensure no personal info is included in text fields. |
|
||||
| No | Detailed Task Information | Includes: task description, expected output description, context references. Users should ensure no personal info is included in these fields. |
|
||||
| No | Environment Information | Includes: platform, release, system, version, and CPU count. Example: 'Windows 10', 'x86_64'. No personal data. |
|
||||
|
||||
@@ -77,4 +77,4 @@ To let an agent read a directory tree outside the working directory, point `base
|
||||
file_read_tool = FileReadTool(base_dir='/data')
|
||||
```
|
||||
|
||||
As a last resort, setting `CREWAI_TOOLS_ALLOW_UNSAFE_PATHS=true` disables path validation. This applies process-wide to every crewai-tools tool, including the SSRF protections on URL-fetching tools, so prefer `base_dir`. Managed workers should set `CREWAI_TOOLS_FORCE_SAFE_PATHS=true` so a tenant cannot disable those checks by exporting the escape hatch.
|
||||
As a last resort, setting `CREWAI_TOOLS_ALLOW_UNSAFE_PATHS=true` disables path validation. This applies process-wide to every crewai-tools tool, including the SSRF protections on URL-fetching tools, so prefer `base_dir`.
|
||||
|
||||
@@ -9,7 +9,7 @@ mode: "wide"
|
||||
|
||||
## Description
|
||||
|
||||
The `ScrapeElementFromWebsiteTool` is designed to extract specific elements from websites using CSS selectors. This tool allows CrewAI agents to scrape targeted content from web pages, making it useful for data extraction tasks where only specific parts of a webpage are needed. Fetches go through CrewAI's SSRF-safe HTTP helper: the requested URL and every redirect hop are checked against private and reserved ranges (including cloud metadata), and the TCP connection is pinned to an IP that passed that check.
|
||||
The `ScrapeElementFromWebsiteTool` is designed to extract specific elements from websites using CSS selectors. This tool allows CrewAI agents to scrape targeted content from web pages, making it useful for data extraction tasks where only specific parts of a webpage are needed.
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ mode: "wide"
|
||||
A tool designed to extract and read the content of a specified website. It is capable of handling various types of web pages by making HTTP requests and parsing the received HTML content.
|
||||
This tool can be particularly useful for web scraping tasks, data collection, or extracting specific information from websites.
|
||||
|
||||
Fetches go through CrewAI's SSRF-safe HTTP helper: the requested URL and every redirect hop are checked against private and reserved ranges (including cloud metadata), and the TCP connection is pinned to an IP that passed that check.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the crewai_tools package
|
||||
|
||||
@@ -4,192 +4,6 @@ description: "CrewAI의 제품 업데이트, 개선 사항 및 버그 수정"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="2026년 8월 19일">
|
||||
## v1.15.17
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.15.17)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- 선언적 대화 흐름 문서 추가
|
||||
- 선언을 위한 내장 대화 방법 합성
|
||||
- 선언이 대화 모드를 주도할 수 있도록 활성화
|
||||
- 대화 선택 참여를 명확하게 표시
|
||||
- 슬러그 참조에서 해결된 도구에 AMP 슬러그 전달
|
||||
- 청크 처리 중 과도한 단일 메시지 처리
|
||||
|
||||
### 버그 수정
|
||||
- MCP HTTP 및 SSE server_name으로 URL 호스트 이름 사용 수정
|
||||
- 모든 실패한 시도에서 에이전트 범위 닫기
|
||||
- 도구 오류를 실패한 도구에 귀속
|
||||
- 각 리디렉션 홉 및 피어 IP에 SSRF 검사 고정
|
||||
- OpenAI Responses API를 통해 깨진 네이티브 도구 호출 문제 해결
|
||||
|
||||
### 문서
|
||||
- v1.15.16에 대한 스냅샷 및 변경 로그로 문서 업데이트
|
||||
|
||||
## 기여자
|
||||
|
||||
@Copilot, @Vidit-Ostwal, @github-code-quality[bot], @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 8월 13일">
|
||||
## v1.15.16
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.15.16)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- UUID 지원을 통한 실행 컨텍스트 관리 도입
|
||||
- 흐름을 종료한 예외의 종류 기록
|
||||
- 트레이스 배치가 AMP와 공유된 시점 기록
|
||||
- 모든 출처에서 배포를 카운트하고 시작 위치 기록
|
||||
|
||||
### 버그 수정
|
||||
- 모든 생성된 스팬에서 실행 중인 릴리스를 기록
|
||||
- MySQL 검색 테이블 이름 유효성 검사 수정
|
||||
- 실패한 턴이 다음 턴을 실패로 표시하지 않도록 중지
|
||||
|
||||
### 문서
|
||||
- CopilotKit 및 AG-UI에 대한 프론트엔드 가이드 추가
|
||||
|
||||
## 기여자
|
||||
|
||||
@joaomdmoura, @lorenzejay, @ranst91, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 8월 11일">
|
||||
## v1.15.15
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.15.15)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- 보고서 흐름 결과, 지속 시간 및 인간 개입 신호를 보고합니다.
|
||||
|
||||
### 버그 수정
|
||||
- 경계 후크가 흐름을 중단할 때 FlowStartedEvent를 발생시킵니다.
|
||||
- 범위 스팬 내보내기를 우리 고유의 트레이서 제공자로 제한합니다.
|
||||
- 보안 취약점을 해결하기 위해 torch를 2.13.0 버전으로 업데이트합니다.
|
||||
- crewai-tools[github]에서 gitpython을 3.1.58 버전으로 업데이트합니다.
|
||||
|
||||
### 리팩토링
|
||||
- 에이전트의 날짜 주입 기능을 업데이트합니다.
|
||||
- CLI 플래그를 케밥 케이스로 표준화합니다.
|
||||
|
||||
### 문서
|
||||
- v1.15.14에 대한 스냅샷 및 변경 로그.
|
||||
|
||||
## 기여자
|
||||
|
||||
@Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 8월 8일">
|
||||
## v1.15.14
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.15.14)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- 코딩 에이전트와 런타임 컨텍스트 분리 및 프로젝트 ID 추가
|
||||
|
||||
### 문서
|
||||
- v1.15.13에 대한 스냅샷 및 변경 로그 업데이트
|
||||
|
||||
## 기여자
|
||||
|
||||
@joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 8월 7일">
|
||||
## 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
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 8월 5일">
|
||||
## v1.15.12
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.15.12)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- 릴리스 시 Flow 카나리 버전 증가
|
||||
- 임의의 URL을 읽기 위한 URLReadTool 추가
|
||||
- 플랫폼 액션 도구에 앱 메타데이터 추가
|
||||
- `crewai create <resource>` 아래에서 스캐폴딩 통합
|
||||
|
||||
### 버그 수정
|
||||
- 대화형 경로/핸들러 이름 충돌 오류 명확화
|
||||
|
||||
### 문서
|
||||
- 통합된 생성 CLI를 위한 AGENTS.md 스캐폴드 업데이트
|
||||
|
||||
### 주요 변경 사항
|
||||
- 없음
|
||||
|
||||
## 기여자
|
||||
|
||||
@Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 8월 4일">
|
||||
## v1.15.11
|
||||
|
||||
[GitHub 릴리스 보기](https://github.com/crewAIInc/crewAI/releases/tag/1.15.11)
|
||||
|
||||
## 변경 사항
|
||||
|
||||
### 기능
|
||||
- 텔레메트리에서 인터셉션 훅 디스패치를 추적합니다.
|
||||
- OSS 사용을 기업 계정에 연결하기 위해 project_id를 추가합니다.
|
||||
- AGENTS.md에서 AMP를 표시하고 텔레메트리에서 코딩 에이전트를 감지합니다.
|
||||
- IBM Db2 검색 도구를 추가합니다.
|
||||
|
||||
### 버그 수정
|
||||
- CodeQL의 불완전한 URL 하위 문자열 정화 경고를 지웁니다.
|
||||
- 여섯 개의 GHSA 권고 사항을 해결하기 위해 aiohttp와 cryptography를 업데이트합니다.
|
||||
- 맵 리터럴 내 실패에 대한 실제 CEL 오류를 보고합니다.
|
||||
- 문서 전용 PR에 대해 코드 CI를 올바르게 건너뜁니다.
|
||||
|
||||
### 문서
|
||||
- v1.15.10에 대한 스냅샷 및 변경 로그
|
||||
|
||||
## 기여자
|
||||
|
||||
@PawanThakurIBM, @Vidit-Ostwal, @gabemilani, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026년 7월 31일">
|
||||
## v1.15.10
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ CrewAI AOP에는 코드를 작성하지 않고도 에이전트 생성 및 구성
|
||||
| **컨텍스트 윈도우 준수** _(옵션)_ | `respect_context_window` | `bool` | 메시지를 컨텍스트 윈도우 크기 내로 유지하기 위하여 요약 기능을 사용합니다. 기본값은 True입니다. |
|
||||
| **코드 실행 모드** _(옵션)_ | `code_execution_mode` | `Literal["safe", "unsafe"]` | 코드 실행 모드: 'safe'(Docker 사용) 또는 'unsafe'(직접 실행). 기본값은 'safe'입니다. |
|
||||
| **멀티모달** _(옵션)_ | `multimodal` | `bool` | 에이전트가 멀티모달 기능을 지원하는지 여부입니다. 기본값은 False입니다. |
|
||||
| **날짜 자동 삽입** _(옵션)_ | `inject_date` | `bool` | 에이전트 프롬프트에 현재 날짜를 자동으로 삽입할지 여부입니다. 기본값은 False입니다. |
|
||||
| **날짜 자동 삽입** _(옵션)_ | `inject_date` | `bool` | 작업에 현재 날짜를 자동으로 삽입할지 여부입니다. 기본값은 False입니다. |
|
||||
| **날짜 형식** _(옵션)_ | `date_format` | `str` | inject_date 활성화 시 날짜 표시 형식 문자열입니다. 기본값은 "%Y-%m-%d"(ISO 포맷)입니다. |
|
||||
| **추론** _(옵션)_ | `reasoning` | `bool` | 에이전트가 작업을 실행하기 전에 반영 및 플랜을 생성할지 여부입니다. 기본값은 False입니다. |
|
||||
| **최대 추론 시도 수** _(옵션)_ | `max_reasoning_attempts` | `Optional[int]` | 작업 실행 전 최대 추론 시도 횟수입니다. 설정하지 않으면 준비될 때까지 시도합니다. |
|
||||
@@ -267,7 +267,7 @@ strategic_agent = Agent(
|
||||
role="Market Analyst",
|
||||
goal="Track market movements with precise date references and strategic planning",
|
||||
backstory="Expert in time-sensitive financial analysis and strategic reporting",
|
||||
inject_date=True, # Automatically inject current date into the prompt
|
||||
inject_date=True, # Automatically inject current date into tasks
|
||||
date_format="%B %d, %Y", # Format as "May 21, 2025"
|
||||
reasoning=True, # Enable strategic planning
|
||||
max_reasoning_attempts=2, # Limit planning iterations
|
||||
@@ -328,7 +328,7 @@ multimodal_agent = Agent(
|
||||
#### 고급 기능
|
||||
- `multimodal`: 텍스트와 시각적 콘텐츠 처리를 위한 멀티모달 기능 활성화
|
||||
- `reasoning`: 에이전트가 작업을 수행하기 전에 반영하고 계획을 작성할 수 있도록 활성화
|
||||
- `inject_date`: 현재 날짜를 에이전트 프롬프트에 자동으로 삽입
|
||||
- `inject_date`: 현재 날짜를 작업 설명에 자동으로 삽입
|
||||
|
||||
#### 템플릿
|
||||
- `system_template`: 에이전트의 핵심 동작을 정의합니다
|
||||
|
||||
@@ -54,16 +54,6 @@ crewai create flow my_new_flow
|
||||
|
||||
기본적으로 `crewai create crew`는 `crew.jsonc`와 `agents/*.jsonc`가 있는 JSON-first 프로젝트를 만듭니다. `crew.py`, `config/agents.yaml`, `config/tasks.yaml`을 사용하는 기존 Python/YAML 스캐폴드가 필요할 때만 `crewai create crew my_new_crew --classic`을 사용하세요.
|
||||
|
||||
#### 사용 중단된 플래그 별칭
|
||||
|
||||
이전 snake_case 플래그는 여전히 동작하지만 `--help`에는 표시되지 않습니다. 아래 각 명령 섹션에 문서화된 kebab-case 형식을 사용하세요.
|
||||
|
||||
| 사용 중단 | 대신 사용 |
|
||||
| :--- | :--- |
|
||||
| `--skip_provider` (`crewai create crew`) | `--skip-provider` |
|
||||
| `--n_iterations` (`crewai train`, `crewai test`) | `--n-iterations` |
|
||||
| `--task_id` (`crewai replay`) | `--task-id` |
|
||||
|
||||
### 2. 버전
|
||||
|
||||
설치된 CrewAI의 버전을 표시합니다.
|
||||
@@ -89,7 +79,7 @@ crewai version --tools
|
||||
crewai train [OPTIONS]
|
||||
```
|
||||
|
||||
- `-n, --n-iterations INTEGER`: crew를 훈련할 반복 횟수 (기본값: 5)
|
||||
- `-n, --n_iterations INTEGER`: crew를 훈련할 반복 횟수 (기본값: 5)
|
||||
- `-f, --filename TEXT`: 훈련에 사용할 커스텀 파일의 경로 (기본값: "trained_agents_data.pkl")
|
||||
|
||||
예시:
|
||||
@@ -106,7 +96,7 @@ crewai train -n 10 -f my_training_data.pkl
|
||||
crewai replay [OPTIONS]
|
||||
```
|
||||
|
||||
- `-t, --task-id TEXT`: 이 task ID에서부터 crew를 다시 재생하며, 이후의 모든 task를 포함합니다.
|
||||
- `-t, --task_id TEXT`: 이 task ID에서부터 crew를 다시 재생하며, 이후의 모든 task를 포함합니다.
|
||||
|
||||
예시:
|
||||
|
||||
@@ -153,7 +143,7 @@ crew를 테스트하고 결과를 평가합니다.
|
||||
crewai test [OPTIONS]
|
||||
```
|
||||
|
||||
- `-n, --n-iterations INTEGER`: crew를 테스트할 반복 횟수 (기본값: 3)
|
||||
- `-n, --n_iterations INTEGER`: crew를 테스트할 반복 횟수 (기본값: 3)
|
||||
- `-m, --model TEXT`: Crew에서 테스트를 실행할 LLM 모델 (기본값: "gpt-4o-mini")
|
||||
|
||||
예시:
|
||||
|
||||
@@ -324,8 +324,6 @@ 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])
|
||||
|
||||
@@ -261,24 +261,6 @@ print(flow.usage_metrics)
|
||||
**전체** 토큰 집계가 필요할 때는 항상 `flow.usage_metrics`를 사용하십시오.
|
||||
</Note>
|
||||
|
||||
### 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()` 완료 후 언제든지 안전하게 읽을 수 있으며, 실행 중에 읽으면 그 시점까지 누적된 부분 합계를 반환합니다.
|
||||
|
||||
## 플로우 상태 관리
|
||||
|
||||
@@ -270,21 +270,6 @@ CrewAI는 고유한 기능, 인증 방법, 모델 역량을 제공하는 다양
|
||||
)
|
||||
```
|
||||
|
||||
**토큰 사용량 및 프롬프트 캐싱:**
|
||||
|
||||
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)를 검토하세요.
|
||||
</Accordion>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ crewai test
|
||||
더 많은 반복 횟수로 실행하거나 다른 모델을 사용하려면 다음과 같이 매개변수를 지정할 수 있습니다:
|
||||
|
||||
```bash
|
||||
crewai test --n-iterations 5 --model gpt-4o
|
||||
crewai test --n_iterations 5 --model gpt-4o
|
||||
```
|
||||
|
||||
또는 축약형을 사용할 수 있습니다:
|
||||
@@ -29,11 +29,6 @@ crewai test --n-iterations 5 --model gpt-4o
|
||||
crewai test -n 5 -m gpt-4o
|
||||
```
|
||||
|
||||
<Note>
|
||||
이전 `--n_iterations` 플래그는 여전히 동작하지만 사용 중단되었으며 `--help`에는
|
||||
표시되지 않습니다. 대신 `--n-iterations`(또는 `-n`)를 사용하세요.
|
||||
</Note>
|
||||
|
||||
`crewai test` 명령어를 실행하면 crew가 지정한 횟수만큼 실행되고, 수행이 끝나면 성능 지표가 표시됩니다.
|
||||
|
||||
실행 마지막에 표시되는 점수 표는 다음과 같은 지표로 crew의 성능을 보여줍니다:
|
||||
|
||||
@@ -427,70 +427,6 @@ LLM router를 우회해 프로그램적으로 라우트를 선택하려면 `rout
|
||||
|
||||
`ConversationConfig.visible_agent_outputs`로 특정 에이전트의 private 결과를 전역적으로 public으로 승격할 수 있습니다 (`"all"` 또는 이름 리스트).
|
||||
|
||||
## JSON/YAML로 대화형 플로우 선언하기
|
||||
|
||||
[선언적 플로우](/edge/en/concepts/cli)도 대화형이 될 수 있습니다. 최상위 `conversational` 블록을 추가하고, 라우트 레이블을 `listen`하는 메서드로 직접 라우트를 선언하세요:
|
||||
|
||||
```yaml
|
||||
schema: crewai.flow/v1
|
||||
name: SupportFlow
|
||||
|
||||
conversational:
|
||||
system_prompt: You are a terse support assistant.
|
||||
llm: gpt-4o-mini
|
||||
router:
|
||||
llm: gpt-4o-mini
|
||||
|
||||
methods:
|
||||
handle_order:
|
||||
description: Order status, shipping and delivery questions.
|
||||
listen: order
|
||||
do:
|
||||
call: agent
|
||||
with:
|
||||
role: Support specialist
|
||||
goal: Answer order questions accurately
|
||||
backstory: Knows the fulfilment pipeline.
|
||||
input: "${state.current_user_message}"
|
||||
```
|
||||
|
||||
블록을 선언하는 것 자체가 옵트인입니다 — `enabled`의 기본값은 `true`입니다. 설정은 유지하면서 채팅만 끄려면 `enabled: false`로 지정하세요.
|
||||
|
||||
세 가지가 자동으로 제공됩니다:
|
||||
|
||||
| 제공 항목 | 설명 |
|
||||
|----------|--------|
|
||||
| 내장 그래프 | `route_conversation`, `converse_turn`, `end_conversation`, `answer_from_history_turn`이 자동으로 추가됩니다. 같은 이름의 메서드를 선언하면 재정의됩니다. |
|
||||
| 대화 상태 | 선언에 `state` 블록이 없으면 `ConversationState`가 사용됩니다. 필드를 추가하려면 `ConversationState`를 상속한 Pydantic 모델을 `state`에 지정하세요. |
|
||||
| 라우트 카탈로그 | `listen` 레이블을 선언한 메서드들로부터 구성됩니다. 각 메서드의 `description`이 라우팅 모델이 라우트를 선택할 때 읽는 내용입니다. |
|
||||
|
||||
클래스 기반 대화형 플로우와 동일한 턴 API로 Python에서 실행합니다:
|
||||
|
||||
```python
|
||||
from crewai.flow import Flow
|
||||
|
||||
flow = Flow.from_declaration(path="flow.yaml")
|
||||
|
||||
try:
|
||||
flow.handle_turn("Where is my order?", session_id="session-1")
|
||||
finally:
|
||||
flow.finalize_session_traces()
|
||||
```
|
||||
|
||||
### 라우트 이름 짓기
|
||||
|
||||
라우트 레이블과 메서드 이름은 하나의 트리거 네임스페이스를 공유하므로, 핸들러 이름이 자신이 listen하는 라우트와 같으면 안 됩니다 — `create_video`가 `create_video`를 listen하면 플로우 생성 시 거부됩니다. `handle_*` 접두사를 사용하세요.
|
||||
|
||||
### 선언으로 표현할 수 없는 것
|
||||
|
||||
| 표현 불가 | 대신 사용 |
|
||||
|-----------------|-------------|
|
||||
| 살아 있는 `LLM` 인스턴스나 커스텀 `BaseLLM` | `gpt-4o-mini` 같은 모델 ID 문자열 |
|
||||
| 모델 클래스로서의 `router.response_format` | 생략하세요; 프레임워크가 생성합니다. ref나 스키마는 경고와 함께 무시됩니다 |
|
||||
| `route_turn()` / `can_answer_from_history()` 재정의 | 플로우를 Python으로 작성하거나, 메서드의 `do`를 `call: code` ref로 지정하세요 |
|
||||
|
||||
`crewai run`에는 아직 채팅 루프가 없습니다: 단일 턴을 실행하는 대신 플로우가 대화형임을 알리고 종료합니다. 선언적 대화형 플로우는 Python에서 `handle_turn()`, `stream_turn()`, `chat()`으로 실행하세요.
|
||||
|
||||
## 턴 간 트레이싱
|
||||
|
||||
`defer_trace_finalization=True` (`ConversationalConfig` 기본값):
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
---
|
||||
title: 실행 경계 훅
|
||||
description: "@on 데코레이터로 crew와 flow 실행의 시작, 입력, 출력, 종료를 가로채기"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
실행 경계 훅은 실행의 가장 바깥쪽 경계를 가로챕니다 — 작업이 시작되기 전,
|
||||
입력이 확정될 때, 최종 결과가 준비될 때, 그리고 실행이 끝날 때입니다. 크루와
|
||||
플로우 모두에서 발생하며, 실행 수준의 정책 검사, 입력 재작성, 출력 정제에
|
||||
적합한 위치입니다.
|
||||
|
||||
## 개요
|
||||
|
||||
네 가지 인터셉션 포인트가 경계를 담당합니다:
|
||||
|
||||
| 포인트 | 시점 | `ctx.payload` |
|
||||
|--------|------|---------------|
|
||||
| `EXECUTION_START` | 크루 또는 플로우가 막 시작되려는 시점 | 입력 `dict` |
|
||||
| `INPUT` | 실행을 위한 입력이 확정된 시점 | 입력 `dict` |
|
||||
| `OUTPUT` | 최종 결과가 준비된 시점 | 출력 객체 |
|
||||
| `EXECUTION_END` | 실행이 끝난 시점(성공 또는 실패) | 출력 객체, 실패 시 `None` |
|
||||
|
||||
크루의 경우 출력 payload는 `CrewOutput`입니다. 플로우의 경우 최종 플로우
|
||||
메서드의 결과입니다.
|
||||
|
||||
## 훅 시그니처
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
경계 훅은 표준 계약을 따릅니다: 진행(`return None`), 제자리(in-place) 수정,
|
||||
값을 반환하여 교체, 또는 `HookAborted`를 발생시켜 중단합니다. 어떤
|
||||
경계에서든 중단(abort)은 그 사유와 함께 `kickoff()` 밖으로 전파됩니다.
|
||||
|
||||
## 컨텍스트 스키마
|
||||
|
||||
각 포인트는 타입이 지정된 컨텍스트를 받습니다. 모든 컨텍스트는 공통 기본
|
||||
필드를 공유합니다:
|
||||
|
||||
```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)
|
||||
```
|
||||
|
||||
포인트별 컨텍스트는 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"
|
||||
```
|
||||
|
||||
<Note>
|
||||
`ctx.inputs`는 **원본** 입력 dict의 별칭이므로, 어느 이름으로든 제자리
|
||||
수정은 동일하게 동작합니다. 이전 훅이 새 dict를 반환하여 payload를
|
||||
*교체*했다면 `ctx.payload`만 다시 바인딩됩니다 — 훅이 연쇄될 수 있는 경우
|
||||
항상 `ctx.payload`를 읽고 쓰세요.
|
||||
</Note>
|
||||
|
||||
## 크루 실행 vs. 플로우 실행
|
||||
|
||||
경계 훅은 두 런타임 모두에서 발생하며, 크루 실행은 내부적으로 플로우 런타임
|
||||
위에서 동작합니다. 따라서 `crew.kickoff()` 중에는 전역 경계 훅이 크루
|
||||
경계(`ctx.crew` 설정, `ctx.flow`는 `None`)**와** 내부 플로우(`ctx.flow`
|
||||
설정, `ctx.crew`는 `None`) 모두에서 발생합니다. 런타임으로 구분하세요:
|
||||
|
||||
```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()
|
||||
```
|
||||
|
||||
## 일반적인 사용 사례
|
||||
|
||||
### 시작 시 정책 검사
|
||||
|
||||
```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")
|
||||
```
|
||||
|
||||
### 입력 재작성
|
||||
|
||||
```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()
|
||||
```
|
||||
|
||||
재작성된 입력은 태스크 보간(interpolation)으로 흘러가므로, 실행은 수정된
|
||||
dict로 시작된 것처럼 동작합니다.
|
||||
|
||||
재작성에는 `INPUT`을 사용하고, `EXECUTION_START`는 허용/거부 게이트로
|
||||
취급하세요. `EXECUTION_START`에서의 재작성도 여전히 반영됩니다 — 크루에서는
|
||||
`before_kickoff` 콜백에도 전달되고, 플로우에서는 `INPUT` 재작성과 동일하게
|
||||
적용됩니다.
|
||||
|
||||
### 출력 정제
|
||||
|
||||
```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`은 `EXECUTION_END`보다 먼저 실행되며, 둘 다 이전 훅에서 (교체되었을
|
||||
수 있는) payload를 봅니다. 최종적으로 재작성된 값이 `kickoff()`가 반환하는
|
||||
값입니다.
|
||||
|
||||
### 실패 관찰
|
||||
|
||||
`EXECUTION_END`는 성공이든 실패든 실행마다 정확히 한 번 발생합니다. 실행이
|
||||
예외를 던지면 — 태스크 오류, 플로우 메서드 예외, 또는 이전 포인트의
|
||||
`HookAborted` — 훅은 `ctx.error`에 예외가 담긴 `status="failed"`를 받으며,
|
||||
원래 예외는 변경 없이 `kickoff()` 밖으로 전파됩니다:
|
||||
|
||||
```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")
|
||||
```
|
||||
|
||||
두 가지 주의 사항: `EXECUTION_START`가 디스패치되지 않았다면
|
||||
`EXECUTION_END`는 발생하지 않습니다(시작 시점의 중단은 경계가 열리지
|
||||
않았다는 뜻이므로 짝을 이룰 종료가 없습니다). 또한 실패 경로의
|
||||
`EXECUTION_END` 디스패치에서 `HookAborted`를 발생시키는 것은 무시됩니다 —
|
||||
더 이상 중단할 것이 없고, 원래 오류가 우선합니다.
|
||||
|
||||
## 순서
|
||||
|
||||
크루 실행의 경계 순서는 다음과 같습니다:
|
||||
|
||||
```
|
||||
EXECUTION_START → before_kickoff callbacks → INPUT → tasks execute → OUTPUT → EXECUTION_END
|
||||
```
|
||||
|
||||
플로우 실행에서는 라이프사이클 이벤트가 시작되기 전에 경계 훅이 입력을
|
||||
확정합니다:
|
||||
|
||||
```
|
||||
EXECUTION_START → INPUT → FlowStartedEvent → flow methods execute → OUTPUT → EXECUTION_END → FlowFinishedEvent
|
||||
```
|
||||
|
||||
`FlowStartedEvent`는 훅이 확정한 입력을 담으며, 경계 훅에서 `inputs["id"]`를
|
||||
재작성하면 상태 복원 대상이 바뀝니다. `EXECUTION_START`에서의 중단은 여전히
|
||||
`FlowStartedEvent` 다음에 `FlowFailedEvent`가 오는 형태로 나타나며, 중단
|
||||
시점에 그때까지 실행된 훅이 확정한 페이로드와 함께 발생합니다.
|
||||
|
||||
같은 포인트의 훅은 등록 순서대로 실행되며, 전역 훅이 먼저, 그다음 크루 범위
|
||||
훅이 실행됩니다. 텔레메트리(`HookDispatchedEvent`)는 디스패치마다
|
||||
발생합니다.
|
||||
|
||||
## 테스트에서 훅 관리
|
||||
|
||||
```python
|
||||
from crewai.hooks import clear_all_hooks
|
||||
|
||||
clear_all_hooks() # Clears every point, including boundaries
|
||||
```
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [실행 훅 개요 →](/edge/ko/learn/execution-hooks)
|
||||
- [LLM 호출 훅 →](/edge/ko/learn/llm-hooks)
|
||||
- [도구 호출 훅 →](/edge/ko/learn/tool-hooks)
|
||||
@@ -33,19 +33,6 @@ os.environ['CREWAI_DISABLE_TELEMETRY'] = 'true'
|
||||
os.environ['OTEL_SDK_DISABLED'] = 'true'
|
||||
```
|
||||
|
||||
### 사용자 OpenTelemetry 설정과의 격리
|
||||
|
||||
CrewAI의 telemetry는 자체 전용 `TracerProvider`에서 실행되며 자신을 전역
|
||||
provider로 등록하지 않습니다. 이를 통해 양방향이 분리됩니다:
|
||||
|
||||
- 프로세스 내 다른 계측된 라이브러리(웹 프레임워크, 데이터베이스 클라이언트,
|
||||
HTTP 클라이언트)의 span은 CrewAI로 전송되지 않습니다.
|
||||
- CrewAI의 telemetry span은 사용자의 관측 가능성 백엔드로 전송되지 않으므로
|
||||
Langfuse, Braintrust, Phoenix 또는 구성한 다른 수집기에 나타나지 않습니다.
|
||||
|
||||
관측 가능성 통합은 영향을 받지 않습니다: 해당 통합은 여기서 설명한 provider와
|
||||
독립적인 자체 tracer provider를 통해 CrewAI를 계측합니다.
|
||||
|
||||
### 데이터 설명:
|
||||
| 기본값 | 데이터 | 사유 및 세부 사항 |
|
||||
|:--------|:-------------------------------------------|:----------------------------------------------------------------------------------------------------------------------|
|
||||
@@ -57,10 +44,7 @@ provider로 등록하지 않습니다. 이를 통해 양방향이 분리됩니
|
||||
| 예 | 테스트 실행 데이터 | crew의 랜덤 생성 키와 ID, 반복 횟수, 사용된 모델명, 품질 점수(실수), 실행 시간(초 단위)이 포함됩니다. 모두 비개인 정보입니다. |
|
||||
| 예 | 작업 라이프사이클 데이터 | 생성 및 실행 시작/종료 시각, crew 및 작업 식별자가 포함됩니다. 타임스탬프를 포함한 span으로 저장됩니다. 개인 정보 없음. |
|
||||
| 예 | LLM 속성 | LLM의 이름, model_name, 모델, top_k, temperature 및 클래스명이 포함됩니다. 모두 기술적이고 비개인 정보입니다. |
|
||||
| 예 | crewAI CLI를 통한 Crew 배포 시도 | 포함 항목: 배포가 시도되고 있다는 사실과 crew id, 로그를 가져오려고 하는지 여부, 그리고 배포가 CLI 명령에서 시작되었는지 실행 TUI에서 시작되었는지 여부. 프로젝트나 crew의 내용은 기록되지 않습니다. 개인 정보 없음. |
|
||||
| 예 | 실행 환경 | 포함: 프로세스를 실행 중인 AI 코딩 어시스턴트(있는 경우, `claude_code`, `codex`, `cursor`, `unknown` 등 고정 목록 중 하나), 프로세스가 실행되는 위치(`ci`, `container`, `serverless`, `interactive` 등 고정 목록 중 하나), 그리고 `pyproject.toml`에 설정된 경우 `project_id`. 감지는 알려진 환경 변수의 설정 여부만 확인하며 값은 읽지 않음. 개인 데이터 없음. |
|
||||
| 예 | Flow 라이프사이클 신호 | 포함 항목: flow의 시작, 완료 또는 실패 여부, 해당 메서드의 실패 여부, 사람의 입력이나 피드백을 위해 일시 중지되었는지 여부, 해당 시작이 재개된 실행이었는지 여부, 대화 턴의 실패 여부, flow 실행 시간, 그리고 해당 flow가 CrewAI가 내부적으로 실행하는 것인지 사용자가 작성한 것인지 여부. flow 이름은 flow 생성 및 실행에서와 마찬가지로 기록됩니다. flow 또는 해당 메서드가 실패하면 장애 진단을 위해 예외의 **클래스 이름**(예: `TimeoutError`)이 기록되며, 프롬프트·모델 출력·파일 경로·자격 증명이 포함될 수 있는 오류 메시지는 절대 기록되지 않습니다. 메서드 이름과 flow 상태는 절대 기록되지 않습니다. 개인 정보 없음. |
|
||||
| 예 | 트레이스 공유 신호 | 포함 항목: 트레이스 배치가 CrewAI AMP에 성공적으로 공유되었는지 여부와, 익명으로(계정 생성 전) 공유되었는지 또는 계정에 연결되어 공유되었는지 여부. 모든 span과 마찬가지로 위에서 설명한 실행 환경 속성(구성된 경우 `project_id`, 코딩 어시스턴트, 런타임)도 함께 기록됩니다. 이 행은 공유 텔레메트리만 설명하며 — 트레이스 내용이나 공유된 트레이스 링크로 부여되는 접근 권한은 설명하지 않습니다. 트레이스 내용, 입력, 출력은 이 신호에는 기록되지 않습니다. 트레이스를 공유하기 전에 비밀 정보, 개인 데이터, AMP 편집 및 보존 설정을 검토하세요. |
|
||||
| 예 | crewAI CLI를 통한 Crew 배포 시도 | 배포가 시도되고 있고 crew id가 포함되며, 로그를 가져오려고 하는 경우에만 해당. 다른 데이터 없음. |
|
||||
| 아니오 | 에이전트 확장 데이터 | 목표 설명, 배경 이야기 텍스트, i18n 프롬프트 파일 식별자가 포함됩니다. 사용자들은 텍스트 필드에 개인 정보가 포함되지 않도록 해야 합니다. |
|
||||
| 아니오 | 상세 작업 정보 | 작업 설명, 예상 출력 설명, 컨텍스트 참조가 포함됩니다. 사용자들은 이러한 필드에 개인 정보가 포함되지 않도록 해야 합니다. |
|
||||
| 아니오 | 환경 정보 | 플랫폼, 릴리즈, 시스템, 버전, CPU 개수가 포함됩니다. 예: 'Windows 10', 'x86_64'. 개인 정보 없음. |
|
||||
|
||||
@@ -9,7 +9,7 @@ mode: "wide"
|
||||
|
||||
## 설명
|
||||
|
||||
`ScrapeElementFromWebsiteTool`은 CSS 선택자를 사용하여 웹사이트에서 특정 요소를 추출하도록 설계되었습니다. 이 도구는 CrewAI 에이전트가 웹 페이지에서 타겟이 되는 콘텐츠를 스크래핑할 수 있게 하여, 웹페이지의 특정 부분만이 필요한 데이터 추출 작업에 유용합니다. 가져오기는 CrewAI의 SSRF 안전 HTTP 헬퍼를 거칩니다. 요청된 URL과 모든 리다이렉트 홉이 사설 및 예약 대역(클라우드 메타데이터 포함)에 대해 검사되며, TCP 연결은 그 검사를 통과한 IP에 고정됩니다.
|
||||
`ScrapeElementFromWebsiteTool`은 CSS 선택자를 사용하여 웹사이트에서 특정 요소를 추출하도록 설계되었습니다. 이 도구는 CrewAI 에이전트가 웹 페이지에서 타겟이 되는 콘텐츠를 스크래핑할 수 있게 하여, 웹페이지의 특정 부분만이 필요한 데이터 추출 작업에 유용합니다.
|
||||
|
||||
## 설치
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ mode: "wide"
|
||||
지정된 웹사이트의 내용을 추출하고 읽을 수 있도록 설계된 도구입니다. 이 도구는 HTTP 요청을 보내고 수신된 HTML 콘텐츠를 파싱함으로써 다양한 유형의 웹 페이지를 처리할 수 있습니다.
|
||||
이 도구는 웹 스크래핑 작업, 데이터 수집 또는 웹사이트에서 특정 정보를 추출하는 데 특히 유용할 수 있습니다.
|
||||
|
||||
가져오기는 CrewAI의 SSRF 안전 HTTP 헬퍼를 거칩니다. 요청된 URL과 모든 리다이렉트 홉이 사설 및 예약 대역(클라우드 메타데이터 포함)에 대해 검사되며, TCP 연결은 그 검사를 통과한 IP에 고정됩니다.
|
||||
|
||||
## 설치
|
||||
|
||||
crewai_tools 패키지를 설치하세요
|
||||
|
||||
@@ -4,192 +4,6 @@ description: "Atualizações de produto, melhorias e correções do CrewAI"
|
||||
icon: "clock"
|
||||
mode: "wide"
|
||||
---
|
||||
<Update label="19 ago 2026">
|
||||
## v1.15.17
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.17)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Recursos
|
||||
- Adicionar documentação de fluxos de conversa declarativos
|
||||
- Sintetizar métodos de conversa embutidos para declarações
|
||||
- Permitir que declarações conduzam o modo de conversa
|
||||
- Tornar a opção de conversa inconfundível
|
||||
- Carregar o slug AMP em ferramentas resolvidas a partir de uma referência de slug
|
||||
- Lidar com mensagens únicas excessivamente grandes durante a fragmentação
|
||||
|
||||
### Correções de Bugs
|
||||
- Corrigir o uso do nome do host da URL como server_name do MCP HTTP e SSE
|
||||
- Fechar o escopo do agente em cada tentativa falhada
|
||||
- Atribuir erros de ferramenta à ferramenta que falhou
|
||||
- Fixar verificações de SSRF em cada redirecionamento e IP de par
|
||||
- Resolver problemas com chamadas de ferramentas nativas quebradas na API de Respostas do OpenAI
|
||||
|
||||
### Documentação
|
||||
- Atualizar a documentação com um instantâneo e registro de alterações para v1.15.16
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@Copilot, @Vidit-Ostwal, @github-code-quality[bot], @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="13 ago 2026">
|
||||
## v1.15.16
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.16)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Recursos
|
||||
- Introduzir gerenciamento de contexto de execução com suporte a UUID
|
||||
- Registrar que tipo de exceção finalizou um fluxo
|
||||
- Registrar quando um lote de rastreamento é compartilhado com AMP
|
||||
- Contar implantações de qualquer origem e registrar onde elas começaram
|
||||
|
||||
### Correções de Bugs
|
||||
- Registrar a versão em execução em cada span emitido
|
||||
- Corrigir a validação do nome da tabela de busca do MySQL
|
||||
- Impedir que uma tentativa falhada marque a próxima como falhada
|
||||
|
||||
### Documentação
|
||||
- Adicionar guias de Frontend para CopilotKit e AG-UI
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@joaomdmoura, @lorenzejay, @ranst91, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="11 ago 2026">
|
||||
## v1.15.15
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.15)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Funcionalidades
|
||||
- Relatar resultado do fluxo, duração e sinais de interação humana.
|
||||
|
||||
### Correções de Bugs
|
||||
- Emitir FlowStartedEvent quando um gancho de limite aborta o fluxo.
|
||||
- Escopar a exportação de span para nosso próprio provedor de rastreamento.
|
||||
- Atualizar o torch para a versão 2.13.0 para resolver vulnerabilidade de segurança.
|
||||
- Atualizar o gitpython para a versão 3.1.58 em crewai-tools[github].
|
||||
|
||||
### Refatoração
|
||||
- Atualizar a funcionalidade de injeção de data em agentes.
|
||||
- Padronizar as flags da CLI para kebab-case.
|
||||
|
||||
### Documentação
|
||||
- Snapshot e changelog para v1.15.14.
|
||||
|
||||
## Contributors
|
||||
|
||||
@Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="08 ago 2026">
|
||||
## v1.15.14
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.14)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Recursos
|
||||
- Separar o contexto de execução do agente de codificação e adicionar ID do projeto
|
||||
|
||||
### Documentação
|
||||
- Atualizar snapshot e changelog para v1.15.13
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@joaomdmoura
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="07 ago 2026">
|
||||
## 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
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="05 ago 2026">
|
||||
## v1.15.12
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.12)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Funcionalidades
|
||||
- Aumentar o canário do Flow na versão
|
||||
- Adicionar URLReadTool para leitura de URLs arbitrárias
|
||||
- Adicionar metadados do aplicativo às ferramentas de ação da plataforma
|
||||
- Unificar a estrutura sob `crewai create <resource>`
|
||||
|
||||
### Correções de Bugs
|
||||
- Esclarecer erros de colisão de nomes de rota/manipulador de conversa
|
||||
|
||||
### Documentação
|
||||
- Atualizar o AGENTS.md da estrutura para CLI de criação unificada
|
||||
|
||||
### Mudanças Quebradoras
|
||||
- Nenhuma
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@Vidit-Ostwal, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="04 ago 2026">
|
||||
## v1.15.11
|
||||
|
||||
[Ver release no GitHub](https://github.com/crewAIInc/crewAI/releases/tag/1.15.11)
|
||||
|
||||
## O que Mudou
|
||||
|
||||
### Recursos
|
||||
- Rastrear dispatches de hooks de interceptação na telemetria
|
||||
- Adicionar project_id para vincular o uso do OSS a uma conta empresarial
|
||||
- Exibir AMP em AGENTS.md e detectar agentes de codificação na telemetria
|
||||
- Adicionar ferramenta de busca IBM Db2
|
||||
|
||||
### Correções de Bugs
|
||||
- Limpar alertas de sanitização de substring de URL incompleta do CodeQL
|
||||
- Atualizar aiohttp e cryptography para eliminar seis avisos GHSA
|
||||
- Reportar o erro CEL real para falhas dentro de literais de mapa
|
||||
- Pular corretamente a CI de código para PRs apenas de documentação
|
||||
|
||||
### Documentação
|
||||
- Snapshot e changelog para v1.15.10
|
||||
|
||||
## Contribuidores
|
||||
|
||||
@PawanThakurIBM, @Vidit-Ostwal, @gabemilani, @joaomdmoura, @lorenzejay, @lucasgomide, @theCyberTech
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="31 jul 2026">
|
||||
## v1.15.10
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ O Construtor Visual de Agentes permite:
|
||||
| **Respect Context Window** _(opcional)_ | `respect_context_window` | `bool` | Mantém as mensagens dentro do tamanho da janela de contexto, resumindo quando necessário. Padrão: True. |
|
||||
| **Code Execution Mode** _(opcional)_ | `code_execution_mode` | `Literal["safe", "unsafe"]` | Modo de execução de código: 'safe' (usando Docker) ou 'unsafe' (direto). Padrão: 'safe'. |
|
||||
| **Multimodal** _(opcional)_ | `multimodal` | `bool` | Se o agente suporta capacidades multimodais. Padrão: False. |
|
||||
| **Inject Date** _(opcional)_ | `inject_date` | `bool` | Se deve injetar automaticamente a data atual no prompt do agente. Padrão: False. |
|
||||
| **Inject Date** _(opcional)_ | `inject_date` | `bool` | Se deve injetar automaticamente a data atual nas tarefas. Padrão: False. |
|
||||
| **Date Format** _(opcional)_ | `date_format` | `str` | Formato de data utilizado quando `inject_date` está ativo. Padrão: "%Y-%m-%d" (formato ISO). |
|
||||
| **Reasoning** _(opcional)_ | `reasoning` | `bool` | Se o agente deve refletir e criar um plano antes de executar uma tarefa. Padrão: False. |
|
||||
| **Max Reasoning Attempts** _(opcional)_ | `max_reasoning_attempts` | `Optional[int]` | Número máximo de tentativas de raciocínio antes de executar a tarefa. Se None, tentará até estar pronto. |
|
||||
@@ -274,7 +274,7 @@ strategic_agent = Agent(
|
||||
role="Analista de Mercado",
|
||||
goal="Acompanhar movimentos do mercado com referências de datas precisas e planejamento estratégico",
|
||||
backstory="Especialista em análise financeira sensível ao tempo e relatórios estratégicos",
|
||||
inject_date=True, # Injeta automaticamente a data atual no prompt
|
||||
inject_date=True, # Injeta automaticamente a data atual nas tarefas
|
||||
date_format="%d de %B de %Y", # Exemplo: "21 de maio de 2025"
|
||||
reasoning=True, # Ativa planejamento estratégico
|
||||
max_reasoning_attempts=2, # Limite de iterações de planejamento
|
||||
@@ -341,7 +341,7 @@ multimodal_agent = Agent(
|
||||
|
||||
- `multimodal`: Habilita capacidades multimodais para processar texto e conteúdo visual
|
||||
- `reasoning`: Permite que o agente reflita e crie planos antes de executar tarefas
|
||||
- `inject_date`: Injeta a data atual automaticamente no prompt do agente
|
||||
- `inject_date`: Injeta a data atual automaticamente nas descrições das tarefas
|
||||
|
||||
#### Templates
|
||||
|
||||
|
||||
@@ -55,16 +55,6 @@ crewai create flow my_new_flow
|
||||
|
||||
Por padrão, `crewai create crew` cria um projeto JSON-first com `crew.jsonc` e `agents/*.jsonc`. Use `crewai create crew my_new_crew --classic` somente quando quiser o scaffold antigo em Python/YAML com `crew.py`, `config/agents.yaml` e `config/tasks.yaml`.
|
||||
|
||||
#### Aliases de flags obsoletas
|
||||
|
||||
As flags antigas em snake_case ainda funcionam, mas ficam ocultas no `--help`. Prefira as formas em kebab-case documentadas em cada seção de comando abaixo.
|
||||
|
||||
| Obsoleto | Use em vez disso |
|
||||
| :--- | :--- |
|
||||
| `--skip_provider` (em `crewai create crew`) | `--skip-provider` |
|
||||
| `--n_iterations` (em `crewai train`, `crewai test`) | `--n-iterations` |
|
||||
| `--task_id` (em `crewai replay`) | `--task-id` |
|
||||
|
||||
### 2. Version
|
||||
|
||||
Mostre a versão instalada do CrewAI.
|
||||
@@ -90,7 +80,7 @@ Treine o crew por um número específico de iterações.
|
||||
crewai train [OPTIONS]
|
||||
```
|
||||
|
||||
- `-n, --n-iterations INTEGER`: Número de iterações para treinar o crew (padrão: 5)
|
||||
- `-n, --n_iterations INTEGER`: Número de iterações para treinar o crew (padrão: 5)
|
||||
- `-f, --filename TEXT`: Caminho para um arquivo customizado para treinamento (padrão: "trained_agents_data.pkl")
|
||||
|
||||
Exemplo:
|
||||
@@ -123,7 +113,7 @@ Reexecute a execução do crew a partir de uma tarefa específica.
|
||||
crewai replay [OPTIONS]
|
||||
```
|
||||
|
||||
- `-t, --task-id TEXT`: Reexecuta o crew a partir deste task ID, incluindo todas as tarefas subsequentes
|
||||
- `-t, --task_id TEXT`: Reexecuta o crew a partir deste task ID, incluindo todas as tarefas subsequentes
|
||||
|
||||
Exemplo:
|
||||
|
||||
@@ -170,7 +160,7 @@ Teste o crew e avalie os resultados.
|
||||
crewai test [OPTIONS]
|
||||
```
|
||||
|
||||
- `-n, --n-iterations INTEGER`: Número de iterações para testar o crew (padrão: 3)
|
||||
- `-n, --n_iterations INTEGER`: Número de iterações para testar o crew (padrão: 3)
|
||||
- `-m, --model TEXT`: Modelo LLM para executar os testes no Crew (padrão: "gpt-4o-mini")
|
||||
|
||||
Exemplo:
|
||||
|
||||
@@ -322,8 +322,6 @@ Caches podem ser utilizados para armazenar resultados de execuções de ferramen
|
||||
|
||||
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])
|
||||
|
||||
@@ -260,24 +260,6 @@ print(flow.usage_metrics)
|
||||
rollup **completo** de tokens da execução do Flow.
|
||||
</Note>
|
||||
|
||||
### 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
|
||||
|
||||
@@ -270,22 +270,6 @@ Nesta seção, você encontrará exemplos detalhados que ajudam a selecionar, co
|
||||
)
|
||||
```
|
||||
|
||||
**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.
|
||||
</Accordion>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ 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
|
||||
crewai test --n_iterations 5 --model gpt-4o
|
||||
```
|
||||
|
||||
ou usando as formas abreviadas:
|
||||
@@ -29,11 +29,6 @@ ou usando as formas abreviadas:
|
||||
crewai test -n 5 -m gpt-4o
|
||||
```
|
||||
|
||||
<Note>
|
||||
A flag antiga `--n_iterations` ainda funciona, mas está obsoleta e oculta no
|
||||
`--help`. Use `--n-iterations` (ou `-n`) em vez disso.
|
||||
</Note>
|
||||
|
||||
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:
|
||||
|
||||
@@ -428,70 +428,6 @@ Dentro de um handler `@listen(label)`, escolha:
|
||||
|
||||
`ConversationConfig.visible_agent_outputs` pode promover globalmente os resultados privados de agentes específicos para públicos (`"all"` ou lista de nomes).
|
||||
|
||||
## Declarando um flow conversacional em JSON/YAML
|
||||
|
||||
Um [flow declarativo](/edge/en/concepts/cli) também pode ser conversacional. Adicione um bloco `conversational` no nível raiz e declare suas próprias rotas como métodos que escutam (`listen`) um rótulo de rota:
|
||||
|
||||
```yaml
|
||||
schema: crewai.flow/v1
|
||||
name: SupportFlow
|
||||
|
||||
conversational:
|
||||
system_prompt: You are a terse support assistant.
|
||||
llm: gpt-4o-mini
|
||||
router:
|
||||
llm: gpt-4o-mini
|
||||
|
||||
methods:
|
||||
handle_order:
|
||||
description: Order status, shipping and delivery questions.
|
||||
listen: order
|
||||
do:
|
||||
call: agent
|
||||
with:
|
||||
role: Support specialist
|
||||
goal: Answer order questions accurately
|
||||
backstory: Knows the fulfilment pipeline.
|
||||
input: "${state.current_user_message}"
|
||||
```
|
||||
|
||||
Declarar o bloco já é o opt-in — `enabled` tem valor padrão `true`. Use `enabled: false` para manter a configuração e desligar o chat.
|
||||
|
||||
Três coisas são fornecidas para você:
|
||||
|
||||
| Fornecido | Detalhe |
|
||||
|----------|--------|
|
||||
| O grafo interno | `route_conversation`, `converse_turn`, `end_conversation` e `answer_from_history_turn` são adicionados automaticamente. Declare um método com um desses nomes para sobrescrevê-lo. |
|
||||
| Estado da conversa | `ConversationState` é usado quando a declaração não tem bloco `state`. Para adicionar campos, aponte `state` para um modelo Pydantic que estenda `ConversationState`. |
|
||||
| O catálogo de rotas | Construído a partir dos métodos que declaram um rótulo `listen`. O `description` de cada método é o que o modelo de roteamento lê ao escolher entre rotas. |
|
||||
|
||||
Execute a partir do Python com as mesmas APIs de turno de um Flow conversacional baseado em classe:
|
||||
|
||||
```python
|
||||
from crewai.flow import Flow
|
||||
|
||||
flow = Flow.from_declaration(path="flow.yaml")
|
||||
|
||||
try:
|
||||
flow.handle_turn("Where is my order?", session_id="session-1")
|
||||
finally:
|
||||
flow.finalize_session_traces()
|
||||
```
|
||||
|
||||
### Nomeando rotas
|
||||
|
||||
Rótulos de rota e nomes de métodos compartilham um único namespace de gatilhos, então um handler não pode ter o nome da rota que escuta — `create_video` escutando `create_video` é rejeitado na construção do flow. Use o prefixo `handle_*`.
|
||||
|
||||
### O que uma declaração não consegue expressar
|
||||
|
||||
| Não expressável | Use no lugar |
|
||||
|-----------------|-------------|
|
||||
| Uma instância `LLM` viva ou um `BaseLLM` customizado | Uma string de id de modelo, como `gpt-4o-mini` |
|
||||
| `router.response_format` como classe de modelo | Omita; o framework sintetiza uma. Um ref ou schema é ignorado com um aviso |
|
||||
| Overrides de `route_turn()` / `can_answer_from_history()` | Escreva o Flow em Python, ou aponte o `do` de um método para um ref `call: code` |
|
||||
|
||||
O `crewai run` ainda não tem loop de chat: ele informa que o flow é conversacional e sai, em vez de rodar um único turno. Conduza um flow conversacional declarativo pelo Python com `handle_turn()`, `stream_turn()` ou `chat()`.
|
||||
|
||||
## Tracing entre turnos
|
||||
|
||||
Com `defer_trace_finalization=True` (padrão em `ConversationalConfig`):
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
---
|
||||
title: Hooks de Fronteira de Execução
|
||||
description: Intercepte o início, as entradas, a saída e o fim de execuções de crews e flows com o decorator @on
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
Os hooks de fronteira de execução interceptam as bordas mais externas de uma
|
||||
execução — antes de qualquer trabalho começar, quando as entradas são
|
||||
resolvidas, quando o resultado final está pronto e quando a execução termina.
|
||||
Eles disparam tanto para crews quanto para flows e são o lugar certo para
|
||||
verificações de política no nível da execução, reescrita de entradas e
|
||||
sanitização de saídas.
|
||||
|
||||
## Visão Geral
|
||||
|
||||
Quatro pontos de interceptação cobrem as fronteiras:
|
||||
|
||||
| Ponto | Quando | `ctx.payload` |
|
||||
|-------|--------|---------------|
|
||||
| `EXECUTION_START` | Uma crew ou flow está prestes a começar | `dict` de entradas |
|
||||
| `INPUT` | Entradas resolvidas para a execução | `dict` de entradas |
|
||||
| `OUTPUT` | O resultado final está pronto | o objeto de saída |
|
||||
| `EXECUTION_END` | A execução terminou (sucesso ou falha) | o objeto de saída, ou `None` em caso de falha |
|
||||
|
||||
Para uma crew, o payload de saída é um `CrewOutput`. Para um flow, é o
|
||||
resultado final do método do flow.
|
||||
|
||||
## Assinatura do Hook
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
Hooks de fronteira seguem o contrato padrão: prosseguir (`return None`), mutar
|
||||
in place, substituir retornando um valor, ou abortar lançando `HookAborted`.
|
||||
Um abort em qualquer fronteira propaga para fora do `kickoff()` com seu
|
||||
motivo.
|
||||
|
||||
## Esquema de Contexto
|
||||
|
||||
Cada ponto recebe um contexto tipado. Todos os contextos compartilham os
|
||||
campos base:
|
||||
|
||||
```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)
|
||||
```
|
||||
|
||||
Os contextos de cada ponto adicionam um alias nomeado para o 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"
|
||||
```
|
||||
|
||||
<Note>
|
||||
`ctx.inputs` é um alias para o dict de entradas **original**, então edições in
|
||||
place por qualquer um dos nomes são equivalentes. Se um hook anterior
|
||||
*substituiu* o payload retornando um novo dict, apenas `ctx.payload` é
|
||||
reassociado — sempre leia e escreva `ctx.payload` quando hooks puderem
|
||||
encadear.
|
||||
</Note>
|
||||
|
||||
## Execuções de Crew vs. Execuções de Flow
|
||||
|
||||
Hooks de fronteira disparam em ambos os runtimes, e a execução de uma crew
|
||||
roda internamente sobre um runtime de flow. Durante um `crew.kickoff()`, um
|
||||
hook de fronteira global portanto dispara para a fronteira da crew
|
||||
(`ctx.crew` definido, `ctx.flow` `None`) **e** para o flow interno
|
||||
(`ctx.flow` definido, `ctx.crew` `None`). Discrimine pelo 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()
|
||||
```
|
||||
|
||||
## Casos de Uso Comuns
|
||||
|
||||
### Verificação de Política no Início
|
||||
|
||||
```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")
|
||||
```
|
||||
|
||||
### Reescrita de Entradas
|
||||
|
||||
```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()
|
||||
```
|
||||
|
||||
Entradas reescritas fluem para a interpolação de tasks, então a execução se
|
||||
comporta como se tivesse sido iniciada com o dict modificado.
|
||||
|
||||
Prefira `INPUT` para reescrita e trate `EXECUTION_START` como o gate de
|
||||
allow/deny. Reescritas em `EXECUTION_START` continuam sendo honradas — em
|
||||
crews elas também alimentam os callbacks de `before_kickoff`; em flows elas
|
||||
se aplicam exatamente como uma reescrita de `INPUT`.
|
||||
|
||||
### Sanitização de Saída
|
||||
|
||||
```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` roda antes de `EXECUTION_END`, e ambos veem o payload (possivelmente
|
||||
substituído) de hooks anteriores; o valor final reescrito é o que `kickoff()`
|
||||
retorna.
|
||||
|
||||
### Observando Falhas
|
||||
|
||||
`EXECUTION_END` dispara exatamente uma vez por execução, tanto em sucesso
|
||||
quanto em falha. Quando a execução lança uma exceção — um erro de task, uma
|
||||
exceção de método de flow ou um `HookAborted` de um ponto anterior — o hook
|
||||
recebe `status="failed"` com a exceção em `ctx.error`, e a exceção original
|
||||
ainda propaga para fora do `kickoff()` sem alterações:
|
||||
|
||||
```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")
|
||||
```
|
||||
|
||||
Duas ressalvas: `EXECUTION_END` não dispara quando `EXECUTION_START` nunca foi
|
||||
despachado (um abort no início significa que a fronteira nunca abriu, então
|
||||
não há fim para parear), e lançar `HookAborted` de um dispatch de
|
||||
`EXECUTION_END` no caminho de falha é ignorado — não resta nada para abortar,
|
||||
e o erro original prevalece.
|
||||
|
||||
## Ordenação
|
||||
|
||||
Para uma execução de crew, a ordem de fronteira é:
|
||||
|
||||
```
|
||||
EXECUTION_START → before_kickoff callbacks → INPUT → tasks execute → OUTPUT → EXECUTION_END
|
||||
```
|
||||
|
||||
Para uma execução de flow, os hooks de fronteira resolvem as entradas antes
|
||||
de os eventos de ciclo de vida começarem:
|
||||
|
||||
```
|
||||
EXECUTION_START → INPUT → FlowStartedEvent → flow methods execute → OUTPUT → EXECUTION_END → FlowFinishedEvent
|
||||
```
|
||||
|
||||
`FlowStartedEvent` carrega as entradas resolvidas pelos hooks, e reescrever
|
||||
`inputs["id"]` em um hook de fronteira redireciona a restauração de estado.
|
||||
Um abort em `EXECUTION_START` ainda aparece como `FlowStartedEvent` seguido
|
||||
de `FlowFailedEvent`, emitidos no momento do abort com o payload como
|
||||
resolvido pelos hooks que rodaram antes dele.
|
||||
|
||||
Hooks no mesmo ponto rodam em ordem de registro, hooks globais primeiro,
|
||||
depois hooks com escopo de crew. A telemetria (`HookDispatchedEvent`) é
|
||||
emitida por dispatch.
|
||||
|
||||
## Gerenciando Hooks em Testes
|
||||
|
||||
```python
|
||||
from crewai.hooks import clear_all_hooks
|
||||
|
||||
clear_all_hooks() # Clears every point, including boundaries
|
||||
```
|
||||
|
||||
## Documentação Relacionada
|
||||
|
||||
- [Visão Geral dos Hooks de Execução →](/edge/pt-BR/learn/execution-hooks)
|
||||
- [Hooks de Chamada LLM →](/edge/pt-BR/learn/llm-hooks)
|
||||
- [Hooks de Chamada de Ferramenta →](/edge/pt-BR/learn/tool-hooks)
|
||||
@@ -34,20 +34,6 @@ os.environ['CREWAI_DISABLE_TELEMETRY'] = 'true'
|
||||
os.environ['OTEL_SDK_DISABLED'] = 'true'
|
||||
```
|
||||
|
||||
### Isolamento da sua própria configuração do OpenTelemetry
|
||||
|
||||
A telemetria do CrewAI roda em seu próprio `TracerProvider` privado e nunca se
|
||||
registra como o provider global. Isso mantém as duas direções separadas:
|
||||
|
||||
- Spans de outras bibliotecas instrumentadas no seu processo — frameworks web,
|
||||
clientes de banco de dados, clientes HTTP — nunca são enviados ao CrewAI.
|
||||
- Os spans de telemetria do CrewAI nunca são enviados ao seu backend de
|
||||
observabilidade, portanto não aparecerão no Langfuse, Braintrust, Phoenix ou
|
||||
em qualquer outro coletor que você configurar.
|
||||
|
||||
As integrações de observabilidade não são afetadas: elas instrumentam o CrewAI
|
||||
por meio do próprio tracer provider, que é independente do descrito aqui.
|
||||
|
||||
### Explicação dos Dados:
|
||||
| Padrão | Dados | Razão e Especificidades |
|
||||
|--------|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
@@ -59,10 +45,7 @@ por meio do próprio tracer provider, que é independente do descrito aqui.
|
||||
| Sim | Dados de Execução de Testes | Inclui: chave e ID aleatórias do crew, número de iterações, nome do modelo usado, score de qualidade (float), tempo de execução (em segundos). Tudo não pessoal. |
|
||||
| Sim | Dados do Ciclo de Vida da Tarefa | Inclui: horários de criação, início/fim de execução, identificadores de crew e tarefa. Armazenado como spans com timestamps. Sem dados pessoais. |
|
||||
| Sim | Atributos do LLM | Inclui: nome, model_name, model, top_k, temperatura e nome da classe do LLM. Todos técnicos, sem dados pessoais. |
|
||||
| Sim | Tentativa de Deploy do Crew pelo CLI do crewAI | Inclui: O fato de um deploy estar sendo realizado e o crew id, se está tentando buscar logs, e se o deploy foi iniciado por um comando do CLI ou pela TUI de execução. Não inclui conteúdo do projeto ou do crew nem dados pessoais. |
|
||||
| Sim | Ambiente de Execução | Inclui: qual assistente de código com IA está executando o processo, se houver (um de uma lista fixa como `claude_code`, `codex`, `cursor` ou `unknown`), onde o processo é executado (um de uma lista fixa como `ci`, `container`, `serverless`, `interactive`) e o `project_id` do seu `pyproject.toml` quando houver um configurado. A detecção lê apenas se variáveis de ambiente conhecidas estão definidas, nunca seus valores. Sem dados pessoais. |
|
||||
| Sim | Sinais de Ciclo de Vida do Flow | Inclui: que um flow iniciou, se foi concluído ou falhou, se um de seus métodos falhou, se pausou para entrada ou feedback humano, se o início foi uma execução retomada, se um turno de conversa falhou, quanto tempo o flow executou, e se o flow é um que a CrewAI executa internamente ou um que você escreveu. O nome do flow é registrado, como já é para criação e execução de flow. Quando um flow ou um de seus métodos falha, o **nome da classe** da exceção é registrado (por exemplo `TimeoutError`) para permitir o diagnóstico de falhas — nunca a mensagem de erro, que pode conter prompts, saída do modelo, caminhos de arquivo ou credenciais. Nomes de métodos e estado do flow nunca são registrados. Nenhum dado pessoal. |
|
||||
| Sim | Sinal de Compartilhamento de Trace | Inclui: que um lote de traces foi compartilhado com sucesso com o CrewAI AMP, e se foi compartilhado anonimamente (antes de você ter uma conta) ou vinculado à sua conta. Como todo span, também carrega os atributos de Ambiente de Execução descritos acima (`project_id` quando configurado, o assistente de programação e o runtime). Esta linha descreve apenas a telemetria do compartilhamento — não o conteúdo dos traces nem o acesso concedido por links de traces compartilhados. O conteúdo dos traces, entradas e saídas nunca são registrados neste sinal. Antes de compartilhar traces, revise segredos, dados pessoais e as configurações de redação e retenção do AMP. |
|
||||
| Sim | Tentativa de Deploy do Crew pelo CLI do crewAI | Inclui: O fato de um deploy estar sendo realizado e o crew id, e se está tentando buscar logs, sem mais dados. |
|
||||
| Não | Dados Expandidos do Agente | Inclui: descrição do objetivo, texto da história, identificador de arquivo i18n prompt. Usuários devem garantir que não haja info pessoal nesses campos de texto. |
|
||||
| Não | Informações Detalhadas da Tarefa | Inclui: descrição da tarefa, descrição do resultado esperado, referências de contexto. Usuários devem garantir que não haja info pessoal nessas áreas. |
|
||||
| Não | Informações de Ambiente | Inclui: plataforma, release, sistema, versão e quantidade de CPUs. Exemplo: 'Windows 10', 'x86_64'. Sem dados pessoais. |
|
||||
|
||||
@@ -9,7 +9,7 @@ mode: "wide"
|
||||
|
||||
## Descrição
|
||||
|
||||
A `ScrapeElementFromWebsiteTool` foi projetada para extrair elementos específicos de websites utilizando seletores CSS. Esta ferramenta permite que agentes CrewAI capturem conteúdos direcionados de páginas web, tornando-se útil para tarefas de extração de dados em que apenas partes específicas de uma página são necessárias. As buscas passam pelo helper HTTP seguro contra SSRF do CrewAI: a URL solicitada e cada hop de redirecionamento são verificados contra faixas privadas e reservadas (incluindo metadados de nuvem), e a conexão TCP é fixada no IP que passou nessa verificação.
|
||||
A `ScrapeElementFromWebsiteTool` foi projetada para extrair elementos específicos de websites utilizando seletores CSS. Esta ferramenta permite que agentes CrewAI capturem conteúdos direcionados de páginas web, tornando-se útil para tarefas de extração de dados em que apenas partes específicas de uma página são necessárias.
|
||||
|
||||
## Instalação
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ mode: "wide"
|
||||
Uma ferramenta desenvolvida para extrair e ler o conteúdo de um site especificado. Ela é capaz de lidar com diversos tipos de páginas web fazendo requisições HTTP e analisando o conteúdo HTML recebido.
|
||||
Esta ferramenta pode ser especialmente útil para tarefas de raspagem de dados, coleta de dados ou extração de informações específicas de sites.
|
||||
|
||||
As buscas passam pelo helper HTTP seguro contra SSRF do CrewAI: a URL solicitada e cada hop de redirecionamento são verificados contra faixas privadas e reservadas (incluindo metadados de nuvem), e a conexão TCP é fixada no IP que passou nessa verificação.
|
||||
|
||||
## Instalação
|
||||
|
||||
Instale o pacote crewai_tools
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
title: "GET /inputs"
|
||||
description: "الحصول على المدخلات المطلوبة لطاقمك"
|
||||
openapi: "/v1.15.11/enterprise-api.en.yaml GET /inputs"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
---
|
||||
title: "مقدمة"
|
||||
description: "المرجع الكامل لواجهة برمجة تطبيقات CrewAI AMP REST"
|
||||
icon: "code"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
# واجهة برمجة تطبيقات CrewAI AMP
|
||||
|
||||
مرحبًا بك في مرجع واجهة برمجة تطبيقات CrewAI AMP. تتيح لك هذه الواجهة التفاعل برمجيًا مع الأطقم المنشورة، مما يمكّنك من دمجها مع تطبيقاتك وسير عملك وخدماتك.
|
||||
|
||||
## البدء السريع
|
||||
|
||||
<Steps>
|
||||
<Step title="الحصول على بيانات اعتماد API">
|
||||
انتقل إلى صفحة تفاصيل طاقمك في لوحة تحكم CrewAI AMP وانسخ رمز Bearer من علامة تبويب الحالة.
|
||||
</Step>
|
||||
|
||||
<Step title="اكتشاف المدخلات المطلوبة">
|
||||
استخدم نقطة النهاية `GET /inputs` لمعرفة المعاملات التي يتوقعها طاقمك.
|
||||
</Step>
|
||||
|
||||
<Step title="بدء تنفيذ الطاقم">
|
||||
استدعِ `POST /kickoff` مع مدخلاتك لبدء تنفيذ الطاقم واستلام
|
||||
`kickoff_id`.
|
||||
</Step>
|
||||
|
||||
<Step title="مراقبة التقدم">
|
||||
استخدم `GET /status/{kickoff_id}` للتحقق من حالة التنفيذ واسترجاع النتائج.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## المصادقة
|
||||
|
||||
تتطلب جميع طلبات API المصادقة باستخدام رمز Bearer. أدرج رمزك في ترويسة `Authorization`:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_CREW_TOKEN" \
|
||||
https://your-crew-url.crewai.com/inputs
|
||||
```
|
||||
|
||||
### أنواع الرموز
|
||||
|
||||
| نوع الرمز | النطاق | حالة الاستخدام |
|
||||
| :-------------------- | :------------------------ | :----------------------------------------------------------- |
|
||||
| **Bearer Token** | وصول على مستوى المؤسسة | عمليات الطاقم الكاملة، مثالي للتكامل بين الخوادم |
|
||||
| **User Bearer Token** | وصول محدد بالمستخدم | صلاحيات محدودة، مناسب للعمليات الخاصة بالمستخدم |
|
||||
|
||||
<Tip>
|
||||
يمكنك العثور على كلا نوعي الرموز في علامة تبويب الحالة من صفحة تفاصيل طاقمك في
|
||||
لوحة تحكم CrewAI AMP.
|
||||
</Tip>
|
||||
|
||||
## عنوان 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` | خطأ في الخادم - تواصل مع الدعم |
|
||||
|
||||
## الاختبار التفاعلي
|
||||
|
||||
<Info>
|
||||
**لماذا لا يوجد زر "إرسال"؟** نظرًا لأن كل مستخدم CrewAI AMP لديه عنوان URL
|
||||
فريد للطاقم، نستخدم **وضع المرجع** بدلاً من بيئة تفاعلية لتجنب
|
||||
الالتباس. يوضح لك هذا بالضبط كيف يجب أن تبدو الطلبات بدون
|
||||
أزرار إرسال غير فعالة.
|
||||
</Info>
|
||||
|
||||
تعرض لك كل صفحة نقطة نهاية:
|
||||
|
||||
- **تنسيق الطلب الدقيق** مع جميع المعاملات
|
||||
- **أمثلة الاستجابة** لحالات النجاح والخطأ
|
||||
- **عينات الكود** بلغات متعددة (cURL، Python، JavaScript، إلخ)
|
||||
- **أمثلة المصادقة** بتنسيق رمز Bearer الصحيح
|
||||
|
||||
### **لاختبار واجهتك الفعلية:**
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="نسخ أمثلة cURL" icon="terminal">
|
||||
انسخ أمثلة cURL واستبدل العنوان URL + الرمز بقيمك الحقيقية
|
||||
</Card>
|
||||
<Card title="استخدام Postman/Insomnia" icon="play">
|
||||
استورد الأمثلة في أداة اختبار API المفضلة لديك
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
**مثال على سير العمل:**
|
||||
|
||||
1. **انسخ مثال cURL هذا** من أي صفحة نقطة نهاية
|
||||
2. **استبدل `your-actual-crew-name.crewai.com`** بعنوان URL الحقيقي لطاقمك
|
||||
3. **استبدل رمز Bearer** برمزك الحقيقي من لوحة التحكم
|
||||
4. **نفّذ الطلب** في طرفيتك أو عميل API
|
||||
|
||||
## هل تحتاج مساعدة؟
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="دعم المؤسسات"
|
||||
icon="headset"
|
||||
href="mailto:support@crewai.com"
|
||||
>
|
||||
احصل على مساعدة في تكامل API واستكشاف الأخطاء وإصلاحها
|
||||
</Card>
|
||||
<Card
|
||||
title="لوحة تحكم المؤسسات"
|
||||
icon="chart-line"
|
||||
href="https://app.crewai.com"
|
||||
>
|
||||
إدارة أطقمك وعرض سجلات التنفيذ
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
title: "POST /kickoff"
|
||||
description: "بدء تنفيذ الطاقم"
|
||||
openapi: "/v1.15.11/enterprise-api.en.yaml POST /kickoff"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
title: "POST /resume"
|
||||
description: "استئناف تنفيذ الطاقم مع التغذية الراجعة البشرية"
|
||||
openapi: "/v1.15.11/enterprise-api.en.yaml POST /resume"
|
||||
mode: "wide"
|
||||
---
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
title: "GET /status/{kickoff_id}"
|
||||
description: "الحصول على حالة التنفيذ"
|
||||
openapi: "/v1.15.11/enterprise-api.en.yaml GET /status/{kickoff_id}"
|
||||
mode: "wide"
|
||||
---
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,147 +0,0 @@
|
||||
---
|
||||
title: "قدرات الوكيل"
|
||||
description: "فهم الطرق الخمس لتوسيع وكلاء CrewAI: الأدوات، MCP، التطبيقات، المهارات، والمعرفة."
|
||||
icon: puzzle-piece
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
يمكن توسيع وكلاء CrewAI بـ **خمسة أنواع مميزة من القدرات**، كل منها يخدم غرضًا مختلفًا. فهم متى تستخدم كل نوع — وكيف يعملون معًا — هو المفتاح لبناء وكلاء فعّالين.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="الأدوات" icon="wrench" href="/ar/concepts/tools" color="#3B82F6">
|
||||
**دوال قابلة للاستدعاء** — تمنح الوكلاء القدرة على اتخاذ إجراءات. البحث على الويب، عمليات الملفات، استدعاءات API، تنفيذ الكود.
|
||||
</Card>
|
||||
<Card title="خوادم MCP" icon="plug" href="/ar/mcp/overview" color="#8B5CF6">
|
||||
**خوادم أدوات عن بُعد** — تربط الوكلاء بخوادم أدوات خارجية عبر Model Context Protocol. نفس تأثير الأدوات، لكن مستضافة خارجيًا.
|
||||
</Card>
|
||||
<Card title="التطبيقات" icon="grid-2" color="#EC4899">
|
||||
**تكاملات المنصة** — تربط الوكلاء بتطبيقات SaaS (Gmail، Slack، Jira، Salesforce) عبر منصة CrewAI. تعمل محليًا مع رمز تكامل المنصة.
|
||||
</Card>
|
||||
<Card title="المهارات" icon="bolt" href="/ar/concepts/skills" color="#F59E0B">
|
||||
**خبرة المجال** — تحقن التعليمات والإرشادات والمواد المرجعية في إرشادات الوكلاء. المهارات تخبر الوكلاء *كيف يفكرون*.
|
||||
</Card>
|
||||
<Card title="المعرفة" icon="book" href="/ar/concepts/knowledge" color="#10B981">
|
||||
**حقائق مُسترجعة** — توفر للوكلاء بيانات من المستندات والملفات وعناوين URL عبر البحث الدلالي (RAG). المعرفة تعطي الوكلاء *ما يحتاجون معرفته*.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
---
|
||||
|
||||
## التمييز الأساسي
|
||||
|
||||
أهم شيء يجب فهمه: **هذه القدرات تنقسم إلى فئتين**.
|
||||
|
||||
### قدرات الإجراء (الأدوات، 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=[]` |
|
||||
|
||||
---
|
||||
|
||||
## تعمّق أكثر
|
||||
|
||||
هل أنت مستعد لمعرفة المزيد عن كل نوع من أنواع القدرات؟
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="الأدوات" icon="wrench" href="/ar/concepts/tools">
|
||||
إنشاء أدوات مخصصة، استخدام كتالوج OSS مع أكثر من 75 خيارًا، تكوين التخزين المؤقت والتنفيذ غير المتزامن.
|
||||
</Card>
|
||||
<Card title="تكامل MCP" icon="plug" href="/ar/mcp/overview">
|
||||
الاتصال بخوادم MCP عبر stdio أو SSE أو HTTP. تصفية الأدوات، تكوين المصادقة.
|
||||
</Card>
|
||||
<Card title="المهارات" icon="bolt" href="/ar/concepts/skills">
|
||||
بناء حزم المهارات مع SKILL.md، حقن خبرة المجال، استخدام الكشف التدريجي.
|
||||
</Card>
|
||||
<Card title="المعرفة" icon="book" href="/ar/concepts/knowledge">
|
||||
إضافة المعرفة من ملفات PDF وCSV وعناوين URL والمزيد. تكوين المُضمّنات والاسترجاع.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,383 +0,0 @@
|
||||
---
|
||||
title: الوكلاء
|
||||
description: دليل تفصيلي حول إنشاء وإدارة الوكلاء ضمن إطار عمل CrewAI.
|
||||
icon: robot
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## نظرة عامة على الوكيل
|
||||
|
||||
في إطار عمل CrewAI، الـ `Agent` هو وحدة مستقلة يمكنها:
|
||||
|
||||
- أداء مهام محددة
|
||||
- اتخاذ قرارات بناءً على دوره وهدفه
|
||||
- استخدام الأدوات لتحقيق الأهداف
|
||||
- التواصل والتعاون مع وكلاء آخرين
|
||||
- الاحتفاظ بذاكرة التفاعلات
|
||||
- تفويض المهام عند السماح بذلك
|
||||
|
||||
<Tip>
|
||||
فكّر في الوكيل كعضو فريق متخصص بمهارات وخبرات ومسؤوليات محددة.
|
||||
على سبيل المثال، قد يتفوق وكيل `Researcher` في جمع وتحليل المعلومات،
|
||||
بينما قد يكون وكيل `Writer` أفضل في إنشاء المحتوى.
|
||||
</Tip>
|
||||
|
||||
<Note type="info" title="تحسين المؤسسات: منشئ الوكلاء المرئي">
|
||||
يتضمن CrewAI AMP منشئ وكلاء مرئي يبسّط إنشاء وتهيئة الوكلاء بدون كتابة كود. صمم وكلاءك بصريًا واختبرهم في الوقت الفعلي.
|
||||
|
||||

|
||||
|
||||
يُمكّن منشئ الوكلاء المرئي من:
|
||||
|
||||
- تهيئة وكلاء بديهية بواجهات نماذج
|
||||
- اختبار والتحقق في الوقت الفعلي
|
||||
- مكتبة قوالب مع أنواع وكلاء مهيأة مسبقًا
|
||||
- تخصيص سهل لخصائص وسلوكيات الوكيل
|
||||
</Note>
|
||||
|
||||
## خصائص الوكيل
|
||||
|
||||
| الخاصية | المعامل | النوع | الوصف |
|
||||
| :-------------------------------------- | :----------------------- | :------------------------------------ | :------------------------------------------------------------------------------------------------------- |
|
||||
| **الدور** | `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 <name>` تستخدم تهيئة JSON-first. يُعرّف كل Agent في `agents/<agent_name>.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`.
|
||||
|
||||
<Note>
|
||||
يدعم JSONC التعليقات والفواصل النهائية. إذا وُجد `agents/<name>.jsonc` و `agents/<name>.json` معًا، يستخدم CrewAI ملف JSONC.
|
||||
</Note>
|
||||
|
||||
### تهيئة YAML الكلاسيكية
|
||||
|
||||
المشاريع الكلاسيكية التي تُنشأ عبر `crewai create crew <name> --classic` تستخدم `config/agents.yaml` وفئة `@CrewBase` في `crew.py`.
|
||||
|
||||
تظل تهيئة YAML مدعومة للمشاريع الحالية المبنية بـ Python/YAML وللفِرق التي تفضل تعريف الوكلاء من خلال فئة `@CrewBase`.
|
||||
|
||||
بعد إنشاء مشروع كلاسيكي، انتقل إلى ملف `src/<project_name>/config/agents.yaml` وعدّل القالب ليتوافق مع متطلباتك.
|
||||
|
||||
<Note>
|
||||
ستُستبدل المتغيرات في ملفات YAML (مثل `{topic}`) بقيم من مدخلاتك عند تشغيل الطاقم:
|
||||
```python Code
|
||||
crew.kickoff(inputs={'topic': 'AI Agents'})
|
||||
```
|
||||
</Note>
|
||||
|
||||
إليك مثالًا على كيفية تهيئة الوكلاء باستخدام YAML:
|
||||
|
||||
```yaml agents.yaml
|
||||
# src/<project_name>/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/<project_name>/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
|
||||
)
|
||||
```
|
||||
|
||||
<Note>
|
||||
يجب أن تتطابق الأسماء المستخدمة في ملفات YAML (`agents.yaml`) مع أسماء
|
||||
الطرق في كود Python.
|
||||
</Note>
|
||||
|
||||
### تعريف مباشر في الكود
|
||||
|
||||
يمكنك إنشاء الوكلاء مباشرة في الكود بإنشاء فئة `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`: إعادات المحاولة عند الخطأ
|
||||
|
||||
#### تنفيذ الكود
|
||||
|
||||
<Warning>
|
||||
`allow_code_execution` و`code_execution_mode` مهجوران. تمت إزالة `CodeInterpreterTool` من `crewai-tools`. استخدم خدمة بيئة معزولة مخصصة مثل [E2B](https://e2b.dev) أو [Modal](https://modal.com) لتنفيذ الكود بأمان.
|
||||
</Warning>
|
||||
|
||||
- `allow_code_execution` _(مهجور)_: كان يُمكّن تنفيذ الكود المدمج عبر `CodeInterpreterTool`.
|
||||
- `code_execution_mode` _(مهجور)_: كان يتحكم في وضع التنفيذ (`"safe"` لـ Docker، `"unsafe"` للتنفيذ المباشر).
|
||||
|
||||
#### الميزات المتقدمة
|
||||
|
||||
- `multimodal`: تفعيل القدرات متعددة الوسائط لمعالجة النص والمحتوى المرئي
|
||||
- `reasoning`: تمكين الوكيل من التأمل وإنشاء خطط قبل تنفيذ المهام
|
||||
- `inject_date`: حقن التاريخ الحالي تلقائيًا في أوصاف المهام
|
||||
|
||||
#### القوالب
|
||||
|
||||
- `system_template`: يحدد السلوك الأساسي للوكيل
|
||||
- `prompt_template`: ينظم تنسيق الإدخال
|
||||
- `response_template`: ينسّق استجابات الوكيل
|
||||
|
||||
<Note>
|
||||
عند استخدام القوالب المخصصة، تأكد من تعريف كل من `system_template` و
|
||||
`prompt_template`. `response_template` اختياري لكن يُوصى به
|
||||
لتنسيق مخرجات متسق.
|
||||
</Note>
|
||||
|
||||
## أدوات الوكيل
|
||||
|
||||
يمكن تجهيز الوكلاء بأدوات متنوعة لتعزيز قدراتهم. يدعم 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)
|
||||
```
|
||||
|
||||
## اعتبارات مهمة وأفضل الممارسات
|
||||
|
||||
### الأمان وتنفيذ الكود
|
||||
|
||||
<Warning>
|
||||
`allow_code_execution` و`code_execution_mode` مهجوران وتمت إزالة `CodeInterpreterTool`. استخدم خدمة بيئة معزولة مخصصة مثل [E2B](https://e2b.dev) أو [Modal](https://modal.com) لتنفيذ الكود بأمان.
|
||||
</Warning>
|
||||
|
||||
### تحسين الأداء
|
||||
|
||||
- استخدم `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` المختار يدعم الميزات التي تحتاجها
|
||||
@@ -1,423 +0,0 @@
|
||||
---
|
||||
title: Checkpointing
|
||||
description: حفظ حالة التنفيذ تلقائيا حتى تتمكن الطواقم والتدفقات والوكلاء من الاستئناف بعد الفشل.
|
||||
icon: floppy-disk
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
الـ Checkpointing يحفظ لقطة من حالة التنفيذ أثناء التشغيل بحيث يمكن لطاقم أو تدفق أو وكيل الاستئناف بعد الفشل أو التفرع إلى فرع بديل.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="الشرح" icon="lightbulb" href="#الشرح">
|
||||
كيف يعمل الـ Checkpointing: الأحداث والتخزين والوراثة.
|
||||
</Card>
|
||||
<Card title="درس تطبيقي" icon="graduation-cap" href="#درس-تطبيقي-استئناف-طاقم-فاشل">
|
||||
دليل 5 دقائق: تشغيل، إيقاف، استئناف.
|
||||
</Card>
|
||||
<Card title="ادلة عملية" icon="screwdriver-wrench" href="#ادلة-عملية">
|
||||
وصفات مركزة على المهام لسير العمل الشائع.
|
||||
</Card>
|
||||
<Card title="المرجع" icon="book" href="#المرجع">
|
||||
`CheckpointConfig` والأحداث والمزودات وسطر الأوامر.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## الشرح
|
||||
|
||||
### ما هي نقطة الحفظ
|
||||
|
||||
تلتقط نقطة الحفظ كل ما يحتاجه CrewAI لإعادة إنشاء تشغيل أثناء سيره: الحالة الكاملة للطاقم أو التدفق أو الوكيل — التكوين، وذاكرة الوكلاء ومصادر المعرفة، وتقدم المهام، والمخرجات الوسيطة، والحالة الداخلية والسمات — إلى جانب مدخلات الـ kickoff، وسجل الأحداث حتى تلك النقطة، ومعرف نسب يربط نقطة الحفظ بالتشغيل الذي جاءت منه.
|
||||
|
||||
الاستعادة تعيد بناء تلك الحالة وتستمر. تتخطى المهام المكتملة، وتعاد ترطيب الذاكرة والمعرفة، ويعمل العمل التابع على نفس المخرجات التي أنتجها التشغيل الأصلي. التفرع يجري نفس الاستعادة تحت نسب جديد، بحيث يكتب الفرع الجديد والتشغيل الأصلي نقاط الحفظ جنبا إلى جنب دون أن يطمس أحدهما الآخر.
|
||||
|
||||
### متى تكتب نقاط الحفظ
|
||||
|
||||
الـ Checkpointing مدفوع بالأحداث. يشترك وقت التشغيل في الأحداث التي تحددها عبر `on_events` ويكتب نقطة حفظ عند إطلاق أحدها. الافتراضي `task_completed` ينتج نقطة حفظ لكل مهمة منتهية — توازن معقول بين الدقة واستخدام القرص. الأحداث عالية التردد مثل `llm_call_completed` متاحة للاستعادة الدقيقة لكنها تكتب ملفات أكثر بكثير.
|
||||
|
||||
### التخزين
|
||||
|
||||
يتضمن CrewAI مزودين:
|
||||
|
||||
- `JsonProvider` يكتب ملفا لكل نقطة حفظ. قابل للقراءة وسهل التفقد.
|
||||
- `SqliteProvider` يكتب إلى قاعدة بيانات SQLite واحدة. أفضل لنقاط الحفظ عالية التردد.
|
||||
|
||||
كلاهما يحذف أقدم نقاط الحفظ عند تحديد `max_checkpoints`.
|
||||
|
||||
<Note>
|
||||
كتابة نقاط الحفظ بأفضل جهد. فشل نقطة حفظ يسجل لكنه لا يقاطع التشغيل.
|
||||
</Note>
|
||||
|
||||
### نموذج الوراثة
|
||||
|
||||
`Crew` و`Flow` و`Agent` كلها تقبل وسيط `checkpoint`. يرث الأبناء من الأب ما لم يحددوا قيمتهم الخاصة أو يمرروا `False` للانسحاب. فعل الـ Checkpointing مرة واحدة على الطاقم وتشارك كل الوكلاء، أو استبعد وكيلا واحدا بشكل انتقائي.
|
||||
|
||||
## درس تطبيقي: استئناف طاقم فاشل
|
||||
|
||||
هذا الدليل يستغرق حوالي 5 دقائق. ستشغل طاقما بمهمتين، توقفه في المنتصف، ثم تستأنف من نقطة الحفظ المحفوظة.
|
||||
|
||||
<Steps>
|
||||
<Step title="أنشئ الطاقم مع تفعيل الـ Checkpointing">
|
||||
```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,
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
<Step title="شغله وأوقفه بعد المهمة الأولى">
|
||||
```python
|
||||
result = crew.kickoff()
|
||||
```
|
||||
|
||||
اضغط `Ctrl+C` بعد انتهاء المهمة الأولى. في `./.checkpoints/`، الملف بصيغة `<timestamp>_<uuid>.json` هو نقطة الحفظ.
|
||||
</Step>
|
||||
<Step title="استأنف من نقطة الحفظ">
|
||||
```python
|
||||
from crewai import CheckpointConfig
|
||||
|
||||
result = crew.kickoff(
|
||||
from_checkpoint=CheckpointConfig(
|
||||
restore_from="./.checkpoints/<timestamp>_<uuid>.json",
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
يتم تخطي مهمة البحث، ويعمل الكاتب على مخرجات البحث المحفوظة، وينتهي الطاقم.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## ادلة عملية
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="تفعيل الـ Checkpointing بالإعدادات الافتراضية" icon="play">
|
||||
```python
|
||||
crew = Crew(agents=[...], tasks=[...], checkpoint=True)
|
||||
```
|
||||
|
||||
يكتب إلى `./.checkpoints/` عند كل `task_completed`.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="تخصيص التخزين والتردد" icon="sliders">
|
||||
```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,
|
||||
),
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="اختيار مزود التخزين" icon="database">
|
||||
<CodeGroup>
|
||||
```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,
|
||||
),
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
SQLite يفعل وضع journal WAL للقراءات المتزامنة. يفضل لنقاط الحفظ عالية التردد.
|
||||
</Tip>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="استبعاد وكيل واحد" icon="user-slash">
|
||||
```python
|
||||
crew = Crew(
|
||||
agents=[
|
||||
Agent(role="Researcher", ...),
|
||||
Agent(role="Writer", ..., checkpoint=False),
|
||||
],
|
||||
tasks=[...],
|
||||
checkpoint=True,
|
||||
)
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="التفرع إلى فرع جديد" icon="code-branch">
|
||||
`fork()` يستعيد نقطة حفظ تحت نسب جديد بحيث لا يتصادم التشغيل الجديد مع الأصلي.
|
||||
|
||||
```python
|
||||
config = CheckpointConfig(restore_from="./my_checkpoints/<file>.json")
|
||||
crew = Crew.fork(config, branch="experiment-a")
|
||||
result = crew.kickoff(inputs={"strategy": "aggressive"})
|
||||
```
|
||||
|
||||
تسمية `branch` اختيارية؛ يتم إنشاء واحدة إذا أغفلت.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Checkpointing لـ Crew أو Flow أو Agent" icon="cubes">
|
||||
<Tabs>
|
||||
<Tab title="Crew">
|
||||
```python
|
||||
crew = Crew(
|
||||
agents=[researcher, writer],
|
||||
tasks=[research_task, write_task, review_task],
|
||||
checkpoint=CheckpointConfig(location="./crew_cp"),
|
||||
)
|
||||
```
|
||||
|
||||
المشغل الافتراضي: `task_completed`.
|
||||
</Tab>
|
||||
<Tab title="Flow">
|
||||
```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()
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Agent">
|
||||
```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"}])
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="كتابة نقطة حفظ يدويا" icon="code">
|
||||
سجل معالجا على أي حدث واستدع `state.checkpoint()`.
|
||||
|
||||
<CodeGroup>
|
||||
```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}")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
يتم تمرير وسيط `state` تلقائيا عندما يقبل المعالج ثلاثة معاملات. راجع [Event Listeners](/ar/concepts/event-listener) لقائمة الأحداث الكاملة.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="التصفح والاستئناف والتفرع من سطر الأوامر" icon="terminal">
|
||||
```bash
|
||||
crewai checkpoint
|
||||
crewai checkpoint --location ./my_checkpoints
|
||||
crewai checkpoint --location ./.checkpoints.db
|
||||
```
|
||||
|
||||
<Frame caption="شجرة نقاط الحفظ — الفروع والتفرعات تتداخل تحت أبيها.">
|
||||
<img src="/images/checkpoint-tui-tree.png" alt="Checkpoint TUI tree view" />
|
||||
</Frame>
|
||||
|
||||
اللوحة اليسرى تجمع نقاط الحفظ حسب الفرع؛ التفرعات تتداخل تحت أبيها. اختيار نقطة حفظ يفتح لوحة التفاصيل مع بياناتها الوصفية وحالة الكيان وتقدم المهام. **Resume** يكمل التشغيل؛ **Fork** يبدأ فرعا جديدا.
|
||||
|
||||
<Frame caption="تبويب النظرة العامة — البيانات الوصفية وحالة الكيان وملخص التشغيل.">
|
||||
<img src="/images/checkpoint-tui-detail-overview.png" alt="Checkpoint detail overview tab" />
|
||||
</Frame>
|
||||
|
||||
لوحة التفاصيل تعرض منطقتين قابلتين للتحرير:
|
||||
|
||||
- **Inputs** — مدخلات الـ kickoff الأصلية، معبأة مسبقا وقابلة للتحرير.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/checkpoint-tui-detail-inputs.png" alt="Editable kickoff inputs" />
|
||||
</Frame>
|
||||
|
||||
- **مخرجات المهام** — مخرجات المهام المكتملة. تحرير مخرج والضغط على **Fork** يبطل المهام التابعة لتعاد بالسياق المعدل.
|
||||
|
||||
<Frame>
|
||||
<img src="/images/checkpoint-tui-detail-tasks.png" alt="Editable task outputs" />
|
||||
</Frame>
|
||||
|
||||
<Frame caption="عرض التفرع — تأكيد فرع جديد من نقطة الحفظ المختارة.">
|
||||
<img src="/images/checkpoint-tui-details-fork.png" alt="Fork confirmation panel" />
|
||||
</Frame>
|
||||
|
||||
<Tip>
|
||||
مفيد لاستكشاف "ماذا لو": تفرع، عدل، راقب.
|
||||
</Tip>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="تفقد نقاط الحفظ بدون TUI" icon="magnifying-glass">
|
||||
```bash
|
||||
crewai checkpoint list ./my_checkpoints
|
||||
crewai checkpoint info ./my_checkpoints/<file>.json
|
||||
crewai checkpoint info ./.checkpoints.db
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## المرجع
|
||||
|
||||
### `CheckpointConfig`
|
||||
|
||||
<ParamField path="location" type="str" default='"./.checkpoints"'>
|
||||
وجهة التخزين. مجلد لـ `JsonProvider`، مسار ملف قاعدة بيانات لـ `SqliteProvider`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="on_events" type='list[CheckpointEventType | Literal["*"]]' default='["task_completed"]'>
|
||||
أنواع الأحداث التي تطلق نقطة حفظ. `CheckpointEventType` هو `Literal` — مدقق الأنواع يكمل تلقائيا ويرفض القيم غير المدعومة. راجع [أنواع الأحداث](#أنواع-الأحداث) للقائمة الكاملة.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="provider" type="BaseProvider" default="JsonProvider()">
|
||||
واجهة التخزين. `JsonProvider` أو `SqliteProvider`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="max_checkpoints" type="int | None" default="None">
|
||||
الحد الاقصى لنقاط الحفظ المحتفظ بها. الأقدم تحذف بعد كل كتابة.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="restore_from" type="Path | str | None" default="None">
|
||||
نقطة الحفظ المراد استعادتها عند تمريرها عبر `from_checkpoint`.
|
||||
</ParamField>
|
||||
|
||||
### قيم حقل `checkpoint`
|
||||
|
||||
مقبولة في `Crew` و`Flow` و`Agent`.
|
||||
|
||||
<ParamField path="None" type="افتراضي">
|
||||
يرث من الأب.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="True" type="bool">
|
||||
تفعيل بالإعدادات الافتراضية.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="False" type="bool">
|
||||
انسحاب صريح. يوقف الوراثة.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="CheckpointConfig(...)" type="CheckpointConfig">
|
||||
إعدادات مخصصة.
|
||||
</ParamField>
|
||||
|
||||
### أنواع الأحداث
|
||||
|
||||
يقبل `on_events` أي مجموعة من قيم `CheckpointEventType`. الافتراضي `["task_completed"]` يكتب نقطة حفظ لكل مهمة منتهية، و`["*"]` يطابق جميع الأحداث.
|
||||
|
||||
<Warning>
|
||||
`["*"]` والأحداث عالية التردد مثل `llm_call_completed` تكتب نقاط حفظ كثيرة وقد تضر بالاداء. استخدمها مع `max_checkpoints`.
|
||||
</Warning>
|
||||
|
||||
<Expandable title="جميع الأحداث المدعومة">
|
||||
|
||||
- **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`
|
||||
- **حرف بدل** — `"*"` يطابق جميع الأحداث.
|
||||
|
||||
</Expandable>
|
||||
|
||||
### مزودات التخزين
|
||||
|
||||
<ParamField path="JsonProvider" type="provider">
|
||||
ملف واحد لكل نقطة حفظ بصيغة `<timestamp>_<uuid>.json` داخل `location`.
|
||||
</ParamField>
|
||||
|
||||
<ParamField path="SqliteProvider" type="provider">
|
||||
ملف قاعدة بيانات واحد في `location` مع journaling WAL.
|
||||
</ParamField>
|
||||
|
||||
### سطر الأوامر
|
||||
|
||||
| الامر | الغرض |
|
||||
|:------|:------|
|
||||
| `crewai checkpoint` | تشغيل TUI؛ كشف التخزين تلقائيا. |
|
||||
| `crewai checkpoint --location <path>` | تشغيل TUI على موقع محدد. |
|
||||
| `crewai checkpoint list <path>` | سرد نقاط الحفظ. |
|
||||
| `crewai checkpoint info <path>` | تفقد ملف نقطة حفظ أو آخر مدخل في قاعدة بيانات SQLite. |
|
||||
@@ -1,302 +0,0 @@
|
||||
---
|
||||
title: واجهة سطر الأوامر
|
||||
description: تعرّف على كيفية استخدام واجهة سطر أوامر CrewAI للتفاعل مع CrewAI.
|
||||
icon: terminal
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Warning>
|
||||
منذ الإصدار 0.140.0، بدأ CrewAI AMP عملية نقل مزود تسجيل الدخول.
|
||||
لذلك، تم تحديث تدفق المصادقة عبر CLI. المستخدمون الذين يسجلون الدخول
|
||||
باستخدام Google، أو الذين أنشأوا حساباتهم بعد 3 يوليو 2025 لن يتمكنوا
|
||||
من تسجيل الدخول مع الإصدارات القديمة من مكتبة `crewai`.
|
||||
</Warning>
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
توفر واجهة سطر أوامر 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
|
||||
```
|
||||
|
||||
<Note>
|
||||
بدءًا من الإصدار 0.103.0، يمكن استخدام أمر `crewai run` لتشغيل
|
||||
كل من الأطقم القياسية والتدفقات. للتدفقات، يكتشف تلقائيًا النوع
|
||||
من pyproject.toml ويشغّل الأمر المناسب. هذه هي الطريقة الموصى بها
|
||||
لتشغيل كل من الأطقم والتدفقات.
|
||||
</Note>
|
||||
|
||||
### 9. الدردشة
|
||||
|
||||
بدءًا من الإصدار `0.98.0`، عند تشغيل أمر `crewai chat`، تبدأ جلسة تفاعلية مع طاقمك. سيرشدك المساعد الذكي بطلب المدخلات اللازمة لتنفيذ الطاقم. بمجرد توفير جميع المدخلات، سينفذ الطاقم مهامه.
|
||||
|
||||
```shell Terminal
|
||||
crewai chat
|
||||
```
|
||||
|
||||
<Note>
|
||||
مهم: عيّن خاصية `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",
|
||||
)
|
||||
```
|
||||
</Note>
|
||||
|
||||
### 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
|
||||
```
|
||||
|
||||
<Note>
|
||||
**لتفعيل التتبع**، استخدم أيًا من هذه الطرق:
|
||||
- عيّن `tracing=True` في كود الطاقم/التدفق، أو
|
||||
- أضف `CREWAI_TRACING_ENABLED=true` إلى ملف `.env`، أو
|
||||
- شغّل `crewai traces enable`
|
||||
|
||||
**لتعطيل التتبع**، استخدم أيًا من هذه الطرق:
|
||||
- عيّن `tracing=False` في كود الطاقم/التدفق، أو
|
||||
- أزل أو عيّن `false` لمتغير `CREWAI_TRACING_ENABLED`، أو
|
||||
- شغّل `crewai traces disable`
|
||||
</Note>
|
||||
|
||||
<Tip>
|
||||
يتعامل CrewAI CLI مع المصادقة لمستودع الأدوات تلقائيًا عند
|
||||
إضافة حزم إلى مشروعك. فقط أضف `crewai` قبل أي أمر `uv`
|
||||
لاستخدامه. مثلًا `crewai uv add requests`.
|
||||
</Tip>
|
||||
|
||||
<Note>
|
||||
تُخزن إعدادات التهيئة في `~/.config/crewai/settings.json`. بعض
|
||||
الإعدادات مثل اسم المؤسسة ومعرّفها للقراءة فقط وتُدار من خلال
|
||||
أوامر المصادقة والمؤسسة.
|
||||
</Note>
|
||||
@@ -1,363 +0,0 @@
|
||||
---
|
||||
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` لرؤية التعاون في العمل
|
||||
- **حسّن أوصاف المهام**: المهام الواضحة تؤدي إلى تعاون أفضل
|
||||
- **وسّع النطاق**: جرّب العمليات الهرمية للمشاريع المعقدة
|
||||
|
||||
يحوّل التعاون وكلاء الذكاء الاصطناعي الفرديين إلى فرق قوية يمكنها معالجة التحديات المعقدة ومتعددة الأوجه معًا.
|
||||
@@ -1,245 +0,0 @@
|
||||
---
|
||||
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`. |
|
||||
|
||||
<Tip>
|
||||
**الحد الأقصى لـ RPM للطاقم**: تعيّن خاصية `max_rpm` الحد الأقصى للطلبات في الدقيقة التي يمكن للطاقم تنفيذها لتجنب حدود المعدل وستتجاوز إعدادات `max_rpm` الفردية للوكلاء إذا عيّنتها.
|
||||
</Tip>
|
||||
|
||||
## إنشاء الأطقم
|
||||
|
||||
هناك طريقتان رئيسيتان لإنشاء الأطقم في CrewAI: باستخدام **تهيئة JSONC (الموصى بها للـ crews الجديدة)** أو تعريفها **مباشرة في الكود** للمشاريع الكلاسيكية والحالات المتقدمة.
|
||||
|
||||
### تهيئة JSONC (موصى بها)
|
||||
|
||||
المشاريع الجديدة التي تُنشأ عبر `crewai create crew <name>` تستخدم `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/<name>.jsonc` ثم إلى `agents/<name>.json`. للـ crews الهرمية، استخدم `"process": "hierarchical"` مع `manager_llm` أو `manager_agent`.
|
||||
|
||||
<Warning>
|
||||
شغّل مشاريع JSON crew من مصادر تثق بها فقط. أدوات `custom:<name>` ومراجع `{"python": "module.attribute"}` تنفذ كود Python محليًا عند تحميل الـ crew.
|
||||
</Warning>
|
||||
|
||||
### تهيئة YAML الكلاسيكية
|
||||
|
||||
المشاريع الكلاسيكية التي تُنشأ عبر `crewai create crew <name> --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,
|
||||
)
|
||||
```
|
||||
|
||||
<Note>
|
||||
سيتم تنفيذ المهام بالترتيب الذي عُرّفت به.
|
||||
</Note>
|
||||
|
||||
فئة `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) لجميع المهام المنفذة.
|
||||
|
||||
```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()` | مبني على الخيوط | غير متزامن مبني على الخيوط لكل مدخل في قائمة |
|
||||
|
||||
<Note>
|
||||
لأحمال العمل عالية التزامن، يُوصى بـ `akickoff()` و `akickoff_for_each()` لأنها تستخدم async أصلي.
|
||||
</Note>
|
||||
|
||||
### بث تنفيذ الطاقم
|
||||
|
||||
للرؤية في الوقت الفعلي لتنفيذ الطاقم، يمكنك تفعيل البث:
|
||||
|
||||
```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 <task_id>
|
||||
```
|
||||
@@ -1,237 +0,0 @@
|
||||
---
|
||||
title: "مستمعو الأحداث"
|
||||
description: "الاستفادة من أحداث CrewAI لبناء تكاملات مخصصة ومراقبة"
|
||||
icon: spinner
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
يوفر CrewAI نظام أحداث قوي يتيح لك الاستماع والتفاعل مع الأحداث المختلفة التي تحدث أثناء تنفيذ طاقمك. تُمكّنك هذه الميزة من بناء تكاملات مخصصة وحلول مراقبة وأنظمة تسجيل أو أي وظائف أخرى تحتاج للتشغيل بناءً على أحداث CrewAI الداخلية.
|
||||
|
||||
## كيف يعمل
|
||||
|
||||
يستخدم CrewAI بنية ناقل أحداث لإرسال الأحداث طوال دورة حياة التنفيذ. يُبنى نظام الأحداث على المكونات التالية:
|
||||
|
||||
1. **CrewAIEventsBus**: ناقل أحداث فريد يدير تسجيل الأحداث وإرسالها
|
||||
2. **BaseEvent**: الفئة الأساسية لجميع الأحداث في النظام
|
||||
3. **BaseEventListener**: فئة أساسية مجردة لإنشاء مستمعي أحداث مخصصين
|
||||
|
||||
عندما تحدث إجراءات محددة في CrewAI (مثل بدء تنفيذ طاقم، أو إكمال وكيل لمهمة، أو استخدام أداة)، يرسل النظام أحداثًا مقابلة. يمكنك تسجيل معالجات لهذه الأحداث لتنفيذ كود مخصص عند حدوثها.
|
||||
|
||||
<Note type="info" title="تحسين المؤسسات: تتبع الأوامر">
|
||||
يوفر CrewAI AMP ميزة تتبع أوامر مدمجة تستفيد من نظام الأحداث لتتبع وتخزين وتصور جميع الأوامر والاستكمالات والبيانات الوصفية المرتبطة.
|
||||
|
||||

|
||||
|
||||
مع تتبع الأوامر يمكنك:
|
||||
|
||||
- عرض السجل الكامل لجميع الأوامر المرسلة إلى LLM
|
||||
- تتبع استخدام الرموز والتكاليف
|
||||
- تصحيح إخفاقات استدلال الوكيل
|
||||
- مشاركة تسلسلات الأوامر مع فريقك
|
||||
- مقارنة استراتيجيات الأوامر المختلفة
|
||||
- تصدير التتبعات للامتثال والتدقيق
|
||||
</Note>
|
||||
|
||||
## إنشاء مستمع أحداث مخصص
|
||||
|
||||
لإنشاء مستمع أحداث مخصص، تحتاج إلى:
|
||||
|
||||
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، يمكنك توسيع وظائفه ودمجه بسلاسة مع بنيتك التحتية الحالية.
|
||||
@@ -1,267 +0,0 @@
|
||||
---
|
||||
title: الملفات
|
||||
description: تمرير الصور وملفات PDF والصوت والفيديو والنصوص إلى وكلائك للمعالجة متعددة الوسائط.
|
||||
icon: file-image
|
||||
---
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
يدعم CrewAI مدخلات الملفات متعددة الوسائط الأصلية، مما يتيح لك تمرير الصور وملفات PDF والصوت والفيديو والنصوص مباشرة إلى وكلائك. يتم تنسيق الملفات تلقائيًا وفقًا لمتطلبات API لكل مزود LLM.
|
||||
|
||||
<Note type="info" title="اعتمادية اختيارية">
|
||||
يتطلب دعم الملفات حزمة `crewai-files` الاختيارية. ثبّتها بـ:
|
||||
|
||||
```bash
|
||||
uv add 'crewai[file-processing]'
|
||||
```
|
||||
</Note>
|
||||
|
||||
<Note type="warning" title="وصول مبكر">
|
||||
واجهة معالجة الملفات حاليًا في مرحلة الوصول المبكر.
|
||||
</Note>
|
||||
|
||||
## أنواع الملفات
|
||||
|
||||
يدعم 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) | ✓ | | ✓ | | |
|
||||
|
||||
<Note type="info" title="Gemini لأقصى دعم للملفات">
|
||||
تدعم نماذج Google Gemini جميع أنواع الملفات بما في ذلك الفيديو (حتى ساعة واحدة، 2 جيجابايت). استخدم Gemini عندما تحتاج لمعالجة محتوى الفيديو.
|
||||
</Note>
|
||||
|
||||
<Note type="warning" title="أنواع الملفات غير المدعومة">
|
||||
إذا مررت نوع ملف لا يدعمه المزود (مثل الفيديو إلى OpenAI)، ستتلقى خطأ `UnsupportedFileTypeError`. اختر مزودك بناءً على أنواع الملفات التي تحتاج لمعالجتها.
|
||||
</Note>
|
||||
|
||||
## كيف تُرسل الملفات
|
||||
|
||||
يختار 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** | ✓ | | ✓ |
|
||||
|
||||
<Note type="info" title="تحسين تلقائي">
|
||||
لا تحتاج لإدارة هذا بنفسك. يستخدم CrewAI تلقائيًا الطريقة الأكثر كفاءة بناءً على حجم الملف وقدرات المزود. المزودات بدون واجهات رفع الملفات تستخدم inline base64 لجميع الملفات.
|
||||
</Note>
|
||||
|
||||
## أوضاع معالجة الملفات
|
||||
|
||||
تحكم في كيفية معالجة الملفات عندما تتجاوز حدود المزود:
|
||||
|
||||
```python
|
||||
from crewai_files import ImageFile, PDFFile
|
||||
|
||||
image = ImageFile(source="large.png", mode="strict")
|
||||
image = ImageFile(source="large.png", mode="auto")
|
||||
image = ImageFile(source="large.png", mode="warn")
|
||||
pdf = PDFFile(source="large.pdf", mode="chunk")
|
||||
```
|
||||
|
||||
## قيود المزودين
|
||||
|
||||
لكل مزود حدود محددة لأحجام الملفات والأبعاد:
|
||||
|
||||
### OpenAI
|
||||
- **الصور**: حد أقصى 20 ميجابايت، حتى 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"),
|
||||
}
|
||||
)
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,878 +0,0 @@
|
||||
---
|
||||
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"}},
|
||||
)
|
||||
```
|
||||
|
||||
### أمثلة المزودين
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="OpenAI (افتراضي)">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"model_name": "text-embedding-3-small",
|
||||
# "api_key": "sk-...", # or set OPENAI_API_KEY env var
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Ollama (محلي، خاص)">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model_name": "mxbai-embed-large",
|
||||
"url": "http://localhost:11434/api/embeddings",
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Azure OpenAI">
|
||||
```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",
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Google AI">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "google-generativeai",
|
||||
"config": {
|
||||
"model_name": "gemini-embedding-001",
|
||||
# "api_key": "...", # or set GOOGLE_API_KEY env var
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Google Vertex AI">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "google-vertex",
|
||||
"config": {
|
||||
"model_name": "gemini-embedding-001",
|
||||
"project_id": "your-gcp-project-id",
|
||||
"location": "us-central1",
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Cohere">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "cohere",
|
||||
"config": {
|
||||
"model_name": "embed-english-v3.0",
|
||||
# "api_key": "...", # or set COHERE_API_KEY env var
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="VoyageAI">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "voyageai",
|
||||
"config": {
|
||||
"model": "voyage-3",
|
||||
# "api_key": "...", # or set VOYAGE_API_KEY env var
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="AWS Bedrock">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "amazon-bedrock",
|
||||
"config": {
|
||||
"model_name": "amazon.titan-embed-text-v1",
|
||||
# Uses default AWS credentials (boto3 session)
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Hugging Face">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "huggingface",
|
||||
"config": {
|
||||
"model_name": "sentence-transformers/all-MiniLM-L6-v2",
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Jina">
|
||||
```python
|
||||
memory = Memory(embedder={
|
||||
"provider": "jina",
|
||||
"config": {
|
||||
"model_name": "jina-embeddings-v2-base-en",
|
||||
# "api_key": "...", # or set JINA_API_KEY env var
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="IBM WatsonX">
|
||||
```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",
|
||||
},
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="مُضمِّن مخصص">
|
||||
```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)
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### مرجع المزودين
|
||||
|
||||
| المزود | المفتاح | النموذج النموذجي | ملاحظات |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| 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 أثناء الاسترجاع العميق. |
|
||||
@@ -1,155 +0,0 @@
|
||||
---
|
||||
title: التخطيط
|
||||
description: تعرّف على كيفية إضافة التخطيط إلى طاقم CrewAI وتحسين أدائه.
|
||||
icon: ruler-combined
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
تتيح لك ميزة التخطيط في CrewAI إضافة قدرة التخطيط إلى طاقمك. عند تفعيلها، قبل كل تكرار للطاقم،
|
||||
يتم إرسال جميع معلومات الطاقم إلى AgentPlanner الذي يخطط للمهام خطوة بخطوة، ويُضاف هذا المخطط إلى وصف كل مهمة.
|
||||
|
||||
### استخدام ميزة التخطيط
|
||||
|
||||
البدء بميزة التخطيط سهل جدًا، الخطوة الوحيدة المطلوبة هي إضافة `planning=True` إلى طاقمك:
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
from crewai import Crew, Agent, Task, Process
|
||||
|
||||
# تجميع طاقمك مع قدرات التخطيط
|
||||
my_crew = Crew(
|
||||
agents=self.agents,
|
||||
tasks=self.tasks,
|
||||
process=Process.sequential,
|
||||
planning=True,
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
من هذه النقطة فصاعدًا، سيكون التخطيط مفعّلًا في طاقمك، وسيتم تخطيط المهام قبل كل تكرار.
|
||||
|
||||
<Warning>
|
||||
عند تفعيل التخطيط، سيستخدم CrewAI `gpt-4o-mini` كنموذج LLM افتراضي للتخطيط، مما يتطلب مفتاح API صالحًا من OpenAI. نظرًا لأن وكلاءك قد يستخدمون نماذج LLM مختلفة، فقد يسبب ذلك ارتباكًا إذا لم يكن لديك مفتاح OpenAI API مهيأ أو إذا كنت تواجه سلوكًا غير متوقع متعلقًا باستدعاءات LLM API.
|
||||
</Warning>
|
||||
|
||||
#### LLM التخطيط
|
||||
|
||||
يمكنك الآن تحديد نموذج LLM الذي سيُستخدم لتخطيط المهام.
|
||||
|
||||
عند تشغيل مثال الحالة الأساسية، سترى شيئًا مشابهًا للمخرجات أدناه، والتي تمثل مخرجات `AgentPlanner`
|
||||
المسؤول عن إنشاء المنطق التدريجي لإضافته إلى مهام الوكلاء.
|
||||
|
||||
<CodeGroup>
|
||||
```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 '```'.
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -1,66 +0,0 @@
|
||||
---
|
||||
title: العمليات
|
||||
description: دليل تفصيلي حول إدارة سير العمل من خلال العمليات في CrewAI، مع تفاصيل التنفيذ المحدّثة.
|
||||
icon: bars-staggered
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
<Tip>
|
||||
تنسّق العمليات تنفيذ المهام بواسطة الوكلاء، على غرار إدارة المشاريع في الفرق البشرية.
|
||||
تضمن هذه العمليات توزيع المهام وتنفيذها بكفاءة، وفقًا لاستراتيجية محددة مسبقًا.
|
||||
</Tip>
|
||||
|
||||
## تنفيذات العمليات
|
||||
|
||||
- **تسلسلي**: ينفذ المهام بالتتابع، مما يضمن إكمال المهام بتقدم منظم.
|
||||
- **هرمي**: ينظم المهام في تسلسل إداري هرمي، حيث يتم تفويض المهام وتنفيذها بناءً على سلسلة أوامر منظمة. يجب تحديد نموذج لغة المدير (`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 ضروري لتمكين العمل الجماعي المنهجي بين الوكلاء.
|
||||
تم تحديث هذه الوثائق لتعكس أحدث الميزات والتحسينات، مما يضمن وصول المستخدمين إلى أحدث المعلومات وأكثرها شمولاً.
|
||||
@@ -1,162 +0,0 @@
|
||||
---
|
||||
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": <uuid>})`، مما يمدّ نفس تاريخ `flow_uuid`. لـ **تفرع** تدفق مستمر إلى نسبٍ جديد — ترطيب الحالة من تشغيل سابق ولكن الكتابة تحت `state.id` جديد — مرّر `restore_from_state_id`:
|
||||
|
||||
```python
|
||||
flow.kickoff(restore_from_state_id="<previous-run-state-id>")
|
||||
```
|
||||
|
||||
يحصل التشغيل الجديد على `state.id` جديد (مولّد تلقائيًا، أو `inputs["id"]` إذا تم تثبيته) لذا لا تمتد كتابات `@persist` الخاصة به إلى تاريخ المصدر. الجمع مع `from_checkpoint` يطلق `ValueError`؛ اختر مصدر ترطيب واحدًا.
|
||||
|
||||
## الخلاصة
|
||||
|
||||
- **ابدأ بتدفق.**
|
||||
- **حدد حالة واضحة.**
|
||||
- **استخدم الأطقم للمهام المعقدة.**
|
||||
- **انشر مع API واستمرارية.**
|
||||
@@ -1,148 +0,0 @@
|
||||
---
|
||||
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. حقن خطة الاستدلال في وصف المهمة قبل التنفيذ
|
||||
|
||||
تساعد هذه العملية الوكيل على تقسيم المهام المعقدة إلى خطوات يمكن إدارتها وتحديد التحديات المحتملة قبل البدء.
|
||||
|
||||
## خيارات التهيئة
|
||||
|
||||
<ParamField body="reasoning" type="bool" default="False">
|
||||
تفعيل أو تعطيل الاستدلال
|
||||
</ParamField>
|
||||
|
||||
<ParamField body="max_reasoning_attempts" type="int" default="None">
|
||||
الحد الأقصى لعدد المحاولات لتحسين الخطة قبل المتابعة بالتنفيذ. إذا كانت القيمة None (الافتراضي)، سيستمر الوكيل في التحسين حتى يصبح مستعدًا.
|
||||
</ParamField>
|
||||
|
||||
## مثال
|
||||
|
||||
إليك مثالًا كاملًا:
|
||||
|
||||
```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.
|
||||
```
|
||||
|
||||
تساعد خطة الاستدلال هذه الوكيل على تنظيم نهجه تجاه المهمة، والنظر في التحديات المحتملة، وضمان تقديم المخرجات المتوقعة.
|
||||
@@ -1,373 +0,0 @@
|
||||
---
|
||||
title: المهارات
|
||||
description: حزم المهارات المبنية على نظام الملفات التي تحقن خبرة المجال والتعليمات في إرشادات الوكلاء.
|
||||
icon: bolt
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
المهارات هي مجلدات مستقلة توفر للوكلاء **تعليمات وإرشادات ومواد مرجعية خاصة بالمجال**. تُعرّف كل مهارة بملف `SKILL.md` يحتوي على بيانات وصفية YAML ومحتوى Markdown.
|
||||
|
||||
عند التفعيل، يتم حقن تعليمات المهارة مباشرة في إرشادات مهمة الوكيل — مما يمنح الوكيل خبرة دون الحاجة لأي تغييرات في الكود.
|
||||
|
||||
<Note type="info" title="المهارات مقابل الأدوات — التمييز الأساسي">
|
||||
**المهارات ليست أدوات.** هذه هي نقطة الارتباك الأكثر شيوعًا.
|
||||
|
||||
- **المهارات** تحقن *تعليمات وسياق* في إرشادات الوكيل. تخبر الوكيل *كيف يفكر* في مشكلة ما.
|
||||
- **الأدوات** تمنح الوكيل *دوال قابلة للاستدعاء* لاتخاذ إجراءات (البحث، قراءة الملفات، استدعاء APIs).
|
||||
|
||||
غالبًا ما تحتاج **كليهما**: مهارات للخبرة، وأدوات للإجراء. يتم تكوينهما بشكل مستقل ويُكمّلان بعضهما.
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## البداية السريعة
|
||||
|
||||
### 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 <slug>` | النشر تحت مؤسسة محددة (يتجاوز الإعدادات). |
|
||||
| `--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]` |
|
||||
|
||||
**القاعدة العامة:** إذا كان الوكيل يحتاج لاتباع *عملية*، استخدم مهارة. إذا كان يحتاج للرجوع إلى *بيانات*، استخدم المعرفة.
|
||||
|
||||
---
|
||||
|
||||
## الأسئلة الشائعة
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="هل أحتاج لتعيين المهارات والأدوات معًا؟">
|
||||
يعتمد على حالة الاستخدام. المهارات والأدوات **مستقلتان** — يمكنك استخدام أيّ منهما أو كليهما أو لا شيء.
|
||||
|
||||
- **مهارات فقط**: عندما يحتاج الوكيل خبرة لكن لا يحتاج إجراءات خارجية (مثال: الكتابة بإرشادات أسلوبية)
|
||||
- **أدوات فقط**: عندما يحتاج الوكيل إجراءات لكن لا يحتاج منهجية خاصة (مثال: بحث بسيط على الويب)
|
||||
- **كليهما**: عندما يحتاج الوكيل خبرة وإجراءات (مثال: تدقيق أمني بقوائم تحقق محددة وقدرة على فحص الكود)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="هل توفر المهارات أدوات تلقائيًا؟">
|
||||
**لا.** حقل `allowed-tools` في SKILL.md هو بيانات وصفية تجريبية فقط — لا يُنشئ أو يحقن أي أدوات. يجب عليك دائمًا تعيين الأدوات بشكل منفصل عبر `tools=[]` أو `mcps=[]` أو `apps=[]`.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="ماذا يحدث إذا عيّنت نفس المهارة على كل من الوكيل والطاقم؟">
|
||||
المهارة على مستوى الوكيل لها الأولوية. يتم إزالة التكرار حسب الاسم — مهارات الوكيل تُعالج أولاً، لذا إذا ظهر نفس اسم المهارة في كلا المستويين، تُستخدم نسخة الوكيل.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="ما الحجم الأقصى لمحتوى SKILL.md؟">
|
||||
هناك تحذير ناعم عند 50,000 حرف، لكن بدون حد صارم. حافظ على تركيز المهارات وإيجازها للحصول على أفضل النتائج — الحقن الكبيرة في الإرشادات قد تُشتت انتباه الوكيل.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,49 +0,0 @@
|
||||
---
|
||||
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`، سيتم تنفيذ الطاقم للعدد المحدد من التكرارات، وستُعرض مقاييس الأداء في نهاية التشغيل.
|
||||
|
||||
سيظهر جدول الدرجات في النهاية لعرض أداء الطاقم من حيث المقاييس التالية:
|
||||
|
||||
<center>**درجات المهام (1-10 الأعلى أفضل)**</center>
|
||||
|
||||
| المهام/الطاقم/الوكلاء | التشغيل 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** | | |
|
||||
|
||||
يوضح المثال أعلاه نتائج الاختبار لتشغيلين للطاقم مع مهمتين، مع الدرجة الإجمالية المتوسطة لكل مهمة والطاقم ككل.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user