Add advanced agent orchestration examples (#313) - #314
Conversation
📝 WalkthroughWalkthroughThe PR adds runnable agent-coordination examples to the Convex example application. The backend implements dynamic routing, parallel fan-out, sequential orchestration, bounded ReAct reasoning, agent networks, and a durable review workflow. The workflow supports start, resume, and status operations. An integration test checks agent handoff order. The UI exposes these patterns at Sequence Diagram(s)sequenceDiagram
participant User
participant AgentCoordination
participant ConvexActions
participant AgentNetwork
User->>AgentCoordination: Select pattern and enter prompt
AgentCoordination->>ConvexActions: Execute coordination action
ConvexActions->>AgentNetwork: Run agent turns
AgentNetwork-->>ConvexActions: Agent outputs and traces
ConvexActions-->>AgentCoordination: Combined result
AgentCoordination-->>User: Display result and agent traces
sequenceDiagram
participant User
participant AgentCoordination
participant startReviewWorkflow
participant reviewWorkflow
participant resumeReviewWorkflow
User->>AgentCoordination: Start review with prompt
AgentCoordination->>startReviewWorkflow: Submit prompt
startReviewWorkflow->>reviewWorkflow: Start durable workflow
reviewWorkflow-->>AgentCoordination: Waiting status
User->>AgentCoordination: Submit feedback
AgentCoordination->>resumeReviewWorkflow: Submit workflowId and feedback
resumeReviewWorkflow->>reviewWorkflow: Resume workflow
reviewWorkflow-->>AgentCoordination: Revised response and status
AgentCoordination-->>User: Display revised response
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
example/convex/workflows/coordination.ts (1)
289-309: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueThrow in the exhaustiveness branch instead of returning the status object.
status satisfies neveris a compile-time assertion only. If a future version of@convex-dev/workflowadds a status type, this branch returns the raw status object at runtime, which does not match thereturnsvalidator and surfaces as an opaque validation error. Throwing gives a clear message.♻️ Proposed change
default: - return status satisfies never; + throw new Error( + `Unexpected workflow status: ${(status satisfies never as { type: string }).type}`, + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@example/convex/workflows/coordination.ts` around lines 289 - 309, Update the default branch of the workflow status switch in the handler to throw a descriptive error for unknown status types instead of returning status after the satisfies never assertion. Preserve the compile-time exhaustiveness check while ensuring unexpected future statuses fail explicitly at runtime.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@example/convex/workflows/coordination.test.ts`:
- Around line 6-18: Update the orchestration test around orchestrate to supply a
deterministic test-only mock model through the action configuration or supported
model override. Ensure all agent handoffs use the mock instead of
defaultConfig’s live Anthropic, OpenAI, or Groq selection, while preserving the
existing agent-order assertion.
In `@example/ui/workflows/AgentCoordination.tsx`:
- Line 167: Update the reset handler in AgentCoordination to clear the current
error state as well as workflowId, so “Start over” removes failures from
startReview or resumeReview. Render the reset button for every workflow state
whenever workflowId exists, including waiting and running, while preserving the
existing completed, failed, and canceled behavior; ensure the pattern selector
remains disabled while an active workflow exists.
---
Nitpick comments:
In `@example/convex/workflows/coordination.ts`:
- Around line 289-309: Update the default branch of the workflow status switch
in the handler to throw a descriptive error for unknown status types instead of
returning status after the satisfies never assertion. Preserve the compile-time
exhaustiveness check while ensuring unexpected future statuses fail explicitly
at runtime.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: get-convex/coderabbit/.coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: f6c31b91-9efc-4bf8-a00a-d0dfdd3510ad
⛔ Files ignored due to path filters (1)
example/convex/_generated/api.d.tsis excluded by!**/_generated/**
📒 Files selected for processing (4)
example/convex/workflows/coordination.test.tsexample/convex/workflows/coordination.tsexample/ui/main.tsxexample/ui/workflows/AgentCoordination.tsx
| test("orchestration preserves the planned agent handoff", async () => { | ||
| const result = await initConvexTest().action( | ||
| api.workflows.coordination.orchestrate, | ||
| { prompt: "Plan a small release" }, | ||
| ); | ||
|
|
||
| expect(result.steps.map(({ agent }) => agent)).toEqual([ | ||
| "coordinator", | ||
| "analyst", | ||
| "critic", | ||
| "coordinator", | ||
| ]); | ||
| }); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Determine which language model the example agents use under test.
fd -t f 'config.ts' example/convex | xargs -r cat -n
rg -n 'MockLanguageModel|mock|languageModel' example/convex --glob '!**/node_modules/**' -C2Repository: get-convex/agent
Length of output: 6241
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- coordination test ---'
cat -n example/convex/workflows/coordination.test.ts
printf '%s\n' '--- coordination implementation ---'
fd -t f . example/convex/workflows | sort
rg -n 'orchestrate|generateText|Agent|defaultConfig|languageModel|initConvexTest' example/convex/workflows example/convex/agents example/convex --glob '*.ts' -C3
printf '%s\n' '--- model selection ---'
cat -n example/convex/modelsForDemo.ts
printf '%s\n' '--- test and package configuration ---'
fd -t f 'package.json|vitest.config.*|vite.config.*|test*.ts' . | sort | head -80
rg -n 'vitest|convexTest|environment|ANTHROPIC_API_KEY|OPENAI_API_KEY|GROQ_API_KEY' package.json example package.json .github --glob '*.json' --glob '*.ts' --glob '*.yml' --glob '*.yaml' -C2Repository: get-convex/agent
Length of output: 50373
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- model selection source ---'
cat -n example/convex/modelsForDemo.ts
printf '%s\n' '--- test setup ---'
cat -n example/convex/setup.test.ts
printf '%s\n' '--- coordination orchestration ---'
sed -n '140,166p' example/convex/workflows/coordination.ts
printf '%s\n' '--- test commands and CI environment ---'
rg -n 'example|vitest|convex test|API_KEY|ANTHROPIC|OPENAI|GROQ' \
package.json example/package.json .github --glob '*.json' --glob '*.yml' --glob '*.yaml' --glob '*.ts' -C2 || true
printf '%s\n' '--- environment-dependent model verifier ---'
python3 - <<'PY'
from pathlib import Path
import re
source = Path("example/convex/modelsForDemo.ts").read_text()
branches = re.findall(
r'if \(process\.env\.([A-Z0-9_]+)\).*?languageModel = ([^;]+);',
source,
flags=re.S,
)
print("branches:", [(name, expr.strip()) for name, expr in branches])
for env in ({}, {"ANTHROPIC_API_KEY": "x"}, {"OPENAI_API_KEY": "x"}, {"GROQ_API_KEY": "x"}):
selected = "mockModel({})"
for name, expr in branches:
if env.get(name):
selected = expr.strip()
break
print("env =", sorted(env), "=>", selected)
print("orchestrate generateText calls:", len(re.findall(r'\.generateText\(', Path("example/convex/workflows/coordination.ts").read_text()[Path("example/convex/workflows/coordination.ts").read_text().find("export const orchestrate"):]))
PYRepository: get-convex/agent
Length of output: 5728
🏁 Script executed:
#!/bin/bash
set -e
printf '%s\n' '--- repository test and CI configuration ---'
find .github -maxdepth 3 -type f -print 2>/dev/null | sort || true
rg -n 'vitest|npm test|API_KEY|ANTHROPIC|OPENAI|GROQ|environment|env:' \
package.json .github example --glob '*.json' --glob '*.yml' --glob '*.yaml' --glob '*.ts' -C2 || true
printf '%s\n' '--- deterministic model-selection check ---'
python3 - <<'PY'
from pathlib import Path
source = Path("example/convex/modelsForDemo.ts").read_text()
checks = [
("ANTHROPIC_API_KEY", 'anthropic.chat("claude-opus-4-20250514")'),
("OPENAI_API_KEY", 'openai.chat("gpt-4o-mini")'),
("GROQ_API_KEY", 'groq.languageModel('),
]
for env_name, model in checks:
print(f"{env_name}: live provider branch present -> {model}")
print("fallback: languageModel = mockModel({})")
orchestrate = Path("example/convex/workflows/coordination.ts").read_text()
start = orchestrate.index("export const orchestrate")
end = orchestrate.index("\n});", start)
body = orchestrate[start:end]
print("orchestrate generateText calls:", body.count(".generateText("))
print("test model override:", "languageModel:" in Path("example/convex/workflows/coordination.test.ts").read_text())
PYRepository: get-convex/agent
Length of output: 5210
Use a test-only mock model for orchestrate. defaultConfig selects a live Anthropic, OpenAI, or Groq model when the corresponding API key exists. The test has no model override, so it can make four live network calls.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@example/convex/workflows/coordination.test.ts` around lines 6 - 18, Update
the orchestration test around orchestrate to supply a deterministic test-only
mock model through the action configuration or supported model override. Ensure
all agent handoffs use the mock instead of defaultConfig’s live Anthropic,
OpenAI, or Groq selection, while preserving the existing agent-order assertion.
| onChange={(event) => | ||
| selectPattern(event.target.value as PatternId) | ||
| } | ||
| disabled={loading || workflowId !== null} |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Clear the error on reset and allow an escape from a waiting workflow.
Two related gaps in the pause/resume flow:
resetclears onlyworkflowId. IfstartRevieworresumeReviewfailed, the error banner stays visible after the user clicks "Start over".- The pattern selector is disabled while
workflowId !== null, and the reset button renders only forcompleted,failed, andcanceled. If the workflow stays inwaitingorrunning, the user cannot leave the pattern.
🐛 Proposed fix
- disabled={loading || workflowId !== null}
+ disabled={loading}- reset={() => setWorkflowId(null)}
+ reset={() => {
+ setWorkflowId(null);
+ setError(null);
+ }}Also render the reset button for every state once a workflow exists, so a waiting workflow can be abandoned.
Also applies to: 211-211
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@example/ui/workflows/AgentCoordination.tsx` at line 167, Update the reset
handler in AgentCoordination to clear the current error state as well as
workflowId, so “Start over” removes failures from startReview or resumeReview.
Render the reset button for every workflow state whenever workflowId exists,
including waiting and running, while preserving the existing completed, failed,
and canceled behavior; ensure the pattern selector remains disabled while an
active workflow exists.
Closes #313
Issue: #313
What changed
Validation
npm run typechecknpm run lintnpm test— 29 files, 290 tests passednpm run buildCONVEX_AGENT_MODE=anonymous npx convex dev --oncenpx convex run workflows/coordination:orchestrate '{"prompt":"Plan a small release"}'— returned the coordinator → analyst → critic → coordinator handoff\n- Browser verification: route loads with no Vite overlay or captured console errors; durable workflow reached waiting, resumed from feedback, and rendered its revised result; home-page link verified