{
  "schemaVersion": "1.0",
  "title": "Run a CrewAI crew and stream events",
  "description": "Use this guide to execute one admitted CrewAI crew, render its ordered progress, and reach a verified terminal result. The same flow recovers after an application disconnect without starting a second crew run.",
  "canonical": "https://getaip.org/docs/connectors/crewai/guides/run-a-crew-and-stream-events",
  "route": "/docs/connectors/crewai/guides/run-a-crew-and-stream-events",
  "source": "docs/connectors/crewai/guides/run-a-crew-and-stream-events.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/crewai/guides/run-a-crew-and-stream-events.md",
    "txt": "/docs/download/connectors/crewai/guides/run-a-crew-and-stream-events.txt",
    "json": "/docs/download/connectors/crewai/guides/run-a-crew-and-stream-events.json",
    "pdf": "/docs/download/connectors/crewai/guides/run-a-crew-and-stream-events.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Run a CrewAI crew and stream events\ndescription: >-\n  Submit one admitted crew run, follow durable chunks, resume sidecar events,\n  and settle completion or cancellation without duplicating work\nkind: how-to\naudience: application-developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: crewai\ncapabilityIds:\n  - cap:crewai:<crew_id>\n  - cap:crewai:<crew_id>:status\n  - cap:crewai:<crew_id>:events\n  - cap:crewai:<crew_id>:cancel\n---\n\n# Run a CrewAI crew and stream events\n\nUse this guide to execute one admitted CrewAI crew, render its ordered progress,\nand reach a verified terminal result. The same flow recovers after an\napplication disconnect without starting a second crew run.\n\nA delivery stream does not own execution. Preserve the original AIP Action ID\nand read durable state before deciding whether any new mutation is necessary.\n\n## Before you begin\n\nObtain these values from the authorized tenant context:\n\n- one discovered `cap:crewai:<crew_id>` capability;\n- the admitted host, sidecar, registry, and crew revisions;\n- one immutable input object of at most 1 MiB;\n- one unique AIP Action ID and tenant-scoped idempotency key;\n- approval authority for the reviewed model, tool, data, and network effects;\n- a durable application record for event progress and terminal evidence.\n\nConfirm that the host is ready. Readiness proves authenticated access to a\ndurable sidecar exposing the admitted crew and operations. It does not execute\nthe crew or validate its external providers.\n\n## 1. Discover the exact capability\n\nUse authenticated discovery under the intended tenant. Select the base\ncapability whose binding metadata contains the reviewed crew ID and CrewAI\nupstream revision.\n\nThe run ID has no `:run` suffix:\n\n```text\ncap:crewai:support-primary\n```\n\nStop if discovery contains an unexpected crew, connector instance, artifact,\ntenant, or operation set. Do not construct a replacement ID from a Python\nregistry key or sidecar address.\n\n## 2. Freeze one execution intent\n\nAllocate the Action ID and key before dispatch:\n\n```sh\nexport AIP_CAPABILITY_ID='cap:crewai:support-primary'\nexport AIP_ACTION_ID='act_crewai_support_001'\nexport AIP_IDEMPOTENCY_KEY='crewai-support-001-v1'\n```\n\nKeep these values with:\n\n- tenant and authenticated principal;\n- complete input digest;\n- crew and registry revisions;\n- model, tool, memory, and knowledge dependency identities;\n- expected timeout and cost envelope;\n- approval record and policy hash.\n\nNever change input or key while retaining the Action ID. The sidecar hashes all\nof that material and rejects a conflicting reuse.\n\n## 3. Prepare bounded input\n\nWrite only crew kickoff fields to `run-input.json`:\n\n```json\n{\n  \"case_id\": \"CASE-1042\",\n  \"objective\": \"Prepare a reviewed incident summary\",\n  \"constraints\": {\n    \"max_findings\": 5,\n    \"include_personal_data\": false\n  }\n}\n```\n\nThe input permits at most 512 top-level properties and 1 MiB of encoded JSON.\nIt cannot select the crew, Python registry, sidecar, provider origin, or\ncredential.\n\nValidate deployment-owned model and tool inputs before approval. A valid JSON\nshape does not make tool execution or generated content trustworthy.\n\n## 4. Submit the stable Action\n\nUse the normal native AIP route, not the private sidecar API:\n\n```sh\ncargo run --locked -p aipctl -- \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action call \"$AIP_URL\" \\\n  \"$AIP_CAPABILITY_ID\" \\\n  --action-id \"$AIP_ACTION_ID\" \\\n  --idempotency-key \"$AIP_IDEMPOTENCY_KEY\" \\\n  --input @run-input.json\n```\n\nExpected first state is either pending approval or a terminal policy denial.\nThe connector contract requires tenant-policy approval for run.\n\nPersist the response before continuing. Do not create another Action while the\nfirst intent is pending.\n\n## 5. Approve the immutable request\n\nReview the pending Action and confirm:\n\n1. capability, crew, tenant, instance, and artifact are expected;\n2. input digest matches `run-input.json`;\n3. model, tool, storage, and network authorities are within policy;\n4. sensitive input and output handling is defined;\n5. timeout, token, provider, and tool budgets are acceptable;\n6. the same Action ID and key will resume after approval.\n\nSubmit one signed approval decision through the tenant's authorized path.\nApproval evidence contains the reason, input snapshot, and policy decision.\n\nAn approval authorizes this Action. It does not make CrewAI or external tool\neffects retry-safe.\n\n## 6. Follow durable AIP events\n\nFollow the original Action from a separate consumer:\n\n```sh\ncargo run --locked -p aipctl -- \\\n  --native-bearer-token-file \"$AIP_TOKEN_FILE\" \\\n  action events \"$AIP_URL\" \\\n  \"$AIP_ACTION_ID\" \\\n  --include-chunks \\\n  --follow\n```\n\nThe equivalent native route is:\n\n```text\nGET /aip/v1/actions/{action_id}/events?include_chunks=true&follow=true\n```\n\nPersist the application consumer position only after applying an event. A\nclosed follow connection is a delivery interruption, not proof that the\nAction stopped.\n\nReconnect with the same Action ID and the last confirmed AIP event position.\nDo not resubmit run to recreate a display stream.\n\n## 7. Decode CrewAI chunks\n\nThe sidecar normally emits `started`, zero or more `chunk` records, and one\nterminal `completed`, `failed`, or `cancelled` record. A factory failure can\nreach `failed` before `started`.\n\nEvery stored record carries a zero-based provider sequence and JSON data.\n\nThe connector maps chunks as follows:\n\n| Sidecar event | Channel | AIP chunk kind | Application action |\n|---|---|---|---|\n| `started` | Any | Progress | Mark the job admitted and executing |\n| `chunk` | `tools` | Tool | Update the correlated tool activity |\n| `chunk` | `llm` or `messages` | Data | Append structured output data |\n| `chunk` | Other or absent | Progress | Update non-terminal progress |\n| `completed` | Any | Done | Candidate terminal success |\n| `failed` | Any | Error | Preserve available failure details and classify uncertainty |\n| `cancelled` | Any | Done | Preserve the sidecar cancellation record |\n\nWhen event data contains non-empty `content` or `data.chunk`, the connector can\nalso project a text message part. Use structured event data for tool and model\nidentity instead of merging every part into one string.\n\nThe Rust connector requires strict provider sequence. It rejects malformed\nUTF-8, invalid JSON, a missing sequence, gaps, oversized frames, excessive\nevents, and streams that close without a terminal event.\n\nThe pinned parser checks its 1 MiB buffer before extracting delimited frames.\nA coalesced transport chunk can fail that check even when its individual\nframes are smaller.\n\n## 8. Keep the two cursor domains separate\n\nThe application can observe two durable event surfaces:\n\n| Cursor domain | Owner | Purpose |\n|---|---|---|\n| AIP Action event position | AIP runtime | Resume delivery of Action state and `StreamChunk` records |\n| CrewAI job cursor | Sidecar journal | Replay sidecar `started`, `chunk`, and terminal events |\n\nThe numbers can differ because AIP records approval, lifecycle, and result\nevents in addition to connector chunks.\n\nNever pass an AIP follow position as the `cursor` input to the CrewAI events\ncapability. Store both with explicit names.\n\n## 9. Replay sidecar events after interruption\n\nUse a new read Action against:\n\n```text\ncap:crewai:support-primary:events\n```\n\nTarget the original run and the last processed sidecar position:\n\n```json\n{\n  \"run_action_id\": \"act_crewai_support_001\",\n  \"cursor\": 4\n}\n```\n\nA blocking read returns the requested events and `next_cursor`. A typed stream\nwaits for later events until the target job is terminal.\n\nAdvance the saved sidecar cursor to `next_cursor` only after processing the\ncomplete slice. Repeating the read is retry-safe.\n\nA cursor beyond the current event count is rejected. Return to the last\nconfirmed cursor instead of guessing a later value.\n\n## 10. Read status independently\n\nUse a separate read Action against:\n\n```text\ncap:crewai:support-primary:status\n```\n\nIts input contains the original Action ID:\n\n```json\n{\n  \"run_action_id\": \"act_crewai_support_001\"\n}\n```\n\nStatus reports crew, operation, state, event count, and completed output when\navailable. It is the concise durable view; events explain how that state was\nreached.\n\nAfter a disconnect, read both AIP Action state and sidecar status. A mismatch\nrequires reconciliation rather than a replacement run.\n\n## 11. Settle a completed result\n\nAccept success only after retaining:\n\n1. the final AIP `ActionResult` with `completed` status;\n2. the sidecar terminal `completed` event for the same original Action ID;\n3. the serialized CrewAI output within the expected schema and data policy;\n4. required evidence for every tool or external provider effect;\n5. the final AIP and sidecar consumer positions.\n\nA Done chunk is not the final AIP result. A text fragment is not proof that\ntools completed or that output validation passed.\n\nThe final output can contain confidential or personal data. Redact general\nlogs and retain raw evidence only in an authorized store.\n\n## 12. Request cancellation when required\n\nUse the explicit cancel capability with a new Action and key:\n\n```json\n{\n  \"run_action_id\": \"act_crewai_support_001\",\n  \"reason\": \"Operator stopped the approved run\"\n}\n```\n\nThe cancel Action requires its own approval. The sidecar closes the streaming\nobject when supported, cancels its asyncio task, and persists a terminal\n`cancelled` record.\n\nObserve status and events after the request. Confirmed sidecar cancellation\nacknowledges that route and record transition. It does not prove provider\ntermination or rollback of earlier model and tool effects.\n\nIf streaming validation fails after admission, the connector also attempts\nremote cancellation. Failure to confirm that attempt becomes an unconfirmed\ncancellation.\n\n## 13. Recover an uncertain outcome\n\n| Observation | Decision |\n|---|---|\n| AIP follow connection closed | Reconnect to the original Action event stream |\n| Sidecar stream closed without terminal event | Read status and replay events from the saved sidecar cursor |\n| Run remains `running` | Continue observation or submit a governed cancel Action |\n| Run fails after provider work starts | Reconcile every possible model and tool effect, even when the event has no uncertainty field |\n| Run is `cancelled` | Verify completed effects separately; no rollback is implied |\n| Sidecar restarted during run | Treat the restored failed record as uncertain and do not rerun automatically |\n| Original job is absent | Check crew, instance, journal ownership, retention, and Action ID |\n| Repeated start conflicts | Restore the exact original input and key; do not change the request |\n\nCreate a new run only when the original intent is terminal, its external effects\nare understood, and policy authorizes another distinct intent.\n\n## Completion checklist\n\n- The capability came from authenticated tenant discovery.\n- One Action ID and key represented the complete run intent.\n- Approval covered crew, input, models, tools, data, and budgets.\n- AIP and sidecar cursor positions were stored separately.\n- Every stream sequence was processed once at the application boundary.\n- Final AIP result and sidecar terminal state agreed.\n- Cancellation claims distinguished stopped execution from prior effects.\n- Uncertain effects were reconciled before any new mutation.\n\n## Related documentation\n\n- [CrewAI run lifecycle and replay reference](../capabilities/run-lifecycle-and-replay.md)\n- [CrewAI capability index](../capabilities/README.md)\n- [Run the CrewAI quickstart](../getting-started/quickstart.md)\n- [Use native AIP](../../../guides/use-native-aip.md)\n- [Errors and retry decisions](../../../reference/errors.md)\n",
    "text": "Run a CrewAI crew and stream events\n\nUse this guide to execute one admitted CrewAI crew, render its ordered progress,\nand reach a verified terminal result. The same flow recovers after an\napplication disconnect without starting a second crew run.\n\nA delivery stream does not own execution. Preserve the original AIP Action ID\nand read durable state before deciding whether any new mutation is necessary.\n\nBefore you begin\n\nObtain these values from the authorized tenant context:\n• one discovered cap:crewai: capability;\n• the admitted host, sidecar, registry, and crew revisions;\n• one immutable input object of at most 1 MiB;\n• one unique AIP Action ID and tenant-scoped idempotency key;\n• approval authority for the reviewed model, tool, data, and network effects;\n• a durable application record for event progress and terminal evidence.\n\nConfirm that the host is ready. Readiness proves authenticated access to a\ndurable sidecar exposing the admitted crew and operations. It does not execute\nthe crew or validate its external providers.\n1. Discover the exact capability\n\nUse authenticated discovery under the intended tenant. Select the base\ncapability whose binding metadata contains the reviewed crew ID and CrewAI\nupstream revision.\n\nThe run ID has no :run suffix:\n\ncap:crewai:support-primary\n\nStop if discovery contains an unexpected crew, connector instance, artifact,\ntenant, or operation set. Do not construct a replacement ID from a Python\nregistry key or sidecar address.\n2. Freeze one execution intent\n\nAllocate the Action ID and key before dispatch:\n\nexport AIPCAPABILITYID='cap:crewai:support-primary'\nexport AIPACTIONID='actcrewaisupport001'\nexport AIPIDEMPOTENCYKEY='crewai-support-001-v1'\n\nKeep these values with:\n• tenant and authenticated principal;\n• complete input digest;\n• crew and registry revisions;\n• model, tool, memory, and knowledge dependency identities;\n• expected timeout and cost envelope;\n• approval record and policy hash.\n\nNever change input or key while retaining the Action ID. The sidecar hashes all\nof that material and rejects a conflicting reuse.\n3. Prepare bounded input\n\nWrite only crew kickoff fields to run-input.json:\n\n{\n  \"caseid\": \"CASE-1042\",\n  \"objective\": \"Prepare a reviewed incident summary\",\n  \"constraints\": {\n    \"maxfindings\": 5,\n    \"includepersonaldata\": false\n  }\n}\n\nThe input permits at most 512 top-level properties and 1 MiB of encoded JSON.\nIt cannot select the crew, Python registry, sidecar, provider origin, or\ncredential.\n\nValidate deployment-owned model and tool inputs before approval. A valid JSON\nshape does not make tool execution or generated content trustworthy.\n4. Submit the stable Action\n\nUse the normal native AIP route, not the private sidecar API:\n\ncargo run --locked -p aipctl -- \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action call \"$AIPURL\" \\\n  \"$AIPCAPABILITYID\" \\\n  --action-id \"$AIPACTIONID\" \\\n  --idempotency-key \"$AIPIDEMPOTENCYKEY\" \\\n  --input @run-input.json\n\nExpected first state is either pending approval or a terminal policy denial.\nThe connector contract requires tenant-policy approval for run.\n\nPersist the response before continuing. Do not create another Action while the\nfirst intent is pending.\n5. Approve the immutable request\n\nReview the pending Action and confirm:\n1. capability, crew, tenant, instance, and artifact are expected;\n2. input digest matches run-input.json;\n3. model, tool, storage, and network authorities are within policy;\n4. sensitive input and output handling is defined;\n5. timeout, token, provider, and tool budgets are acceptable;\n6. the same Action ID and key will resume after approval.\n\nSubmit one signed approval decision through the tenant's authorized path.\nApproval evidence contains the reason, input snapshot, and policy decision.\n\nAn approval authorizes this Action. It does not make CrewAI or external tool\neffects retry-safe.\n6. Follow durable AIP events\n\nFollow the original Action from a separate consumer:\n\ncargo run --locked -p aipctl -- \\\n  --native-bearer-token-file \"$AIPTOKENFILE\" \\\n  action events \"$AIPURL\" \\\n  \"$AIPACTIONID\" \\\n  --include-chunks \\\n  --follow\n\nThe equivalent native route is:\n\nGET /aip/v1/actions/{actionid}/events?includechunks=true&follow=true\n\nPersist the application consumer position only after applying an event. A\nclosed follow connection is a delivery interruption, not proof that the\nAction stopped.\n\nReconnect with the same Action ID and the last confirmed AIP event position.\nDo not resubmit run to recreate a display stream.\n7. Decode CrewAI chunks\n\nThe sidecar normally emits started, zero or more chunk records, and one\nterminal completed, failed, or cancelled record. A factory failure can\nreach failed before started.\n\nEvery stored record carries a zero-based provider sequence and JSON data.\n\nThe connector maps chunks as follows:\n\n| Sidecar event | Channel | AIP chunk kind | Application action |\n\n| started | Any | Progress | Mark the job admitted and executing |\n| chunk | tools | Tool | Update the correlated tool activity |\n| chunk | llm or messages | Data | Append structured output data |\n| chunk | Other or absent | Progress | Update non-terminal progress |\n| completed | Any | Done | Candidate terminal success |\n| failed | Any | Error | Preserve available failure details and classify uncertainty |\n| cancelled | Any | Done | Preserve the sidecar cancellation record |\n\nWhen event data contains non-empty content or data.chunk, the connector can\nalso project a text message part. Use structured event data for tool and model\nidentity instead of merging every part into one string.\n\nThe Rust connector requires strict provider sequence. It rejects malformed\nUTF-8, invalid JSON, a missing sequence, gaps, oversized frames, excessive\nevents, and streams that close without a terminal event.\n\nThe pinned parser checks its 1 MiB buffer before extracting delimited frames.\nA coalesced transport chunk can fail that check even when its individual\nframes are smaller.\n8. Keep the two cursor domains separate\n\nThe application can observe two durable event surfaces:\n\n| Cursor domain | Owner | Purpose |\n\n| AIP Action event position | AIP runtime | Resume delivery of Action state and StreamChunk records |\n| CrewAI job cursor | Sidecar journal | Replay sidecar started, chunk, and terminal events |\n\nThe numbers can differ because AIP records approval, lifecycle, and result\nevents in addition to connector chunks.\n\nNever pass an AIP follow position as the cursor input to the CrewAI events\ncapability. Store both with explicit names.\n9. Replay sidecar events after interruption\n\nUse a new read Action against:\n\ncap:crewai:support-primary:events\n\nTarget the original run and the last processed sidecar position:\n\n{\n  \"runactionid\": \"actcrewaisupport001\",\n  \"cursor\": 4\n}\n\nA blocking read returns the requested events and nextcursor. A typed stream\nwaits for later events until the target job is terminal.\n\nAdvance the saved sidecar cursor to nextcursor only after processing the\ncomplete slice. Repeating the read is retry-safe.\n\nA cursor beyond the current event count is rejected. Return to the last\nconfirmed cursor instead of guessing a later value.\n10. Read status independently\n\nUse a separate read Action against:\n\ncap:crewai:support-primary:status\n\nIts input contains the original Action ID:\n\n{\n  \"runactionid\": \"actcrewaisupport001\"\n}\n\nStatus reports crew, operation, state, event count, and completed output when\navailable. It is the concise durable view; events explain how that state was\nreached.\n\nAfter a disconnect, read both AIP Action state and sidecar status. A mismatch\nrequires reconciliation rather than a replacement run.\n11. Settle a completed result\n\nAccept success only after retaining:\n1. the final AIP ActionResult with completed status;\n2. the sidecar terminal completed event for the same original Action ID;\n3. the serialized CrewAI output within the expected schema and data policy;\n4. required evidence for every tool or external provider effect;\n5. the final AIP and sidecar consumer positions.\n\nA Done chunk is not the final AIP result. A text fragment is not proof that\ntools completed or that output validation passed.\n\nThe final output can contain confidential or personal data. Redact general\nlogs and retain raw evidence only in an authorized store.\n12. Request cancellation when required\n\nUse the explicit cancel capability with a new Action and key:\n\n{\n  \"runactionid\": \"actcrewaisupport001\",\n  \"reason\": \"Operator stopped the approved run\"\n}\n\nThe cancel Action requires its own approval. The sidecar closes the streaming\nobject when supported, cancels its asyncio task, and persists a terminal\ncancelled record.\n\nObserve status and events after the request. Confirmed sidecar cancellation\nacknowledges that route and record transition. It does not prove provider\ntermination or rollback of earlier model and tool effects.\n\nIf streaming validation fails after admission, the connector also attempts\nremote cancellation. Failure to confirm that attempt becomes an unconfirmed\ncancellation.\n13. Recover an uncertain outcome\n\n| Observation | Decision |\n\n| AIP follow connection closed | Reconnect to the original Action event stream |\n| Sidecar stream closed without terminal event | Read status and replay events from the saved sidecar cursor |\n| Run remains running | Continue observation or submit a governed cancel Action |\n| Run fails after provider work starts | Reconcile every possible model and tool effect, even when the event has no uncertainty field |\n| Run is cancelled | Verify completed effects separately; no rollback is implied |\n| Sidecar restarted during run | Treat the restored failed record as uncertain and do not rerun automatically |\n| Original job is absent | Check crew, instance, journal ownership, retention, and Action ID |\n| Repeated start conflicts | Restore the exact original input and key; do not change the request |\n\nCreate a new run only when the original intent is terminal, its external effects\nare understood, and policy authorizes another distinct intent.\n\nCompletion checklist\n• The capability came from authenticated tenant discovery.\n• One Action ID and key represented the complete run intent.\n• Approval covered crew, input, models, tools, data, and budgets.\n• AIP and sidecar cursor positions were stored separately.\n• Every stream sequence was processed once at the application boundary.\n• Final AIP result and sidecar terminal state agreed.\n• Cancellation claims distinguished stopped execution from prior effects.\n• Uncertain effects were reconciled before any new mutation.\n\nRelated documentation\n• CrewAI run lifecycle and replay reference (../capabilities/run-lifecycle-and-replay.md)\n• CrewAI capability index (../capabilities/README.md)\n• Run the CrewAI quickstart (../getting-started/quickstart.md)\n• Use native AIP (../../../guides/use-native-aip.md)\n• Errors and retry decisions (../../../reference/errors.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "0827584f1df2de3d33fc8a3f68d12797c4f3541c39908a3f77046337b3911eb0"
  }
}
