Playwright install stderr is diagnostic signal — version/network errors,
missing system libs, or browser download failures all surface here. Only
suppress stderr on the noisy npm install step. Also pin the image-tag /
client-version relationship with a code comment on one compose file so
future bumps know to keep them aligned.
The Playwright Docker image (mcr.microsoft.com/playwright:v1.52.0-noble)
ships with all Chromium system libraries and browsers pre-installed, so
`--with-deps` adds no runtime value — it only forces a redundant
`apt-get update && apt-get install` inside the tests container.
That apt-get call is the sole source of the intermittent
"Installation process exited with code: 100" / "Failed to install
browsers" failures that rotate across the 12 smoke matrix entries. The
underlying cause is transient Ubuntu archive mirror hash/size mismatches
("File has unexpected size ... Mirror sync in progress?", "Hash Sum
mismatch"), which cause apt to abort with exit 100. Because each matrix
job races apt against archive.ubuntu.com independently, the failing
subset rotates per run (run 24526747926 hit 5 starters; run 24509673514
hit a different 5; run 24495760568 hit 3) — classic flake, not a per-
starter regression.
Dropping --with-deps eliminates the apt-get call entirely. The browsers
themselves are already present at /ms-playwright/chromium-* in the base
image, and `npx playwright install chromium` remains as a cheap no-op
that self-heals if the pinned Playwright version ever drifts from the
image's bundled browser build.
- Remove @langchain/community from sdk-js peerDependencies (unused,
was blocking @langchain/core@1.x resolution)
- Add langchain@^1.0.0 to langgraph-js agent deps to prevent
transitive resolution to 0.3.x
- Add postcss.config.mjs to mcp-apps threejs-server
- Remove '|| .bat' fallback from all starter package.json scripts so
real errors on Linux/macOS are not masked by a failing .bat attempt
- Fix typos: 'isseus' -> 'issues', 'interactin' -> 'interacting'
- Fix crewai-crews README title/body saying 'Flow' instead of 'Crew'
- Fix a2a-a2ui README wrong agent name and file path
- Remove phantom lint/dev:debug scripts from README Available Scripts
sections where those scripts don't exist in package.json
- Add missing dev:ui and dev:agent to mastra README
- chmod +x all new .sh scripts so they work on Linux/macOS
- Use --ignore-scripts in langgraph-js Dockerfiles to avoid postinstall
failure (agent/ dir not yet copied during npm install stage)
- Install agent deps in production Dockerfile after COPY agent/
- Fix hardcoded pnpm commands in agent-spec README
Reorder package manager instructions to show npm first as the default.
Remove stale 'ignores lock files' notes since lock file entries were
removed from .gitignore. All starters now work with npm, pnpm, yarn,
or bun — user's choice.
Starters should not constrain users to a specific package manager.
The .gitignore gets cloned into the user's project, so ignoring
certain lock files would prevent them from committing their chosen
package manager's lock file.
Flatten langgraph-python, langgraph-js, and mcp-apps starters so
npm install && npm run dev works out of the box. Replace Turborepo
with concurrently, move apps/* to root, update Dockerfiles, READMEs,
and entrypoints. Also remove stray pnpm-lock.yaml from a2a-a2ui and
ms-agent-framework-dotnet starters.
- starter-langgraph-python: use next build --webpack (Turbopack default
in Next 16 can't handle serverExternalPackages)
- starter-crewai-crews: bump ag-ui-protocol>=0.1.10 to match
ag-ui-crewai 0.1.5 requirement
- shell-dojolike: add recharts dependency (used by shared frontend)
- Remove test-integration-tmp from workflow (package was deleted)
- starter-langgraph-python: disable Turbopack for Next.js build
(serverExternalPackages incompatible with Turbopack)
- starter-crewai-crews: pin crewai-tools~=0.47.1 to avoid version
conflict with crewai==0.130.0
- shell-dojolike: add missing zod dependency (required by shared
frontend modules)
Templates were pinned at old @ag-ui/client versions (0.0.40–0.0.46).
@copilotkit/runtime@1.55.2 ships 0.0.52, which added private fields to
AbstractAgent. The version split caused a nominal type error on build.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Templates had stale pinned versions ranging from 1.9.3 to 1.52.1.
The CLI does a verbatim sparse checkout of these files, so users
scaffolding via `copilotkit create` were getting old versions installed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Source route.ts files now read process.env.AGENT_URL natively (PR #3737),
so the build-time sed patches and verification greps are no longer needed.
Also removes crewai-crews docker-route-override.ts and its COPY line,
since that starter's route.ts already has AGENT_URL support.
## Summary
Adds **factory mode** to `BuiltInAgent`, enabling backend-agnostic LLM
integration without introducing a new class. Users provide a factory
function that creates the LLM stream — CopilotKit handles lifecycle
events, stream-to-AG-UI conversion, error handling, and
abort/cancellation.
### What's included
- **Three backend types**: `aisdk` (Vercel AI SDK), `tanstack` (TanStack
AI), and `custom` (raw AG-UI events)
- **Stream converters**: `convertAISDKStream` and
`convertTanStackStream` extract AG-UI events from backend-native streams
- **Input helpers**: `convertInputToTanStackAI` and
`convertMessagesToVercelAISDKMessages` for message/prompt conversion
- **State management**: Automatic `STATE_SNAPSHOT`/`STATE_DELTA` event
extraction from tool results
- **Reasoning support**: Auto-close logic for providers that never emit
`reasoning-end` (e.g. `@ai-sdk/anthropic`)
- **273 tests** across 16 test files covering all backend types,
converters, state tools, multimodal, and edge cases
- **Docs**: Comprehensive factory mode guide with 16 examples covering
tools, reasoning, state, forwardedProps, structured output
- **Example app**: React Router example migrated to factory mode
### Architecture
Factory mode is a discriminated union on `BuiltInAgentConfiguration`:
```typescript
const agent = new BuiltInAgent({
type: "aisdk", // or "tanstack" | "custom"
factory: ({ input, abortSignal }) =>
streamText({ model: openai("gpt-4o"), messages: ..., abortSignal }),
});
```
No new public classes — `BuiltInAgent` handles both simple mode (model
string) and factory mode (user-owned LLM call).
## PR feedback addressed
### Critical fixes
- **C1/M3**: Fixed TOCTOU window — `abortController` now set
synchronously before Observable creation in classic `run()`, with
concurrent run guard
- **C2/M2**: Classic `tool-result` now checks both `output` and `result`
property names, with `try/catch` on `JSON.stringify`
- **C3**: Error case safely handles `undefined` `p.error` with proper
fallback chain
### Important fixes
- **I2**: `RUN_ERROR` events now include `threadId` and `runId` in
classic mode (matching factory mode)
- **I3**: State tool events guarded against `undefined` snapshot/delta
before emitting
- **I4**: `JSON.stringify` wrapped in try/catch with descriptive
fallback message
- **M1**: `assignToolsToAgents` now skips factory-mode agents (prevents
config corruption)
- **M5**: TanStack converter's dropped event types documented with clear
limitation note
### Suggestions addressed
- **S1**: `@ts-expect-error` on `clone()` middlewares documented with
rationale
- **M4**: `AgentFactoryContext.abortController` kept (needed by TanStack
AI) but JSDoc added discouraging direct `.abort()` calls
## Test plan
- [x] 273 unit tests pass across all 3 backend types
- [x] Build succeeds
- [x] React Router example compiles
- [x] Docs render correctly (Vercel preview)
## Summary
Adds a `/health` GET endpoint returning `{"status": "ok"}` to all 11
starter integration examples. This is a best practice for any deployed
service — health checks enable platform health monitoring, load balancer
probes, and container lifecycle management.
**11 starters updated:**
- adk, agent-spec, agno, crewai-crews, crewai-flows, langgraph-fastapi,
llamaindex, ms-agent-framework-dotnet, ms-agent-framework-python,
pydantic-ai, strands-python
**1 skipped:**
- langgraph-python — uses `langgraph dev` which provides its own `/ok`
endpoint
All `/health` endpoints are registered before any catch-all mount to
ensure they take priority (lesson learned from the pydantic-ai showcase
bug).
## Test plan
- [ ] Each starter builds successfully
- [ ] `curl localhost:8000/health` returns `{"status": "ok"}` on each
## Summary
- **Configurable agent URL**: All starter `route.ts` files now read
`AGENT_URL` from environment with localhost fallback, enabling
deployment to non-localhost environments without code changes. Applied
to: pydantic-ai, adk, agno, llamaindex, ms-agent-framework-python,
ms-agent-framework-dotnet, crewai-crews.
- **crewai-crews version bump**: Bumped `ag-ui-crewai` from pinned
`==0.1.3` to `>=0.1.5` to pick up the `MethodExecutionFinishedEvent`
dict state fix from ag-ui-protocol/ag-ui#1478.
- **`.env.example` files**: Added `.env.example` with `OPENAI_API_KEY`
and `AGENT_URL` (correct default port per starter) to all affected
starters.
## Starters NOT touched (already configurable or different pattern)
- strands-python (uses `STRANDS_AGENT_URL`)
- langgraph-python / langgraph-js (use `LANGGRAPH_DEPLOYMENT_URL`)
- langgraph-fastapi (has docker-route-override)
- mastra (monolith, no separate agent URL)
## Test plan
- [ ] Verify each starter builds with `next build`
- [ ] Verify `AGENT_URL` env var is respected when set
- [ ] Verify localhost fallback works when `AGENT_URL` is unset
- [ ] Verify crewai-crews agent installs with `ag-ui-crewai>=0.1.5`
The starter pinned ag-ui-crewai==0.1.3 which crashes on crew completion:
'dict' object has no attribute 'messages' in MethodExecutionFinishedEvent
handler. Fixed upstream in ag-ui-protocol/ag-ui#1478, released in 0.1.5.
Every starter's route.ts now reads process.env.AGENT_URL as the
primary agent endpoint, with framework-specific vars as fallback:
- AGENT_URL || "http://localhost:8000" (pydantic-ai, adk, agno, crewai,
ms-agent-python, ms-agent-dotnet, strands-python)
- AGENT_URL || LANGGRAPH_DEPLOYMENT_URL || "http://localhost:8123"
(langgraph-python, langgraph-js)
- AGENT_URL || "http://localhost:9000" (llamaindex)
Also adds .env.example with AGENT_URL to all starters.