{
  "schemaVersion": "1.0",
  "title": "CrewAI sidecar contract and lockfile",
  "description": "This reference identifies the Python artifact behind the CrewAI connector and the private HTTP contract used by its Rust host. Use it to compare image provenance, request shapes, durable records, and failure responses.",
  "canonical": "https://getaip.org/docs/connectors/crewai/reference/sidecar-contract-and-lockfile",
  "route": "/docs/connectors/crewai/reference/sidecar-contract-and-lockfile",
  "source": "docs/connectors/crewai/reference/sidecar-contract-and-lockfile.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Connectors",
  "documentType": "Connector",
  "language": "en",
  "downloads": {
    "md": "/docs/download/connectors/crewai/reference/sidecar-contract-and-lockfile.md",
    "txt": "/docs/download/connectors/crewai/reference/sidecar-contract-and-lockfile.txt",
    "json": "/docs/download/connectors/crewai/reference/sidecar-contract-and-lockfile.json",
    "pdf": "/docs/download/connectors/crewai/reference/sidecar-contract-and-lockfile.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: CrewAI sidecar contract and lockfile\ndescription: >-\n  Identify the exact CrewAI sidecar artifact and integrate its private HTTP,\n  durable-job, and event-stream contract\nkind: reference\naudience: operator\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"97be86e9efedf07ecf1783b03800f683f107fb04\"\nconnector: crewai\naliases:\n  - CrewAI sidecar API\n  - CrewAI Python lockfile\n  - CrewAI sidecar routes\n---\n\n# CrewAI sidecar contract and lockfile\n\nThis reference identifies the Python artifact behind the CrewAI connector and\nthe private HTTP contract used by its Rust host. Use it to compare image\nprovenance, request shapes, durable records, and failure responses.\n\nThe sidecar is not a tenant-facing AIP API. AIP identity, admission, policy,\napproval, routing, and signed results remain owned by the Rust host and shared\nruntime.\n\n## Fix the reviewed identity\n\n| Property | Reviewed value |\n|---|---|\n| AIP source | `97be86e9efedf07ecf1783b03800f683f107fb04` |\n| Sidecar package | `aip-crewai-sidecar` `1.0.0` |\n| Python range | `>=3.10,<3.14` |\n| Default CrewAI package set | `crewai`, `crewai-cli`, and `crewai-core` `1.15.5` |\n| Method-verification source | `bfa652a7be8637562cc9b0833f75d927a64552d1` |\n| Method-source package version | `1.15.2` |\n| Default listener | `0.0.0.0:8090` |\n| Application identity | FastAPI title `AIP CrewAI Sidecar`, version `1.0.0` |\n\nThe operation catalogue records the method-verification source revision. That\nrevision is not the package identity of the default product sidecar.\n\n## Choose the artifact definition deliberately\n\nThe reviewed tree contains two image definitions with different identities.\n\n| Definition | Dependency resolution | CrewAI installation | Selected by product Compose |\n|---|---|---|---:|\n| `Dockerfile` | Two frozen `uv sync` steps | Complete lockfile set at `1.15.5` | Yes |\n| `Dockerfile.upstream` | Frozen lockfile first | Reinstalls only `lib/crewai` from a supplied source stage, without dependencies | No |\n\nThe default image labels CrewAI version `1.15.5`. It also places\n`CREWAI_STORAGE_DIR` and `HOME` under `/var/lib/aip-crewai` so journal and\nCrewAI-local state share one durable volume.\n\nThe source-overlay definition accepts a `CREWAI_SOURCE_REVISION` build argument\nand copies an external stage named `crewai-source`. It verifies only that the\nargument is non-empty; it does not compare the argument with copied bytes.\n\nAt the reviewed CrewAI source commit, the reinstalled distribution reports\n`1.15.2`. The overlay does not reinstall `crewai-core` or `crewai-cli`, so\nthose dependencies remain at lockfile version `1.15.5`.\n\nThe source-overlay definition also lacks the default image's durable `HOME`\nand `CREWAI_STORAGE_DIR` declarations. Configure equivalent paths explicitly\nbefore using that artifact with persistent credentials or storage.\n\n## Bind the source files and lockfile\n\nThese SHA-256 values are calculated from each blob at the reviewed AIP commit.\n\n| Source blob | SHA-256 |\n|---|---|\n| `sidecar/pyproject.toml` | `d0b1278261efa26f9bc8905040dcf00066b19f7bd64beca44d206777572b32a0` |\n| `sidecar/uv.lock` | `946f033e72f52d23172d9e1d9179f1057ad8fb2975a2d79d76d1e6bb469baa02` |\n| `sidecar/Dockerfile` | `2c5e874b424d1eb6e0eea1204f6475d06088233c940b36361feb3a7591b6c388` |\n| `sidecar/Dockerfile.upstream` | `1c8ab9e9835dce1aa5e6cbe50c7522732bfb48b321f8bf5031d1378c9d28e61e` |\n| `sidecar/aip_crewai_sidecar/app.py` | `705046d4662fee1f1fa5b678ebfed6c7f9e88e1c6e8e69a502e78f23fa151998` |\n| `sidecar/aip_crewai_sidecar/registry.py` | `a6d9444e9a89812beeb1c3f1af206d470ae056d67d2d34485df1e7413c8917fb` |\n\nAn image digest and retained software bill of materials remain the deployment\nidentity. Source hashes identify reviewed inputs; they do not prove which\nbytes a registry image contains.\n\n## Keep the HTTP boundary private\n\nEvery route requires the complete Bearer header unless the process binds to\nloopback and explicitly enables unauthenticated development mode. The sidecar\ncompares the expected header in constant time.\n\nUvicorn disables proxy-header trust and omits its server header. These settings\ndo not supply TLS, AIP identity, tenant routing, or admission. Deploy the\nsidecar behind the fixed private route used by `aip-host-crewai`.\n\nThe Rust host disables redirects and uses HTTPS except for explicit loopback\nHTTP. Do not expose the sidecar port through the public AIP edge.\n\n## Read the start and cancel models\n\nEvery startable operation uses this closed request envelope:\n\n| Field | Required | Constraint |\n|---|---:|---|\n| `crew_id` | Yes | String from 1 through 256 characters |\n| `action_id` | Yes | String from 1 through 256 characters |\n| `operation` | No | Frozen operation enum; default `run` |\n| `input` | No | JSON object; default empty object; encoded value at most 1 MiB |\n| `timeout_ms` | No | Integer from 1 through `3600000`; default `600000` |\n\nOperation-specific validation then applies exact fields and bounds. The\nsidecar rejects unknown request-envelope fields.\n\nCancellation uses a separate closed envelope:\n\n| Field | Required | Constraint |\n|---|---:|---|\n| `crew_id` | Yes | String from 1 through 256 characters |\n| `action_id` | Yes | String from 1 through 256 characters; must equal the path ID |\n| `reason` | No | String of at most 2,048 characters |\n\nThe request model does not reject control characters in `reason` at this\nrevision.\n\n## Use only the fixed private routes\n\n| Method | Route | Purpose |\n|---|---|---|\n| `GET` | `/health` | Read registry, policy, journal, training, and capacity status |\n| `POST` | `/jobs` | Start or observe one blocking durable job |\n| `POST` | `/jobs/stream` | Start or observe one job as SSE |\n| `GET` | `/jobs/{action_id}` | Read one durable job record |\n| `GET` | `/jobs/{action_id}/events` | Read a JSON slice or follow SSE from a cursor |\n| `POST` | `/jobs/{action_id}/cancel` | Cancel the sidecar task for one job |\n| `DELETE` | `/jobs/{action_id}` | Archive one terminal durable record |\n\nLegacy aliases remain for `POST /runs`, `POST /runs/stream`,\n`GET /runs/{action_id}`, and `POST /runs/{action_id}/cancel`. The two start\naliases accept only the `run` operation.\n\nThere is no legacy events or archive alias. AIP callers must not call either\nroute family directly.\n\n## Supply the required headers\n\n| Header | Applies to | Behavior |\n|---|---|---|\n| `Authorization: Bearer ...` | Every protected route | Exact sidecar credential |\n| `Idempotency-Key` | Every startable job | Required, non-empty, at most 512 UTF-8 bytes, no code point below U+0020 |\n| `Accept: text/event-stream` | Job events read | Selects streaming instead of the JSON slice |\n| `X-AIP-Archive-Confirmation` | Archive | Must equal the archived Action ID |\n\nThe Rust connector also sends `X-AIP-Action-ID` on job starts and explicit\ncancel Actions. The reviewed FastAPI handlers do not read that header; the\nbody and path IDs remain authoritative inside the sidecar.\n\n## Interpret records and event streams\n\nA durable record contains Action ID, crew ID, operation, request hash, status,\nevents, and optional output. Raw operation input and idempotency-key bytes are\nnot persisted, but they contribute to the request hash.\n\nEvents have this stored form:\n\n```json\n{\n  \"event\": \"completed\",\n  \"sequence\": 3,\n  \"data\": {\n    \"status\": \"completed\"\n  }\n}\n```\n\nSSE serializes the same record under its event name:\n\n```text\nevent: completed\ndata: {\"event\":\"completed\",\"sequence\":3,\"data\":{\"status\":\"completed\"}}\n```\n\nOne job status is `running`, `completed`, `failed`, or `cancelled`. A blocking\nroute returns only after terminal state or its HTTP wait timeout. The timeout\ndoes not prove that the job or worker thread stopped.\n\nStored events and output can contain model, tool, knowledge, or provider data.\nTreat the journal as confidential even though credential and raw-input bytes\nare absent.\n\n## Interpret HTTP failures\n\n| Status | Source-owned meaning |\n|---:|---|\n| `400` | Legacy start used a non-run operation, or cancel path and body IDs differ |\n| `401` | Missing or invalid sidecar Bearer credential |\n| `403` | Startable operation is disabled by sidecar policy |\n| `404` | Crew or durable job is absent |\n| `409` | Action ID conflicts with different material, or a running job is archived |\n| `413` | Encoded operation input exceeds 1 MiB |\n| `416` | Event cursor is negative or beyond the retained event count |\n| `422` | Request or operation-specific validation failed |\n| `428` | Idempotency key or archive confirmation is missing |\n| `504` | Blocking HTTP wait exceeded the requested operation timeout |\n| `507` | Journal capacity or durable persistence prevented admission |\n\nAn ordinary provider failure becomes a terminal `failed` event with exception\nclass and a generic message. It has no `uncertain_outcome` field at this\nrevision.\n\nThe sidecar logs such failures with `LOGGER.exception`. Restrict and redact\nsidecar logs because provider exception text and traceback may contain governed\ncontent or credentials.\n\n## Verify an artifact before deployment\n\n1. identify which Dockerfile definition produced the image;\n2. verify the exact AIP commit and the relevant source-blob hashes;\n3. retain the immutable image digest, labels, build provenance, and SBOM;\n4. inspect installed `crewai`, `crewai-core`, and `crewai-cli` distributions;\n5. verify durable `HOME`, CrewAI storage, journal, and training paths;\n6. compare authenticated health with the admitted descriptor set;\n7. qualify route, timeout, restart, cancellation, and archive behavior;\n8. record every mismatch between published support and provider behavior.\n\nDo not infer a source-overlay build from the revision label alone. Do not infer\nprovider termination from a successful cancellation response.\n\n## Related documentation\n\n- [CrewAI connector overview](../README.md)\n- [CrewAI connector configuration](configuration.md)\n- [CrewAI authentication and admitted crews](../getting-started/authentication-and-admitted-crews.md)\n- [CrewAI capability index](../capabilities/README.md)\n- [Errors and retry decisions](../../../reference/errors.md)\n",
    "text": "CrewAI sidecar contract and lockfile\n\nThis reference identifies the Python artifact behind the CrewAI connector and\nthe private HTTP contract used by its Rust host. Use it to compare image\nprovenance, request shapes, durable records, and failure responses.\n\nThe sidecar is not a tenant-facing AIP API. AIP identity, admission, policy,\napproval, routing, and signed results remain owned by the Rust host and shared\nruntime.\n\nFix the reviewed identity\n\n| Property | Reviewed value |\n\n| AIP source | 97be86e9efedf07ecf1783b03800f683f107fb04 |\n| Sidecar package | aip-crewai-sidecar 1.0.0 |\n| Python range | >=3.10,<3.14 |\n| Default CrewAI package set | crewai, crewai-cli, and crewai-core 1.15.5 |\n| Method-verification source | bfa652a7be8637562cc9b0833f75d927a64552d1 |\n| Method-source package version | 1.15.2 |\n| Default listener | 0.0.0.0:8090 |\n| Application identity | FastAPI title AIP CrewAI Sidecar, version 1.0.0 |\n\nThe operation catalogue records the method-verification source revision. That\nrevision is not the package identity of the default product sidecar.\n\nChoose the artifact definition deliberately\n\nThe reviewed tree contains two image definitions with different identities.\n\n| Definition | Dependency resolution | CrewAI installation | Selected by product Compose |\n\n| Dockerfile | Two frozen uv sync steps | Complete lockfile set at 1.15.5 | Yes |\n| Dockerfile.upstream | Frozen lockfile first | Reinstalls only lib/crewai from a supplied source stage, without dependencies | No |\n\nThe default image labels CrewAI version 1.15.5. It also places\nCREWAISTORAGEDIR and HOME under /var/lib/aip-crewai so journal and\nCrewAI-local state share one durable volume.\n\nThe source-overlay definition accepts a CREWAISOURCEREVISION build argument\nand copies an external stage named crewai-source. It verifies only that the\nargument is non-empty; it does not compare the argument with copied bytes.\n\nAt the reviewed CrewAI source commit, the reinstalled distribution reports\n1.15.2. The overlay does not reinstall crewai-core or crewai-cli, so\nthose dependencies remain at lockfile version 1.15.5.\n\nThe source-overlay definition also lacks the default image's durable HOME\nand CREWAISTORAGEDIR declarations. Configure equivalent paths explicitly\nbefore using that artifact with persistent credentials or storage.\n\nBind the source files and lockfile\n\nThese SHA-256 values are calculated from each blob at the reviewed AIP commit.\n\n| Source blob | SHA-256 |\n\n| sidecar/pyproject.toml | d0b1278261efa26f9bc8905040dcf00066b19f7bd64beca44d206777572b32a0 |\n| sidecar/uv.lock | 946f033e72f52d23172d9e1d9179f1057ad8fb2975a2d79d76d1e6bb469baa02 |\n| sidecar/Dockerfile | 2c5e874b424d1eb6e0eea1204f6475d06088233c940b36361feb3a7591b6c388 |\n| sidecar/Dockerfile.upstream | 1c8ab9e9835dce1aa5e6cbe50c7522732bfb48b321f8bf5031d1378c9d28e61e |\n| sidecar/aipcrewaisidecar/app.py | 705046d4662fee1f1fa5b678ebfed6c7f9e88e1c6e8e69a502e78f23fa151998 |\n| sidecar/aipcrewaisidecar/registry.py | a6d9444e9a89812beeb1c3f1af206d470ae056d67d2d34485df1e7413c8917fb |\n\nAn image digest and retained software bill of materials remain the deployment\nidentity. Source hashes identify reviewed inputs; they do not prove which\nbytes a registry image contains.\n\nKeep the HTTP boundary private\n\nEvery route requires the complete Bearer header unless the process binds to\nloopback and explicitly enables unauthenticated development mode. The sidecar\ncompares the expected header in constant time.\n\nUvicorn disables proxy-header trust and omits its server header. These settings\ndo not supply TLS, AIP identity, tenant routing, or admission. Deploy the\nsidecar behind the fixed private route used by aip-host-crewai.\n\nThe Rust host disables redirects and uses HTTPS except for explicit loopback\nHTTP. Do not expose the sidecar port through the public AIP edge.\n\nRead the start and cancel models\n\nEvery startable operation uses this closed request envelope:\n\n| Field | Required | Constraint |\n\n| crewid | Yes | String from 1 through 256 characters |\n| actionid | Yes | String from 1 through 256 characters |\n| operation | No | Frozen operation enum; default run |\n| input | No | JSON object; default empty object; encoded value at most 1 MiB |\n| timeoutms | No | Integer from 1 through 3600000; default 600000 |\n\nOperation-specific validation then applies exact fields and bounds. The\nsidecar rejects unknown request-envelope fields.\n\nCancellation uses a separate closed envelope:\n\n| Field | Required | Constraint |\n\n| crewid | Yes | String from 1 through 256 characters |\n| actionid | Yes | String from 1 through 256 characters; must equal the path ID |\n| reason | No | String of at most 2,048 characters |\n\nThe request model does not reject control characters in reason at this\nrevision.\n\nUse only the fixed private routes\n\n| Method | Route | Purpose |\n\n| GET | /health | Read registry, policy, journal, training, and capacity status |\n| POST | /jobs | Start or observe one blocking durable job |\n| POST | /jobs/stream | Start or observe one job as SSE |\n| GET | /jobs/{actionid} | Read one durable job record |\n| GET | /jobs/{actionid}/events | Read a JSON slice or follow SSE from a cursor |\n| POST | /jobs/{actionid}/cancel | Cancel the sidecar task for one job |\n| DELETE | /jobs/{actionid} | Archive one terminal durable record |\n\nLegacy aliases remain for POST /runs, POST /runs/stream,\nGET /runs/{actionid}, and POST /runs/{actionid}/cancel. The two start\naliases accept only the run operation.\n\nThere is no legacy events or archive alias. AIP callers must not call either\nroute family directly.\n\nSupply the required headers\n\n| Header | Applies to | Behavior |\n\n| Authorization: Bearer ... | Every protected route | Exact sidecar credential |\n| Idempotency-Key | Every startable job | Required, non-empty, at most 512 UTF-8 bytes, no code point below U+0020 |\n| Accept: text/event-stream | Job events read | Selects streaming instead of the JSON slice |\n| X-AIP-Archive-Confirmation | Archive | Must equal the archived Action ID |\n\nThe Rust connector also sends X-AIP-Action-ID on job starts and explicit\ncancel Actions. The reviewed FastAPI handlers do not read that header; the\nbody and path IDs remain authoritative inside the sidecar.\n\nInterpret records and event streams\n\nA durable record contains Action ID, crew ID, operation, request hash, status,\nevents, and optional output. Raw operation input and idempotency-key bytes are\nnot persisted, but they contribute to the request hash.\n\nEvents have this stored form:\n\n{\n  \"event\": \"completed\",\n  \"sequence\": 3,\n  \"data\": {\n    \"status\": \"completed\"\n  }\n}\n\nSSE serializes the same record under its event name:\n\nevent: completed\ndata: {\"event\":\"completed\",\"sequence\":3,\"data\":{\"status\":\"completed\"}}\n\nOne job status is running, completed, failed, or cancelled. A blocking\nroute returns only after terminal state or its HTTP wait timeout. The timeout\ndoes not prove that the job or worker thread stopped.\n\nStored events and output can contain model, tool, knowledge, or provider data.\nTreat the journal as confidential even though credential and raw-input bytes\nare absent.\n\nInterpret HTTP failures\n\n| Status | Source-owned meaning |\n\n| 400 | Legacy start used a non-run operation, or cancel path and body IDs differ |\n| 401 | Missing or invalid sidecar Bearer credential |\n| 403 | Startable operation is disabled by sidecar policy |\n| 404 | Crew or durable job is absent |\n| 409 | Action ID conflicts with different material, or a running job is archived |\n| 413 | Encoded operation input exceeds 1 MiB |\n| 416 | Event cursor is negative or beyond the retained event count |\n| 422 | Request or operation-specific validation failed |\n| 428 | Idempotency key or archive confirmation is missing |\n| 504 | Blocking HTTP wait exceeded the requested operation timeout |\n| 507 | Journal capacity or durable persistence prevented admission |\n\nAn ordinary provider failure becomes a terminal failed event with exception\nclass and a generic message. It has no uncertainoutcome field at this\nrevision.\n\nThe sidecar logs such failures with LOGGER.exception. Restrict and redact\nsidecar logs because provider exception text and traceback may contain governed\ncontent or credentials.\n\nVerify an artifact before deployment\n1. identify which Dockerfile definition produced the image;\n2. verify the exact AIP commit and the relevant source-blob hashes;\n3. retain the immutable image digest, labels, build provenance, and SBOM;\n4. inspect installed crewai, crewai-core, and crewai-cli distributions;\n5. verify durable HOME, CrewAI storage, journal, and training paths;\n6. compare authenticated health with the admitted descriptor set;\n7. qualify route, timeout, restart, cancellation, and archive behavior;\n8. record every mismatch between published support and provider behavior.\n\nDo not infer a source-overlay build from the revision label alone. Do not infer\nprovider termination from a successful cancellation response.\n\nRelated documentation\n• CrewAI connector overview (../README.md)\n• CrewAI connector configuration (configuration.md)\n• CrewAI authentication and admitted crews (../getting-started/authentication-and-admitted-crews.md)\n• CrewAI capability index (../capabilities/README.md)\n• Errors and retry decisions (../../../reference/errors.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "efd99491b1dd0fbb19796b895b1a8755a911368cd74f1b89be0140278c9ab25b"
  }
}
