mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-07-01 13:18:10 +00:00
Merge branch 'main' into fix-skill-archive-symlink-traversal
This commit is contained in:
142
AGENTS.md
Normal file
142
AGENTS.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Docs contributor guide
|
||||
|
||||
The `docs/` directory is published at [docs.crewai.com](https://docs.crewai.com)
|
||||
by [Mintlify](https://www.mintlify.com/). Mintlify watches `docs/docs.json`
|
||||
and the MDX files referenced from it.
|
||||
|
||||
## TL;DR for editing docs
|
||||
|
||||
- Edit MDX under `docs/edge/<lang>/...` (e.g. `docs/edge/en/concepts/agents.mdx`).
|
||||
- Your change ships under the **Edge** version selector the moment it merges
|
||||
to `main`. Edge follows `main` and is the channel for unreleased work.
|
||||
- On release cut, the current Edge state is frozen into `docs/v<X.Y.Z>/` and
|
||||
that snapshot becomes the new default version in the selector (tag:
|
||||
`Latest`). Canonical URLs (`/<lang>/...`) auto-redirect to the new default.
|
||||
- Never modify files under `docs/v*/`. Those are frozen release snapshots
|
||||
and the `docs-snapshots` CI guard rejects writes. The only exception is a
|
||||
release-cut PR (auto-generated by `devtools release` or the manual
|
||||
`scripts/docs/freeze_current_edge.py` wrapper), which uses a
|
||||
`[docs-freeze]` title prefix to opt out.
|
||||
- Never delete or rename files under `docs/images/`. Images are append-only.
|
||||
See [Images](#images) below.
|
||||
|
||||
## The version model
|
||||
|
||||
The site has one rolling channel (Edge) plus one frozen snapshot per
|
||||
release.
|
||||
|
||||
```
|
||||
docs/
|
||||
edge/ <-- Edge sources (you edit here)
|
||||
en/...
|
||||
pt-BR/ ko/ ar/
|
||||
enterprise-api.*.yaml
|
||||
|
||||
v1.14.7/ <-- frozen snapshot of v1.14.7
|
||||
en/...
|
||||
pt-BR/ ko/ ar/
|
||||
enterprise-api.*.yaml
|
||||
v1.14.6/...
|
||||
...
|
||||
|
||||
images/ <-- shared, append-only
|
||||
docs.json <-- Mintlify config: navigation + redirects
|
||||
```
|
||||
|
||||
`docs/docs.json` lists one navigation block per version per language. Edge
|
||||
points at `docs/edge/<lang>/...`; every other version points at its own
|
||||
`docs/v<X.Y.Z>/<lang>/...` subtree. Mintlify scopes both the sidebar and the
|
||||
in-site search to whichever version the reader selects, so picking
|
||||
`v1.10.0` genuinely shows the v1.10.0 docs (and only those).
|
||||
|
||||
### URLs and canonical redirects
|
||||
|
||||
Each Mintlify version corresponds to its own URL prefix:
|
||||
|
||||
- Edge: `/edge/<lang>/<page>` (e.g. `/edge/en/concepts/agents`)
|
||||
- Frozen: `/v<X.Y.Z>/<lang>/<page>` (e.g. `/v1.14.7/en/concepts/agents`)
|
||||
|
||||
External links to the old, unversioned `/<lang>/<page>` URLs would 404 under
|
||||
this layout. To keep them working, `docs.json` ships wildcard redirects:
|
||||
|
||||
```jsonc
|
||||
{ "source": "/en/:slug*", "destination": "/v1.14.7/en/:slug*", "permanent": false }
|
||||
```
|
||||
|
||||
The release-cut step rewrites the destination on every release so canonical
|
||||
`/<lang>/...` URLs always resolve to the latest stable docs.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
1. **During development.** You add or edit pages under
|
||||
`docs/edge/<lang>/...` in normal PRs. They land in Edge as soon as the PR
|
||||
merges. Both `/edge/<lang>/<page>` and the version selector's `Edge` entry
|
||||
reflect the change immediately.
|
||||
2. **Release cut.** The release engineer runs `devtools release X.Y.Z`. As
|
||||
part of that flow the CLI opens a `[docs-freeze]` PR that copies Edge into
|
||||
`docs/v<X.Y.Z>/`, rewrites internal OpenAPI references, updates
|
||||
`docs/docs.json` to make `v<X.Y.Z>` the new default + `Latest`, and rewires
|
||||
the canonical-URL redirects to the new default. The PR must merge before
|
||||
the tag and PyPI publish run.
|
||||
3. **After release.** Edge keeps rolling. Patch fixes to the just-released
|
||||
docs go into Edge and ship with the next release. We do not back-edit
|
||||
frozen snapshots.
|
||||
|
||||
See [`RELEASING.md`](RELEASING.md) for the full release runbook.
|
||||
|
||||
## Images
|
||||
|
||||
Snapshots share a single `docs/images/` directory. If an image is deleted
|
||||
or renamed, every frozen snapshot that referenced it breaks. So the rule
|
||||
is:
|
||||
|
||||
- Adding new images is always fine.
|
||||
- Deleting or renaming an existing image fails CI unless the PR is a
|
||||
`[docs-freeze]` release-cut PR.
|
||||
- If an asset is wrong, add a new file with a new name and reference the
|
||||
new name in the Edge MDX (`docs/edge/<lang>/...`). Leave the old file
|
||||
alone.
|
||||
|
||||
## Local preview
|
||||
|
||||
Install the Mintlify CLI and run from `docs/`:
|
||||
|
||||
```bash
|
||||
npm i -g mintlify
|
||||
mintlify dev
|
||||
```
|
||||
|
||||
Use the version selector at the top of the rendered page to switch between
|
||||
Edge and frozen versions.
|
||||
|
||||
To check links across every version:
|
||||
|
||||
```bash
|
||||
mintlify broken-links
|
||||
```
|
||||
|
||||
CI runs the broken-links check on every PR that touches `docs/**` via
|
||||
[`.github/workflows/docs-broken-links.yml`](.github/workflows/docs-broken-links.yml).
|
||||
|
||||
## Scripts
|
||||
|
||||
- `scripts/docs/freeze_historical_versions.py` — one-time migration that
|
||||
reconstructed `docs/v1.10.0/` through `docs/v1.14.7/` from git tags. You
|
||||
should not need to run this again.
|
||||
- `scripts/docs/prefix_version_paths.py` — one-time migration that switched
|
||||
`docs/docs.json` to directory-based versioning, inserted Edge, and added
|
||||
the canonical-URL redirects. You should not need to run this again.
|
||||
- `scripts/docs/freeze_current_edge.py` — thin CLI wrapper around
|
||||
`crewai_devtools.docs_versioning.freeze`. `devtools release` calls the
|
||||
same module during its docs PR step; this script is the manual escape
|
||||
hatch (e.g. retroactively freezing a forgotten release).
|
||||
|
||||
## CI guards
|
||||
|
||||
- [`.github/workflows/docs-snapshots.yml`](.github/workflows/docs-snapshots.yml)
|
||||
enforces the two rules above (frozen snapshots immutable, images
|
||||
append-only). Both checks accept the `[docs-freeze]` PR-title escape
|
||||
hatch.
|
||||
- [`.github/workflows/docs-broken-links.yml`](.github/workflows/docs-broken-links.yml)
|
||||
runs `mintlify broken-links` against the whole site, so adding a new
|
||||
page or moving a snapshot file that breaks a link will fail CI.
|
||||
13
README.md
13
README.md
@@ -601,6 +601,19 @@ CrewAI is open-source and we welcome contributions. If you're looking to contrib
|
||||
- Send a pull request.
|
||||
- We appreciate your input!
|
||||
|
||||
### Contributing to the docs
|
||||
|
||||
The site at [docs.crewai.com](https://docs.crewai.com) is published from
|
||||
`docs/` by [Mintlify](https://www.mintlify.com/). The docs use directory-based
|
||||
versioning: edits to `docs/edge/<lang>/...` (e.g.
|
||||
`docs/edge/en/concepts/agents.mdx`) land under the **Edge** version selector
|
||||
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
|
||||
[`AGENTS.md`](AGENTS.md) for the full contributor guide and
|
||||
[`RELEASING.md`](RELEASING.md) for the release-cut runbook.
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
```bash
|
||||
|
||||
16
conftest.py
16
conftest.py
@@ -134,17 +134,21 @@ def bedrock_host_matcher(r1: Request, r2: Request) -> bool: # type: ignore[no-a
|
||||
)
|
||||
|
||||
|
||||
def _patched_make_vcr_request(httpx_request: Any, **kwargs: Any) -> Any:
|
||||
def _patched_make_vcr_request(
|
||||
httpx_request: Any, real_request_body: Any = None, **kwargs: Any
|
||||
) -> Any:
|
||||
"""Patched version of VCR's _make_vcr_request that handles binary content.
|
||||
|
||||
The original implementation fails on binary request bodies (like file uploads)
|
||||
because it assumes all content can be decoded as UTF-8.
|
||||
"""
|
||||
raw_body = httpx_request.read()
|
||||
try:
|
||||
body = raw_body.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
body = base64.b64encode(raw_body).decode("ascii")
|
||||
raw_body = real_request_body if real_request_body is not None else httpx_request.read()
|
||||
body: Any = raw_body
|
||||
if isinstance(raw_body, bytes):
|
||||
try:
|
||||
body = raw_body.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
body = base64.b64encode(raw_body).decode("ascii")
|
||||
uri = str(httpx_request.url)
|
||||
headers = dict(httpx_request.headers)
|
||||
return Request(httpx_request.method, uri, body, headers)
|
||||
|
||||
32694
docs/docs.json
32694
docs/docs.json
File diff suppressed because it is too large
Load Diff
1784
docs/edge/ar/changelog.mdx
Normal file
1784
docs/edge/ar/changelog.mdx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -959,7 +959,7 @@ source .venv/bin/activate
|
||||
بعد تفعيل البيئة الافتراضية، يمكنك تشغيل التدفق بتنفيذ أحد الأوامر التالية:
|
||||
|
||||
```bash
|
||||
crewai flow kickoff
|
||||
crewai run
|
||||
```
|
||||
|
||||
أو
|
||||
@@ -1160,10 +1160,4 @@ crewai run
|
||||
|
||||
يكتشف هذا الأمر تلقائيًا ما إذا كان مشروعك تدفقًا (بناءً على إعداد `type = "flow"` في pyproject.toml الخاص بك) ويشغّله وفقًا لذلك. هذه هي الطريقة الموصى بها لتشغيل التدفقات من سطر الأوامر.
|
||||
|
||||
للتوافق مع الإصدارات السابقة، يمكنك أيضًا استخدام:
|
||||
|
||||
```shell
|
||||
crewai flow kickoff
|
||||
```
|
||||
|
||||
ومع ذلك، فإن أمر `crewai run` هو الطريقة المفضلة الآن لأنه يعمل لكل من فرق Crew والتدفقات.
|
||||
أمر `crewai flow kickoff` القديم deprecated. استخدم `crewai run` لكل من فرق Crew والتدفقات.
|
||||
87
docs/edge/ar/enterprise/features/merged-step-card.mdx
Normal file
87
docs/edge/ar/enterprise/features/merged-step-card.mdx
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
title: بطاقة واحدة لكل خطوة
|
||||
description: "كل خطوة على لوحة Studio هي بطاقة واحدة تجمع بين المهمة والوكيل الذي ينفّذها."
|
||||
icon: "layer-group"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
{/* CLEANUP: This <Note> banner is the only time-bound content on the page. After the feature ships (Wednesday, June 24th 2026), delete the banner below — the rest of the page is evergreen present-tense docs and needs no other edits. */}
|
||||
<Note>
|
||||
**الإطلاق يوم الأربعاء 24 يونيو.** تنتقل لوحة Studio إلى بطاقة واحدة لكل خطوة بدلاً من عُقد منفصلة للمهمة والوكيل، وذلك لتبسيط اللوحة مع إضافتنا لوظائف جديدة قريبًا. تستمر أتمتتك الحالية في العمل دون أي تغييرات مطلوبة — تبقى جميع إعدادات المهمة والوكيل متاحة، ولكن منظّمة في بطاقة واحدة.
|
||||
</Note>
|
||||
|
||||
## نظرة عامة
|
||||
|
||||
على لوحة Studio، تُمثَّل كل خطوة عمل بـ **بطاقة واحدة**. تجمع البطاقة بين عنصرين كانا في السابق في عُقد منفصلة:
|
||||
|
||||
- **المهمة** — ماذا تفعل (الاسم، الوصف، المخرجات المتوقعة، وتنسيق الاستجابة).
|
||||
- **الوكيل** — من ينفّذها (الوكيل المُعيَّن ونموذجه وأدواته).
|
||||
|
||||
الوكيل ليس مشاركًا مستقلاً في سير العمل لديك — بل هو سمة من سمات المهمة: *أي وكيل ينفّذ هذا العمل.* وضع المهمة والوكيل في بطاقة واحدة يجعل هذه العلاقة واضحة، ويحوّل أتمتتك إلى سلسلة واحدة من وحدات العمل من اليسار إلى اليمين يسهل قراءتها بنظرة واحدة.
|
||||
|
||||
<Frame caption="بطاقة واحدة لكل خطوة: المهمة مع ملخص للوكيل المُعيَّن في التذييل.">
|
||||

|
||||
</Frame>
|
||||
|
||||
## على اللوحة
|
||||
|
||||
تعرض كل بطاقة مطوية ما يلي:
|
||||
|
||||
- **اسم المهمة ووصفها** في الأعلى.
|
||||
- **تذييل يلخّص الوكيل المُعيَّن** — الصورة الرمزية والاسم والنموذج والأدوات.
|
||||
|
||||
لا توجد عقدة وكيل منفصلة ولا حافة عمودية من الوكيل ← المهمة. تتصل خطواتك مباشرةً ببعضها البعض بالترتيب الذي تُنفَّذ به.
|
||||
|
||||
## في المحرّر
|
||||
|
||||
افتح بطاقة لتحريرها. العرض الموسّع هو البطاقة نفسها في حالة مفصّلة — وليس شاشة مختلفة — منظّمة في قسمين موسومين بوضوح.
|
||||
|
||||
<Frame caption="المحرّر الموسّع: قسم المهمة مفتوح، والوكيل ملخّص أسفله.">
|
||||

|
||||
</Frame>
|
||||
|
||||
### المهمة — ماذا تفعل
|
||||
|
||||
مفتوحة افتراضيًا، لأنها ما تحرّره عادةً:
|
||||
|
||||
- **الاسم**
|
||||
- **الوصف**
|
||||
- **المخرجات المتوقعة**
|
||||
- **تنسيق الاستجابة** — يظهر هنا لأنه يتحكم تحديدًا في ما تقرأه الخطوات اللاحقة (مثل التوجيه) من هذه الخطوة.
|
||||
|
||||
### الوكيل — من ينفّذها
|
||||
|
||||
يُعرض الوكيل المُعيَّن كملخّص — **الاسم والنموذج والأدوات في سطر واحد**. ويُحفَظ إعداده الأعمق خلف قسمين قابلين للطي:
|
||||
|
||||
- **الدور والهدف والخلفية**
|
||||
- **إعدادات الوكيل** — الاستدلال، الحد الأقصى لمحاولات الاستدلال، السماح بالتفويض، الحد الأقصى للتكرارات، وإعدادات LLM.
|
||||
|
||||
<Tip>
|
||||
الإعداد الكامل للوكيل — الدور، الهدف، الخلفية، النموذج، الأدوات، إعدادات LLM، وكامل كتلة إعدادات الوكيل — موجود خلف القسمين القابلين للطي **الدور والهدف والخلفية** و**إعدادات الوكيل**، منظّمًا حسب عدد مرّات تحريرك له.
|
||||
</Tip>
|
||||
|
||||
## التبديل مقابل تحرير الوكيل
|
||||
|
||||
هناك طريقتان متمايزتان للتعامل مع الوكيل في البطاقة، وكل منهما تؤدي وظيفة مختلفة:
|
||||
|
||||
- **التبديل (Swap)** يعيد تعيين *أي* وكيل ينفّذ هذه المهمة. استخدم عنصر التحكم **تبديل** لاختيار وكيل مختلف من هذا المشروع، أو اختيار واحد من مستودع الوكلاء، أو إنشاء وكيل جديد. هذا مقصور على نطاق المهمة.
|
||||
- **تحرير** الوكيل — بفتح **الدور والهدف والخلفية** أو **إعدادات الوكيل** — يغيّر الوكيل *نفسه*.
|
||||
|
||||
<Frame caption="التبديل يغيّر الوكيل الذي ينفّذ المهمة.">
|
||||

|
||||
</Frame>
|
||||
|
||||
<Warning>
|
||||
**الوكلاء قابلون لإعادة الاستخدام ومشتركون.** يمكن للوكيل نفسه تنفيذ أكثر من مهمة عبر مشروعك. تحرير دور الوكيل أو خلفيته أو إعداداته يحدّث ذلك الوكيل **في كل مكان يُستخدم فيه** — وليس فقط في البطاقة التي فتحتها. إذا أردت تطبيق تغيير على خطوة واحدة فقط، فقم **بالتبديل** إلى وكيل مختلف بدلاً من تحرير الوكيل المشترك.
|
||||
</Warning>
|
||||
|
||||
## ذات صلة
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Crew Studio" href="/ar/enterprise/features/crew-studio" icon="pencil">
|
||||
أنشئ الأتمتة بمساعدة الذكاء الاصطناعي ومحرّر مرئي.
|
||||
</Card>
|
||||
<Card title="مستودعات الوكلاء" href="/ar/enterprise/features/agent-repositories" icon="users">
|
||||
إدارة الوكلاء وإعادة استخدامهم عبر أتمتتك.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
57
docs/edge/ar/enterprise/guides/capture_telemetry_logs.mdx
Normal file
57
docs/edge/ar/enterprise/guides/capture_telemetry_logs.mdx
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
title: "تصدير OpenTelemetry"
|
||||
description: "تصدير التتبعات والسجلات من عمليات نشر CrewAI AMP إلى مجمّع OpenTelemetry الخاص بك"
|
||||
icon: "magnifying-glass-chart"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
يمكن لـ CrewAI AMP تصدير **التتبعات** و**السجلات** من OpenTelemetry من عمليات النشر مباشرة إلى مجمّعك الخاص. يتيح لك ذلك مراقبة أداء الوكلاء وتتبع استدعاءات LLM وتصحيح الأخطاء باستخدام مجموعة المراقبة الحالية.
|
||||
|
||||
تتبع بيانات القياس [اتفاقيات OpenTelemetry GenAI الدلالية](https://opentelemetry.io/docs/specs/semconv/gen-ai/) بالإضافة إلى سمات خاصة بـ CrewAI.
|
||||
|
||||
<Tip>
|
||||
تُعدّ OpenTelemetry **مسار المراقبة الموصى به** — محايدة تجاه الموردين، وتعمل مع أي خلفية متوافقة مع OTLP (Grafana, Honeycomb, NewRelic، أو مجمّعك الخاص). إذا كنت تستخدم Datadog تحديدًا، فراجع دليل [تكامل Datadog](./datadog) المخصص، الذي يغطي كلًا من مسار وكيل Datadog واستيعاب OTLP من Datadog.
|
||||
</Tip>
|
||||
|
||||
## المتطلبات المسبقة
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="حساب CrewAI AMP" icon="users">
|
||||
يجب أن يكون لدى مؤسستك حساب CrewAI AMP نشط.
|
||||
</Card>
|
||||
<Card title="مجمّع OpenTelemetry" icon="server">
|
||||
تحتاج إلى نقطة نهاية مجمّع متوافقة مع OpenTelemetry (مثل OTel Collector الخاص بك أو Datadog أو Grafana أو أي واجهة خلفية متوافقة مع OTLP).
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## إعداد مجمّع
|
||||
|
||||
1. في CrewAI AMP، انتقل إلى **Settings** > **OpenTelemetry Collectors**.
|
||||
2. انقر على **Add Collector**.
|
||||
3. اختر تكاملاً:
|
||||
- **OpenTelemetry Traces** و**OpenTelemetry Logs** — صدّر إلى أي مجمّع أو واجهة خلفية متوافقة مع OTLP.
|
||||
- **Datadog** — أرسل التتبعات مباشرة إلى استقبال OTLP الخاص بـ Datadog، دون الحاجة إلى مجمّع منفصل أو Datadog Agent.
|
||||
4. هيّئ الاتصال. تعتمد الحقول على التكامل الذي اخترته:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="OpenTelemetry Traces / Logs">
|
||||
إن **OpenTelemetry Traces** و**OpenTelemetry Logs** تكاملان منفصلان يتشاركان نفس الحقول — اختر التكامل المطابق للإشارة التي تريد تصديرها.
|
||||
|
||||
- **Endpoint** — نقطة نهاية OTLP لمجمّعك (مثل `https://otel-collector.example.com:4317`).
|
||||
- **Service Name** — اسم لتعريف هذه الخدمة في منصة المراقبة.
|
||||
- **Custom Headers** *(اختياري)* — أضف رؤوس المصادقة أو التوجيه كأزواج مفتاح-قيمة.
|
||||
- **Certificate** *(اختياري)* — قدم شهادة TLS إذا كان مجمّعك يتطلبها.
|
||||
|
||||
<Frame></Frame>
|
||||
</Tab>
|
||||
<Tab title="Datadog">
|
||||
لإعداد Datadog، راجع دليل [تكامل Datadog](./datadog) المخصص — فهو يغطي كلًا من مسار وكيل Datadog (الموصى به، أرخص لحجم السجلات الكبير) واستيعاب OTLP من Datadog، مع خطوات تهيئة كاملة للمجمّع.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
5. *(اختياري)* انقر على **Test Connection** للتحقق من قدرة CrewAI على الوصول إلى نقطة النهاية باستخدام بيانات الاعتماد التي قدمتها.
|
||||
6. انقر على **Save**.
|
||||
|
||||
<Tip>
|
||||
يمكنك إضافة مجمّعات متعددة — على سبيل المثال، واحد للتتبعات وآخر للسجلات، أو الإرسال إلى واجهات خلفية مختلفة لأغراض مختلفة.
|
||||
</Tip>
|
||||
295
docs/edge/ar/enterprise/guides/datadog.mdx
Normal file
295
docs/edge/ar/enterprise/guides/datadog.mdx
Normal file
@@ -0,0 +1,295 @@
|
||||
---
|
||||
title: "تكامل Datadog"
|
||||
description: "راقب عمليات نشر CrewAI AMP المُستضافة ذاتيًا في Datadog عبر وكيل Datadog أو استيعاب OTLP من Datadog — يوفر كلا المسارين نفس الواجهات المهيكلة لاستيراد لوحة معلومات العمليات الجاهزة."
|
||||
icon: "dog"
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Note>
|
||||
**الترجمة قيد التقدم** — يتم عرض المحتوى باللغة الإنجليزية.
|
||||
</Note>
|
||||
|
||||
CrewAI ships first-class support for Datadog: two log-ingestion paths, a JSON log schema designed for cheap indexing, and a ready-made operations dashboard you can import in under five minutes.
|
||||
|
||||
<Note>
|
||||
For vendor-neutral observability via any OTLP backend (Grafana, Honeycomb, your own collector), see [OpenTelemetry Export](./capture_telemetry_logs).
|
||||
</Note>
|
||||
|
||||
## Choose a path
|
||||
|
||||
CrewAI supports two log-ingestion paths to Datadog — both are first-class and produce the same structured facets that power the dashboard. Pick the one that fits your infrastructure.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Datadog Agent">
|
||||
The Datadog Agent runs alongside your CrewAI containers (typically as a DaemonSet on Kubernetes) and tails their stdout. With `CREWAI_LOG_FORMAT=json` set, each log event ships as a single billable line with structured attributes.
|
||||
|
||||
**Setup:**
|
||||
1. Run the Datadog Agent next to your CrewAI containers — see [Datadog's deployment docs](https://docs.datadoghq.com/agent/) for Kubernetes, ECS, or VM setup. Enable log collection (`logs_enabled: true`) and container log collection (`logs_config.container_collect_all: true`).
|
||||
2. Set `CREWAI_LOG_FORMAT=json` as an **automation environment variable** in CrewAI AMP (open your automation → **Settings → Environment Variables**) so each log event is a single line instead of a multi-line traceback. AMP propagates the value to every container in the deployment (API + workers) — don't set it on the container or host directly. See [Enabling JSON output](#enabling-json-output) below for the AMP UI walkthrough and the [log schema reference](#log-schema-reference) for the full field contract.
|
||||
3. Confirm logs arrive in Datadog Logs with the JSON fields parsed — see [Verify ingestion](#verify-ingestion).
|
||||
|
||||
**Pick this path if** you already operate Datadog Agents (e.g. for infrastructure metrics), or your log volume makes per-event ingestion cost a real concern — collapsing tracebacks into single events keeps Agent ingestion cheap at scale.
|
||||
</Tab>
|
||||
<Tab title="Datadog OTLP intake">
|
||||
CrewAI AMP exports OpenTelemetry traffic directly to Datadog's OTLP endpoint with no Agent required. Logs and traces ride a single export pipeline configured in AMP's UI, using the same protocol you'd use for any other OTLP backend.
|
||||
|
||||
**Setup:**
|
||||
1. In CrewAI AMP, go to **Settings → OpenTelemetry Collectors → Add Collector** and pick **Datadog**.
|
||||
2. Configure the connection:
|
||||
- **Datadog Site Domain** — your Datadog site's OTLP host only, no protocol or path. CrewAI builds the full HTTPS OTLP endpoint for you. Use the host that matches your [Datadog site](https://docs.datadoghq.com/getting_started/site/):
|
||||
- `otlp.datadoghq.com` (US1)
|
||||
- `otlp.us3.datadoghq.com` (US3)
|
||||
- `otlp.us5.datadoghq.com` (US5)
|
||||
- `otlp.datadoghq.eu` (EU1)
|
||||
- `otlp.ap1.datadoghq.com` (AP1)
|
||||
- **API Key** — your Datadog API key. See [how to create one](https://docs.datadoghq.com/account_management/api-app-keys/#api-keys).
|
||||
3. The Datadog template provisions **both signals at once** — when you save, AMP creates a traces collector at `/v1/traces` and a logs collector at `/v1/logs`, both sharing the same Datadog OTLP host and API key. You'll see them as two separate rows in your OTel collectors list.
|
||||
4. *(optional)* Click **Test Connection** to verify CrewAI can reach the endpoint with the credentials you provided. Then click **Save** — both collectors are created in one step.
|
||||
|
||||
<Frame></Frame>
|
||||
|
||||
**Pick this path if** you'd rather not operate a Datadog Agent, you already use OTLP for traces and want one export pipeline, or you may later want to fan out the same telemetry to other backends (Grafana, Honeycomb, etc.) without changing your application setup.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
Either path lands the same structured facets in Datadog (`@automation_id`, `@kickoff_id`, `@execution_id`, `@automation_name`, `@crewai_version`, `@exception.type`, `@gen_ai.*`), so the dashboard works identically with either choice.
|
||||
|
||||
## Log schema reference
|
||||
|
||||
<Info>
|
||||
This schema applies to the **Datadog Agent path** — stdout JSON logs produced when `CREWAI_LOG_FORMAT=json` is set. Logs delivered via the **Datadog OTLP intake** use OpenTelemetry attribute names and may differ; see [OpenTelemetry Export](./capture_telemetry_logs).
|
||||
</Info>
|
||||
|
||||
When `CREWAI_LOG_FORMAT=json` is set, every log event is emitted as a **single JSON object per line** to stdout, with internal newlines escaped. The format is plain JSON — Datadog parses it natively, and the same payload is also consumable by Splunk, Loki, Elasticsearch, and CloudWatch without custom log pipelines.
|
||||
|
||||
### Why JSON output
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Lower ingestion cost" icon="dollar-sign">
|
||||
Most managed log backends bill per event. A Python traceback in text format is counted as one event per line — 30+ events for a single error. JSON output collapses each traceback into a single event with the stack trace as an escaped string field.
|
||||
</Card>
|
||||
<Card title="Structured search" icon="magnifying-glass">
|
||||
Search by `@automation_id`, `@exception.type`, `@kickoff_id` instead of grepping free-text. Build dashboards on typed facets without parser configuration.
|
||||
</Card>
|
||||
<Card title="APM ↔ logs correlation" icon="link">
|
||||
Every event carries `trace_id` and `span_id` when fired inside a recording span, so backends auto-link logs to traces.
|
||||
</Card>
|
||||
<Card title="Stable contract" icon="file-shield">
|
||||
The `schema` field gates compatibility — within `v1`, fields are added but never renamed or removed.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
### Enabling JSON output
|
||||
|
||||
`CREWAI_LOG_FORMAT=json` must be set as an **automation environment variable** in CrewAI AMP — it is **not** a container, host, or Docker setting. Open your automation in AMP, click the **Settings** icon, and add the variable under the **Environment Variables** section. AMP applies the value to every container in the deployment (API + workers) on the next restart. See [Update Your Crew](./update-crew) for the full UI walkthrough with screenshots.
|
||||
|
||||
```shell
|
||||
CREWAI_LOG_FORMAT=json
|
||||
```
|
||||
|
||||
Restart the deployment to pick up the change. Every log line on stdout from that point on is a single JSON object.
|
||||
|
||||
<Note>
|
||||
The default value is `text`, which preserves the legacy human-readable line format byte-for-byte. Setting any value other than `json` falls back to text mode. There is no migration step — the variable is read at process start and the format switches immediately.
|
||||
</Note>
|
||||
|
||||
### Example events
|
||||
|
||||
A single info-level log inside an active automation kickoff:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "v1",
|
||||
"ts": "2026-06-17T16:14:23.482914Z",
|
||||
"level": "INFO",
|
||||
"logger": "crewai_enterprise.utilities.pii_redaction",
|
||||
"crewai_version": "1.14.7",
|
||||
"msg": "PII tracking state reset (engines preserved)",
|
||||
"automation_id": "12",
|
||||
"task_id": "0843a930-b306-464b-89c8-bfafa78cc711",
|
||||
"kickoff_id": "0843a930-b306-464b-89c8-bfafa78cc711",
|
||||
"execution_id": "0843a930-b306-464b-89c8-bfafa78cc711",
|
||||
"automation_name": "research_flow"
|
||||
}
|
||||
```
|
||||
|
||||
An error with a Python exception is collapsed into a single event with the traceback as a string:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema": "v1",
|
||||
"ts": "2026-06-17T16:14:31.218450Z",
|
||||
"level": "ERROR",
|
||||
"logger": "api.tasks.flow_run_task",
|
||||
"crewai_version": "1.14.7",
|
||||
"msg": "Flow execution failed",
|
||||
"automation_id": "12",
|
||||
"kickoff_id": "0843a930-b306-464b-89c8-bfafa78cc711",
|
||||
"execution_id": "0843a930-b306-464b-89c8-bfafa78cc711",
|
||||
"automation_name": "research_flow",
|
||||
"exception": {
|
||||
"type": "ValueError",
|
||||
"message": "Topic cannot be empty",
|
||||
"stacktrace": "Traceback (most recent call last):\n File \"/app/flow.py\", line 42, in summarize\n ...\nValueError: Topic cannot be empty\n"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The same error in legacy text mode would have produced ~25 separate log events (one per traceback line) — all of which the backend would bill and index individually.
|
||||
|
||||
### Schema v1 fields
|
||||
|
||||
Within the `v1` schema, fields are only added, never renamed or removed. New fields will appear as soon as a deployment is upgraded.
|
||||
|
||||
| Field | Type | Always present | Source |
|
||||
|-------|------|----------------|--------|
|
||||
| `schema` | string | Yes | Constant `"v1"`. Increment indicates a breaking schema change. |
|
||||
| `ts` | string (ISO-8601 UTC, microseconds) | Yes | Record creation time, e.g. `2026-06-17T16:14:23.482914Z`. |
|
||||
| `level` | string | Yes | Python log level name: `DEBUG` / `INFO` / `WARNING` / `ERROR` / `CRITICAL`. |
|
||||
| `logger` | string | Yes | Dotted logger name, e.g. `api.tasks.flow_run_task`. |
|
||||
| `crewai_version` | string | Yes (when `crewai` package metadata is resolvable) | Installed `crewai` package version, e.g. `"1.14.7"`. |
|
||||
| `msg` | string | Yes | Rendered log message (after `%`-formatting / `{}`-formatting). |
|
||||
| `automation_id` | string | When `CREWAI_PLUS_ID` env var is set | Numeric deployment ID (AMP provisions this on every container). |
|
||||
| `task_id` | string | On Celery worker logs | Celery task UUID, or `"no-task"` for non-task contexts. |
|
||||
| `kickoff_id` | string | Inside an automation kickoff | UUID of the current kickoff. |
|
||||
| `execution_id` | string | Inside an automation kickoff | UUID of the current sub-execution. Equal to `kickoff_id` at the top level; differs for nested flow methods that spawn sub-executions. |
|
||||
| `automation_name` | string | Inside an automation kickoff | Human-readable automation/flow name, e.g. `"research_flow"`. |
|
||||
| `trace_id` | string (32-hex) | Inside a recording OpenTelemetry span | Hex trace ID. Omitted when no span is active. |
|
||||
| `span_id` | string (16-hex) | Inside a recording OpenTelemetry span | Hex span ID. Omitted when no span is active. |
|
||||
| `exception` | object | When the log record has `exc_info` | `{type, message, stacktrace}` — full traceback as a single escaped string. |
|
||||
|
||||
<Tip>
|
||||
Any additional `extra={...}` kwargs passed to a logger call appear as top-level JSON fields verbatim. Reserved field names above always win to keep the schema stable.
|
||||
</Tip>
|
||||
|
||||
### Stability promise
|
||||
|
||||
The `schema` field declares the contract. Within `v1`, CrewAI commits to:
|
||||
|
||||
- **Never removing a field** that customers may have built queries or dashboards against.
|
||||
- **Never renaming a field** in place — renames happen via a schema bump (e.g. `v2`), with the old name kept as a deprecated alias for at least one release cycle.
|
||||
- **Adding new fields** at any time. Consumers should ignore unknown top-level keys.
|
||||
|
||||
When a `v2` is introduced, both the `schema` field and the migration guide will be published in advance, and `v1` will continue to be emitted for one release cycle so dashboards and queries have time to migrate.
|
||||
|
||||
## Prerequisite: promote facets
|
||||
|
||||
Datadog auto-discovers fields the first time it sees them but doesn't make them queryable in widgets until they're promoted to **facets**. This is a one-time setup in your Datadog account.
|
||||
|
||||
<Steps>
|
||||
<Step title="Search for a CrewAI log">
|
||||
Open [Logs Explorer](https://app.datadoghq.com/logs) and search `service:crewai*`. You should see at least one log event.
|
||||
</Step>
|
||||
<Step title="Promote each field">
|
||||
Click any log entry to open the right-hand details panel. For each field below, hover the field name → click the gear icon → **Create facet**.
|
||||
|
||||
- `automation_id`, `automation_name`, `execution_id`, `kickoff_id`, `task_id`
|
||||
- `crewai_version`, `model_id`
|
||||
- `exception.type`, `exception.message`
|
||||
|
||||
Skip any field that already shows a star icon next to its name — that means it's already a facet. The `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, and `gen_ai.request.model` facets are typically promoted automatically by Datadog's LLM Observability auto-discovery, but verify they exist before importing the dashboard.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Import the dashboard
|
||||
|
||||
<Steps>
|
||||
<Step title="Download the dashboard JSON">
|
||||
Save [`datadog_dashboard.json`](https://raw.githubusercontent.com/crewAIInc/crewAI/main/docs/edge/en/enterprise/guides/datadog_dashboard.json) to your machine.
|
||||
</Step>
|
||||
<Step title="Open the import dialog in Datadog">
|
||||
Navigate to **Dashboards → New Dashboard**. Click the **gear icon** in the top right of the empty dashboard and select **Import Dashboard JSON**.
|
||||
</Step>
|
||||
<Step title="Paste or upload the JSON">
|
||||
Paste the contents of `datadog_dashboard.json` into the import dialog (or drag the file in). Click **Import**.
|
||||
|
||||
Datadog creates the dashboard immediately and lands you on it. The first load may show empty widgets for a few seconds while queries execute against the time range.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Tip>
|
||||
Datadog's [Dashboard API](https://docs.datadoghq.com/api/latest/dashboards/#create-a-new-dashboard) accepts the same JSON via `POST /api/v1/dashboard`. Use it if you manage dashboards through Terraform, Pulumi, or CI.
|
||||
</Tip>
|
||||
|
||||
## What you get
|
||||
|
||||
The dashboard is organized into four sections plus a placeholder for a custom drill-down widget:
|
||||
|
||||
| Section | Widgets | Useful for |
|
||||
|---------|---------|------------|
|
||||
| **Header** | Total Executions · Error Rate (%) · Active Automations · CrewAI Versions in Use | At-a-glance health for the last hour. Error Rate is conditionally formatted (green ≤ 5%, yellow ≤ 10%, red > 10%). |
|
||||
| **Throughput** | Executions per Hour by Automation (top 10, stacked bars) | Spotting traffic shifts, surfacing busy automations, validating that a rollout didn't change baseline volume. |
|
||||
| **Errors** | Errors by Exception Type (top 5, stacked bars) · Top Exception Types by Count (toplist) | Triaging failures — which exception types are spiking, which automations they're hitting. |
|
||||
| **Cost** | Total Tokens per Hour by Model (input + output, stacked area) | Tracking LLM token spend by model. Useful for catching cost regressions when an automation switches model or starts looping. |
|
||||
| **Drill-Down** | _(empty placeholder)_ | See [Customization](#customize) for adding a recent-errors log stream here. |
|
||||
|
||||
Three template variables at the top of the dashboard re-scope every widget at once:
|
||||
|
||||
- **`$automation`** — filter to a single automation by name.
|
||||
- **`$version`** — filter to a single `crewai` SDK version (useful for comparing pre- and post-upgrade behavior).
|
||||
- **`$service`** — filter to a specific Datadog `service` tag (useful when multiple CrewAI deployments share one Datadog account).
|
||||
|
||||
## Verify ingestion
|
||||
|
||||
Open [Logs Explorer](https://app.datadoghq.com/logs) and run a query that matches your ingestion path:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Datadog Agent">
|
||||
Search `service:crewai* @schema:v1`. You should see structured logs with the JSON fields parsed into Datadog facets. Pick a recent event and verify it has `@automation_id`, `@kickoff_id`, `@execution_id`, `@crewai_version`, and (when running inside a span) `@trace_id` / `@span_id` populated.
|
||||
|
||||
If nothing appears, confirm `CREWAI_LOG_FORMAT=json` is set under your automation's **Environment Variables** in AMP, the deployment was restarted after the change, and the Datadog Agent is tailing container stdout.
|
||||
</Tab>
|
||||
<Tab title="Datadog OTLP intake">
|
||||
Search `source:otlp service:crewai*`. OTLP attributes land with their OpenTelemetry names (`automation_id`, `crewai.kickoff.id`, etc.) rather than the stdout JSON keys, but they map to the same dashboard facets after [facet promotion](#prerequisite-promote-facets).
|
||||
|
||||
If nothing appears, verify the collector endpoint is correct (`/v1/logs` for logs, `/v1/traces` for traces) and **Test Connection** succeeded when the collector was saved.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Customize
|
||||
|
||||
The dashboard ships with deliberate gaps so you can extend it without uninstalling and re-importing.
|
||||
|
||||
### Add a Recent Errors log stream
|
||||
|
||||
The **Drill-Down** section is intentionally empty. Add a Log Stream widget to it for an inline view of recent failures:
|
||||
|
||||
1. Edit the dashboard and click **+ Add Widgets** inside the Drill-Down group.
|
||||
2. Drag in a **Log Stream** widget.
|
||||
3. Set the filter query to `status:error $automation $version $service`.
|
||||
4. Choose columns: `@timestamp`, `@automation_name`, `@exception.type`, `@exception.message`, `@execution_id`.
|
||||
5. Sort by most recent, limit to 25 entries.
|
||||
|
||||
Clicking any row jumps to Logs Explorer with the same filter pre-applied.
|
||||
|
||||
### Add p95 latency
|
||||
|
||||
Logs don't include execution duration by default. Two ways to add a latency widget:
|
||||
|
||||
- **From APM traces** — if you also export OTLP traces to Datadog, add a Timeseries widget with data source **Traces**, query `service:crewai*`, aggregation `p95 of @duration`. Datadog APM auto-tracks span duration.
|
||||
- **From metric extraction** — extract a `flow.duration_ms` metric from logs via [Datadog's log-to-metric pipeline](https://docs.datadoghq.com/logs/log_configuration/logs_to_metrics/), then chart it like any other metric. Useful if you don't run APM.
|
||||
|
||||
### Re-scope to multiple deployments
|
||||
|
||||
The `$service` template variable defaults to `*` and will catch every CrewAI deployment in your Datadog account. Change the default to a specific service name in **Configure → Template Variables** if you want the dashboard to focus on one deployment by default.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Likely cause | Fix |
|
||||
|---------|--------------|-----|
|
||||
| All widgets show "No data" | Facets aren't promoted | Re-do the [Promote facets](#prerequisite-promote-facets) step. Datadog won't query against an un-promoted field. |
|
||||
| Error Rate widget shows `NaN` | No executions in the time window | Either no traffic, or `@execution_id` isn't faceted. Expand the time range and re-check facets. |
|
||||
| Throughput chart is flat at the same value | Logs aren't reaching Datadog | Search `service:crewai*` in Logs Explorer. If nothing shows, verify the Datadog Agent is running (Agent path) or the OTel collector endpoint is correct (OTLP path). |
|
||||
| `crewai_version` shows fewer values than expected | Some containers predate the structured-logs work | The `crewai_version` field was added alongside JSON output. Older deployments running text mode (or older AMP builds) won't emit it. Upgrade those deployments to pick up the field. See the [log schema reference](#log-schema-reference) for the full field contract. |
|
||||
| Template variables don't filter widgets | The widget's filter line doesn't reference the template variable | Edit the widget and confirm the search includes `$automation $version $service`. |
|
||||
|
||||
## Next steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="OpenTelemetry Export" icon="magnifying-glass-chart" href="./capture_telemetry_logs">
|
||||
Vendor-neutral observability for non-Datadog stacks (Grafana, Honeycomb, your own collector) — or as a Datadog complement when you want to fan out telemetry to multiple backends.
|
||||
</Card>
|
||||
<Card title="Datadog Log Search Syntax" icon="magnifying-glass" href="https://docs.datadoghq.com/logs/explorer/search_syntax/">
|
||||
Reference for customizing widget queries against the structured facets above.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user