Mirror of #3868 by @Abubakar-01.
Wraps `agent.runAgent(...)` in a `useEffect` with an empty dependency
array in both the docs and showcase MDX files, and adds a prose warning
explaining why calling `runAgent` directly in the component body causes
"thread is already processing" errors.
## Summary
Resolves the recurring `docs-sync` manual-review flag on
`integrations/mastra/agent-app-context.mdx` by applying the sync
script's clean-transform to bring the showcase copy in line with
upstream, plus a small typo fix.
- Typo: `useCopilotReadble` → `useCopilotReadable` (both files)
- Clean-transform sync: restores 2 code-block imports
(`useAgentContext`, `useState` — both actually used in the example on
lines 40 + 32), normalizes whitespace
- Bumps `showcase/shell/.docs-sync-sha` from `41b6eb93` to `0e7811402`
## Note
There is an existing auto-generated PR #4044 covering this same file
(plus 2 aws-strands files). Close that PR after merging this one; the
aws-strands files will be handled by a separate future sync run once the
updated workflow (see branch `ci/docs-sync-auto-pr`) is merged.
## Test plan
- [ ] CI green
- [ ] Post-merge: `npx tsx showcase/scripts/sync-docs-from-main.ts
--dry-run` no longer flags this file for review
Feature matrix (generative-ui category):
- Order: Controlled Gen-UI (Display) -> (Interactive) / In-Chat HITL
-> (Interrupt) -> Declarative Generative UI (A2UI) -> MCP Apps
-> Fully Open-Ended Generative UI -> Agentic Generative UI
(In-Chat State Rendering) -> Tool Rendering.
- Merge `hitl-in-chat` with the Controlled Gen-UI (Interactive) idea;
drop the unused `gen-ui-interactive` placeholder.
- Merge standalone `a2ui` entry into Declarative Generative UI (A2UI);
drop the duplicate.
- Rename `gen-ui-agent` display to "Agentic Generative UI (In-Chat
State Rendering)". Moved `tool-rendering` next to it.
- Rename `gen-ui-tool-based` display from "Controlled Generative UI"
to "Controlled Gen-UI (Display)". Dropped the placeholder
`gen-ui-display` entry (was zero-use).
Agentic chat demo (langgraph-python):
- Removed the "Weather in SF" suggestion and the associated
`useRenderTool`/`get_weather` code. The slimmed agent has no backend
tools, so this demo is now pure chat -- just `CopilotChat`, a user
context tag, and one sonnet suggestion.
Regenerated registry + demo-content.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rework the Controlled Generative UI demo to be minimal, self-contained,
and render charts via `useComponent`.
Frontend (`src/app/demos/gen-ui-tool-based/`):
- `page.tsx` -- `CopilotKit` + full-screen `CopilotChat` (no sidebar),
two `useComponent` registrations (`render_bar_chart`,
`render_pie_chart`), three chart-oriented suggestions.
- `bar-chart.tsx`, `pie-chart.tsx` -- ported from
`examples/integrations/langgraph-python`. Each file reads top-to-
bottom as imports -> schema -> props type -> component; colors and
animation helpers are inlined inside the component. No shared
chart-config module.
- Haiku card + schema removed.
Agent (`src/agents/main.py`):
- Rewritten using `create_agent` + `CopilotKitMiddleware()` so the
LangGraph middleware injects the frontend `render_*_chart` tools into
the model request at runtime.
- Deleted all backend-tool modules (`tools.py`, `todos.py`,
`a2ui_dynamic_schema.py`, `a2ui_fixed_schema.py`). System prompt
trimmed to a data-viz assistant.
Peripheral cleanups:
- `demos/agentic-chat/page.tsx` -- `change_background` tool + its
suggestion removed; it had nothing to do with chat.
- New `demos/frontend-tools/` (In-App Actions) hosts
`change_background` as its own demo with a `frontend_tools` agent
name registered in `api/copilotkit/route.ts`.
- Stub `gen-ui-tool-based/agent.py` removed.
- `generate-starters.test.ts` no longer requires every python package
to have backend tool imports -- a package with only frontend tools
(like this controlled-gen-ui demo) is now valid.
- Whitelist generated shell data (`demo-content.json`,
`search-index.json`, `starter-content.json`) in check-binaries hook
-- they're generated artifacts like `package-lock.json`.
- Regenerated `demo-content.json` + `registry.json`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Grid polish:
- Light-mode palette (white surface, slate borders, dark text); dropped
the dark-theme tokens.
- Rows are every declared feature, even ones with zero current support.
Empty rows surface feature gaps we want to fill -- hiding them hides
the TODO.
- Cells: `demo · code` as tight blue text links, `-` for supported but
no demo, red `✗` for unsupported. No colored pill buttons.
- Sticky first column + sticky header row. Hover highlight replaces
striped rows.
Internal sort order:
- New `src/lib/sort-order.ts` -- slug -> rank map used only by this app
(intentionally not in the public registry). Orders columns LangChain
first, then Google/MS/AWS, then the rest. Explicitly internal.
- `getIntegrations()` in lib/registry.ts sorts by this map with a
fallback to the registry's `sort_order`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a single command to spin up the exact image Railway deploys,
for any of the 17 showcase packages, with a single shared .env:
./showcase/scripts/dev-local.sh up [<slug> ...] # all if empty
./showcase/scripts/dev-local.sh down|build|logs|ps|ports
Pieces:
- `docker-compose.local.yml` with a service per package. Ports come
from `shared/local-ports.json` (langgraph-python -> 3100, ...).
- `.env.example` as a commit-safe template. Real `.env` is gitignored
and fed to every container via `env_file`, so keys (OPENAI_API_KEY,
etc.) live in one place.
- `dev-local.sh` wraps `docker compose` and handles the
`shared_python/` / `shared_typescript/` staging step that CI does
before `docker build` (see showcase_deploy.yml).
- Staged `shared_*` dirs added to .gitignore.
Shell wiring:
- `shell/next.config.ts` reads `shared/local-ports.json` when
`SHOWCASE_LOCAL=1` is set and injects it as a public env.
- `/integrations/[slug]/[demo]/preview` uses that map to iframe
`http://localhost:<port>` instead of `integration.backend_url`.
Per-slug; any slug not running locally falls back to Railway.
Unset SHOWCASE_LOCAL -> prod behavior, unchanged.
Full workflow + prerequisites (Colima / Docker Desktop) documented in
showcase/README.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
langgraph-python, langgraph-fastapi, and langgraph-typescript starters run
langgraph_cli dev which exposes /ok (not /health). The template now probes
/health, so the generator must rewrite this back to /ok for langgraph-* only,
otherwise drift-check fails and regenerating would break those starters'
health routes.
Next.js 15.4.10's turbopack panics ("Next.js package not found") on the
repo's multi-lockfile layout. Webpack dev works; production builds are
unaffected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduces a new internal-facing showcase app (`showcase/shell-internal`)
that renders a feature × integration grid. Each cell links to one of two
new canonical standalone routes on the main `shell` app:
- `/integrations/[slug]/[demo]/preview` — iframe-only hosted demo
- `/integrations/[slug]/[demo]/code` — code viewer; supports `?file=<name>`
and `?lines=<start>-<end>` URL params for future line-highlighting
Keeping the canonical pages in `shell` means they can also be embedded in
docs/marketing; `shell-internal` is a pure overview with no duplicated
content (reads `shell/src/data/registry.json` directly).
Also drops `--turbopack` from `shell`'s dev script: Next.js 15.4.10's
turbopack panics on the repo's multi-lockfile layout. Webpack dev works
fine and this doesn't affect production builds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The docs-sync workflow flagged these two files as having showcase-local
modifications that blocked the automated transform pipeline:
- docs/content/docs/integrations/langgraph/generative-ui/your-components/interrupt-based.mdx
- docs/content/docs/integrations/langgraph/human-in-the-loop/interrupt-flow.mdx
Upstream docs/ changes pending sync to showcase/:
- Add useInterrupt `agentId: "starterAgent"` to all four examples per file
- Add <Callout type="warn"> explaining that a mismatched agentId silently
never fires the interrupt
- Update stale model name gpt-5.2 -> gpt-5.4 in code snippets
Showcase-local divergence present before this PR:
- Leftover import fragment at the top of each file (bytes from an
incomplete multi-line import strip by an older version of the sync
script, not deliberate content)
- Prettier-style reformatting applied ad hoc (line wrapping in the
Callout info block and the last useInterrupt handler example)
- Stale model name gpt-5.2 (pre-dates the upstream bump to gpt-5.4)
- interrupt-flow.mdx never received the agentId / Callout additions
that interrupt-based.mdx received in 63a6a2733 and 90d1869ea
Resolution: rebuild both showcase files as a clean transform of the
current upstream source. None of the showcase-local changes were
intentional additive content — they were stripping bugs, formatter
drift, and pre-sync staleness — so dropping them and taking the full
upstream reconciles both files cleanly.
Also bumps showcase/shell/.docs-sync-sha to the current main tip so the
next docs-sync run does not re-flag the same files.
## Summary
Adds 5 missing QA markdown files (gen-ui-agent,
shared-state-{read,write,streaming}, subagents) to bring
`showcase/packages/ag2/qa/` from 4 files to 9, matching
`langgraph-python/qa/`.
Part of the QA-parity blitz (Bundle 0 in the action inventory).
### Detail
- `gen-ui-agent.md` and `shared-state-read.md` describe the full
implementations — selectors (`task-progress`, `task-step-text`,
`recipe-card`, `add-ingredient-button`, `improve-button`), labels (`AI
Recipe Assistant`), and suggestion button names match the ag2 page
sources verbatim (they mirror LG-py's implementations word-for-word).
- `shared-state-write.md`, `shared-state-streaming.md`, and
`subagents.md` follow the "Note: Stub Demo" pattern from LG-py — the ag2
pages for these demos are stubs identical to LG-py's stubs, so the QA
coverage is identical.
## Test plan
- [ ] Verify `showcase/packages/ag2/qa/` now contains 9 files matching
the file set in `showcase/packages/langgraph-python/qa/`
- [ ] Spot-check selectors in `gen-ui-agent.md` and
`shared-state-read.md` against the ag2 page sources
## Summary
Follow-up hardening to #3971. aimock supports fixture schema validation
at startup via `--validate-on-load`, but the flag is **opt-in** and the
showcase Dockerfile was not passing it. That meant fixtures with
unrecognized response keys (e.g. `"text"` instead of `"content"`) loaded
silently and only surfaced as HTTP 500s at request time — which is
exactly what crashed crewai-crews and triggered #3971.
This PR wires up two independent safety nets so a broken fixture can't
ship again:
1. **Dockerfile (fail-fast at container boot)** —
`showcase/aimock/Dockerfile` now passes `--validate-on-load`. If any
fixture fails the aimock schema, the container exits non-zero instead of
starting and serving 500s. Railway will not promote a bad build.
2. **CI test (fail-fast in PR review)** — new vitest spec at
`showcase/scripts/__tests__/aimock-fixtures.test.ts` imports
`loadFixtureFile` + `validateFixtures` from `@copilotkit/aimock` and
asserts zero errors against both `feature-parity.json` and `smoke.json`.
Runs inside the existing ` Showcase: Validate` workflow
(`showcase/scripts` vitest suite) on every PR that touches
`showcase/**`.
## Verification
**Red-green on the vitest spec:**
- Rebased onto the tip of main *before* #3971 merged: the spec fails
with 5 errors — exactly the 5 broken `"text"` fixtures (`plan`, `steps`,
`mars`, `dashboard`, `report`) that #3971 repaired.
- Rebased forward onto main *after* #3971: spec passes with 0 errors,
all 549 showcase/scripts tests green.
**Red-green on the Dockerfile:**
- Current fixtures + `--validate-on-load`: container boots cleanly, logs
`Loaded 39 fixture(s) from /fixtures`.
- Injecting an intentionally broken fixture (`response: { "text": "..."
}`): container fails to start with `[aimock] Fixture 0: response is not
a recognized type (must have content, toolCalls, error, or embedding)` /
`Validation failed: 1 error(s), 0 warning(s)` and non-zero exit.
## Test plan
- [x] Local: full `showcase/scripts` vitest suite passes (549/549)
- [x] Local: `pnpm run test` (monorepo) passes
- [x] Docker: image builds and starts with `--validate-on-load` against
current fixtures
- [x] Docker red-green: broken fixture fails container start with
non-zero exit
- [ ] CI: ` Showcase: Validate` job runs the new test file on PR
## Summary
Updates LangGraph human-in-the-loop interrupt documentation so
`useInterrupt`
examples set `agentId: "starterAgent"` and readers see a warning that
`agentId`
must match a runtime-registered agent (default assumption is
`"default"`).
## Changes
-
**`docs/content/docs/integrations/langgraph/human-in-the-loop/interrupt-flow.mdx`**
— warning callout; `agentId` on basic, conditional (`enabled`), and
`handler` snippets.
-
**`docs/content/docs/integrations/langgraph/generative-ui/your-components/interrupt-based.mdx`**
— same.
-
**`showcase/shell/src/content/docs/integrations/langgraph/generative-ui/your-components/interrupt-based.mdx`**
— same content alignment; adds the `useInterrupt` import line in the
primary code block for consistency with main docs.
## Notes
- Production apps should replace `"starterAgent"` with the id their
runtime actually registers.
- If you also want showcase `human-in-the-loop/interrupt-flow.mdx`, hook
reference docs, or a longer callout (e.g. `/info`, example error text),
those are not part of this staged set—add them in a follow-up or stage
them before merge.
## Test plan
- [ ] Open the three MDX pages in the docs/showcase preview and confirm
the callout and snippets render as expected.
Brings showcase/packages/ag2/qa/ from 4 files to 9, matching langgraph-python.
Adds: gen-ui-agent, shared-state-read, shared-state-write, shared-state-streaming, subagents.
Content is adapted from the LG-py templates with titles changed to AG2. The
three stub demos (shared-state-write, shared-state-streaming, subagents) keep
the LG-py 'Note: Stub Demo' pattern since the ag2 implementations are stubs
identical in shape to LG-py's. gen-ui-agent and shared-state-read describe
the full implementations (which mirror LG-py's selectors and labels
verbatim).
## Summary
CrewAI's `ChatWithCrewFlow.__init__` (invoked from
`ag_ui_crewai.endpoint.add_crewai_crew_fastapi_endpoint` at module
import in `ag-ui-crewai <= 0.1.5`) makes synchronous blocking LLM calls
via `crewai.cli.crew_chat.generate_input_description_with_ai` and
`generate_crew_description_with_ai`. ANY LLM hiccup — aimock regression,
OpenAI outage, network blip, DNS failure — crashes the Python process
BEFORE uvicorn can bind its port, causing Railway/Kubernetes health
checks to fail and deploys to roll back.
This was the direct cause of the crewai-crews Railway crash fixed
server-side in #3971. That fix patched the aimock response schema, but
the underlying fragility in upstream CrewAI / ag-ui-crewai remained — a
future blip would crash us again.
This PR adds a defensive monkey-patch in `agent_server.py` that replaces
both generator functions with static-string returns BEFORE
`ag_ui_crewai` is imported. The AI-generated descriptions are only
surfaced in the CrewAI chat UI (which the CopilotKit runtime does not
use), so static defaults are functionally equivalent for our showcase.
Upstream issue filed: https://github.com/crewAIInc/crewAI/issues/5510
The long-term fix is deferred construction in `ag-ui-crewai`, which has
landed on ag-ui `main` but is not yet released. Remove this shim once
`ag-ui-crewai > 0.1.5` ships.
## Why a monkey-patch and not lazy-init
`add_crewai_crew_fastapi_endpoint` is the entry point and internally
constructs `ChatWithCrewFlow(crew)` synchronously in `ag-ui-crewai <=
0.1.5`. Deferring that call would require either vendoring the endpoint
function or reimplementing it. The monkey-patch is two lines and removes
cleanly when the upstream fix ships.
## Test plan
Verified locally via Docker build + run with an intentionally broken LLM
endpoint (`OPENAI_BASE_URL=http://invalid-host/v1`):
**Unhardened (negative control):**
```
File "/app/agent_server.py", line 27, in <module>
add_crewai_crew_fastapi_endpoint(app, LatestAiDevelopment(), "/")
File ".../ag_ui_crewai/endpoint.py", line 250, in add_crewai_crew_fastapi_endpoint
add_crewai_flow_fastapi_endpoint(app, ChatWithCrewFlow(crew=crew), path)
File ".../ag_ui_crewai/crews.py", line 56, in __init__
self.crew_chat_inputs = crew_chat_generate_crew_chat_inputs(...)
File ".../crewai/cli/crew_chat.py", line 387, in generate_crew_chat_inputs
description = generate_input_description_with_ai(input_name, crew, chat_llm)
File ".../crewai/cli/crew_chat.py", line 481, in generate_input_description_with_ai
response = chat_llm.call(...)
APIError
```
Container exits with code 1, never binds a port.
**Hardened (this PR):**
```
INFO: Started server process [7]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
```
`curl http://localhost:PORT/api/health` ->
`{"status":"ok","integration":"crewai-crews","agent":"ok","timestamp":"..."}`
(HTTP 200).
### Checklist
- [x] Docker build succeeds locally
- [x] Unhardened build crashes on import with broken LLM endpoint
(negative control)
- [x] Hardened build starts cleanly with broken LLM endpoint and
responds 200 on `/api/health`
- [x] Upstream issue filed on crewAIInc/crewAI
## Summary
- The Mastra showcase package registers only `weatherAgent` in its
Mastra config, but the demo pages request names like `agentic_chat`,
`human_in_the_loop`, `tool-rendering`, etc.
`MastraAgent.getLocalAgents({ mastra })` returns agents keyed by
registration name, so the runtime cannot resolve the demo-requested
names. This was causing the L3 mastra chat test to fail.
- Mirror the pattern used in
`showcase/packages/crewai-crews/src/app/api/copilotkit/route.ts`: wrap
`MastraAgent.getLocalAgents` and expose the underlying `weatherAgent`
under every name the demo pages ask for. `weatherAgent` itself is
preserved so the internal `/api/smoke` route (which calls `agentId:
"weatherAgent"`) keeps working.
## Agent names now exposed on the backend
- `weatherAgent` (original Mastra registration — preserved for smoke
test)
- `agentic_chat`
- `human_in_the_loop`
- `tool-rendering`
- `gen-ui-tool-based`
- `gen-ui-agent`
- `shared-state-read`
- `shared-state-write`
- `shared-state-streaming`
- `subagents`
The starter (`showcase/starters/mastra`) was checked and is not affected
— its route uses `LangGraphAgent` and already registers `sample_agent`,
which matches what the starter's page requests.
## Test plan
- [ ] CI L3 mastra chat test passes (the failure this PR targets)
- [ ] `/api/smoke` route still returns 200 (uses `weatherAgent` which is
preserved)
- [ ] Demo pages (`/demos/agentic-chat`, `/demos/hitl`,
`/demos/tool-rendering`, etc.) can reach the runtime without 404
Addresses CR R1 CRITICAL finding on PR #3974.
setattr() on a Python module always succeeds regardless of prior
attribute existence. Without a guard, an upstream rename of
generate_input_description_with_ai or generate_crew_description_with_ai
in a future crewai release would silently no-op the patch, leaving the
real functions in place. The pre-bind LLM crash bug would quietly
reappear in production with a green PR.
Changes:
- Add hasattr() guard in both agent_server.py files that raises
RuntimeError with an actionable drift message if either symbol
disappears upstream.
- Add post-assignment assert to defend against import-order weirdness
or module re-imports shadowing the reference.
- Add an info-level log line so operators can see the shim is active
and know to remove it after adoption.
- Add upstream issue link (crewAIInc/crewAI#5510) and explicit ag-ui-crewai
release status to the comment block.
- Pin ag-ui-crewai upper bound to <0.1.6 in both requirements.txt files
so the shim's applicability window is enforced by pip — upgrading past
0.1.5 forces the engineer to confront the version mismatch and remove
the shim.
Applied to both showcase/packages/crewai-crews/src/agent_server.py and
showcase/starters/crewai-crews/agent_server.py to keep the demo and
starter trees in sync.
Verified locally:
- Docker build succeeds (showcase/packages/crewai-crews).
- Hardened container starts cleanly with OPENAI_BASE_URL set to an
unreachable host; /health returns 200 on both agent (8000) and
Next.js (10000) ports.
- Negative case: deleting generate_input_description_with_ai from the
installed crewai module inside the container and re-importing
agent_server raises RuntimeError with the upstream-drift message, as
expected.
- Add --validate-on-load to all aimock invocations (4 workflows/scripts
+ 13 integration docker-compose files)
- Replace hardcoded 2-file fixture list with dynamic discovery across
showcase/, examples/integrations/*/, scripts/doc-tests/ (16 fixtures)
- Add sanity check to prevent silent zero-test pass when discovery fails
- Extend showcase_validate.yml path filter to trigger on
examples/integrations/**/fixtures/** and scripts/doc-tests/fixtures/**
- Import and use ValidationResult type for callback parameters
- Fix scripts/doc-tests/fixtures/default.json to use { fixtures: [...] }
envelope shape
Add a sentence to the warning callout explaining that if agentId doesn't
match a runtime-registered agent, the interrupt will silently never fire.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CrewAI's ChatWithCrewFlow.__init__ (called by ag_ui_crewai's
add_crewai_crew_fastapi_endpoint at module import) makes blocking
synchronous LLM calls via generate_input_description_with_ai and
generate_crew_description_with_ai in crewai/cli/crew_chat.py. Any LLM
hiccup (aimock regression, OpenAI outage, network blip) crashes the
Python process before uvicorn can bind, causing Railway healthcheck
failure and deploy rollback.
Patch both functions to return static strings before ag_ui_crewai is
imported. The AI-generated descriptions are only used by the CrewAI
chat UI (not the CopilotKit runtime), so static defaults are
functionally equivalent for our showcase.
Verified via docker build: unhardened image crashes on import with
APIError at crew_chat.py:481; hardened image starts cleanly with an
invalid OPENAI_BASE_URL and responds on /api/health.
Upstream fix (deferred construction) landed on ag-ui main but is not
yet released in ag-ui-crewai > 0.1.5. Remove shim when released.
Upstream issue: https://github.com/crewAIInc/crewAI/issues/5510
Follow-up to #3971. aimock supports fixture schema validation at startup via
--validate-on-load, but it's opt-in. The showcase Dockerfile did not pass
the flag, so fixtures with unrecognized response keys (e.g. "text" instead
of "content") loaded silently and only failed at request time with HTTP 500.
That's what crashed crewai-crews on startup.
Changes:
- showcase/aimock/Dockerfile: pass --validate-on-load so broken fixtures
fail the container boot, not individual requests.
- showcase/scripts/__tests__/aimock-fixtures.test.ts: new vitest spec that
loads feature-parity.json and smoke.json via @copilotkit/aimock's
loadFixtureFile + validateFixtures and asserts zero errors. Runs as part
of the existing showcase-validate CI workflow.
- showcase/scripts/package.json: add @copilotkit/aimock dependency for the
validator import.
Verified red-green: with the pre-#3971 broken "text" fixtures, validateFixtures
flags 5 errors; post-#3971 it returns zero. Docker red-green: container with
an intentionally broken fixture fails to start with "Validation failed: 1
error(s)" and non-zero exit.
The showcase aimock feature-parity fixture had five entries that used the
unrecognized field "text" instead of "content" in the response body.
aimock's /v1/chat/completions handler validates the response shape through
discriminators (isTextResponse, isToolCallResponse, etc.) and when none
match, returns 500 "Fixture response did not match any known type".
When CrewAI's ChatWithCrewFlow.__init__ calls generate_input_description_with_ai,
it sends a prompt containing "Reporting Analyst" / "reports" text (from the
LatestAiDevelopment crew definition). aimock substring-matches this against
the "report" fixture, which had the broken "text" shape, and returned 500.
CrewAI treats that as an InternalServerError, the crewai-crews container
crashes during module import (before uvicorn binds), Railway healthchecks
fail, and the deployment rolls back to the previous ACTIVE build.
Fix:
- Convert the 5 fixtures with "text" (plan, steps, mars, dashboard, report)
to the valid "content" field so they return 200 OK.
- Add a targeted fixture that matches CrewAI's exact startup prompt prefix
("Based on the following context, write a concise") and returns a clean
text description. This catches generate_input_description_with_ai and
generate_crew_description_with_ai before they can fall through to the
more generic fixtures, providing a more predictable response for CrewAI
startup.
Verified locally against @copilotkit/aimock@1.10.0:
- Before: the CrewAI-style prompt returns 500 with the exact error message
seen in Railway logs.
- After: returns 200 with a valid chat.completion envelope.
Note: CrewAI's blocking LLM call at module import remains fragile (any
aimock hiccup crashes the container before it can bind a port). That is
an upstream issue and will be tracked separately.