This guide covers Copilot Workspace with production-focused examples and trade-offs.
Cross-repo Copilot Workspace tasks fail in a predictable way: the model invents an endpoint that “should exist,” updates one service, and leaves the other on the old contract. Spec-driven tasks flip that — OpenAPI/AsyncAPI and fixture contracts are the source of truth; acceptance criteria name the services and the verify commands; agents may only implement symbols that already appear in the spec (or in a explicitly approved spec PR).⚡ TL;DR: Every Workspace task starts with a machine-readable contract + acceptance checklist. Generate typed clients from OpenAPI before coding. Forbid greenfield paths not in the spec. Run contract tests across service boundaries in CI. Humans merge spec changes first, then implementation tasks. Related: Cursor rules, AI PR reviewers, Express production APIs.
Task brief that survives microservice reality — Copilot Workspace
## Task: Add idempotent refund endpoint
### Spec
- OpenAPI: `services/payments/openapi.yaml#/paths/@/v1/refunds`
- Event: `refund.completed.v1` in `asyncapi.yaml`
### Acceptance
- [ ] Handler matches generated types from OpenAPI
- [ ] Contract test `refunds.contract.test.ts` green against mock + sandbox
- [ ] Orders service consumes `refund.completed.v1` without schema drift
- [ ] No new paths outside the OpenAPI file in this PR
### Verify
```bash
pnpm --filter @acme/payments test:contract
pnpm --filter @acme/orders test:contract -- --grep refund
</code></pre>
<pre><code>
```markdown
❌ Bad task: "wire refunds between payments and orders somehow"
Generate clients — don’t let the model invent them
# ✅ Spec first → types → implementation
pnpm openapi-typescript services/payments/openapi.yaml -o packages/payments-client/src/types.ts
pnpm --filter @acme/payments-client build
// orders/src/refunds.ts
import type { paths } from "@acme/payments-client/types";
type RefundBody = paths["/v1/refunds"]["post"]["requestBody"]["content"]["application/json"];
export async function requestRefund(body: RefundBody) {
// ✅ Only fields that exist on the generated type
return paymentsFetch("/v1/refunds", { method: "POST", body });
}
// ❌ Model-invented client
await fetch("https://payments/api/refundOrder", { body: JSON.stringify({ order: id }) });
Boundary rules inside the Workspace prompt
Encode service ownership so the agent does not “helpfully” edit both sides of a domain boundary in one chaotic diff — or if it must, require two stacked PRs.RULES:
- You may edit only: services/payments/** and packages/payments-client/**
- Spec PRs are separate: changes to openapi.yaml need label spec-change
- Do not add routes absent from openapi.yaml
- Prefer extending existing handlers over new micro-services
Contract tests as the merge gate
// payments/refunds.contract.test.ts
import { OpenAPIResponseValidator } from "openapi-response-validator";
import spec from "../openapi.yaml";
test("POST /v1/refunds matches response schema", async () => {
const res = await app.inject({ method: "POST", url: "/v1/refunds", payload: fixture });
const v = new OpenAPIResponseValidator({ responses: spec.paths["/v1/refunds"].post.responses });
// ✅ Fail closed on schema drift
expect(v.validateResponse(res.statusCode, res.json())).toBeUndefined();
});
Cross-repo orchestration pattern
| Step | Owner | Artifact |
|---|---|---|
| 1. Spec PR | Human + agent assist | OpenAPI/AsyncAPI diff |
| 2. Generate clients | CI | types package bump |
| 3. Provider impl task | Workspace | payments PR |
| 4. Consumer impl task | Workspace | orders PR |
| 5. Dual contract CI | CI | both greens |
Closing checklist
✅ Dos– ✅ Spec + acceptance + verify commands in every task brief
– ✅ Generate typed clients before implementation
– ✅ Separate spec PRs from impl PRs
– ✅ Contract tests across provider and consumer
– ✅ Scope Workspace file allowlists per service ❌ Don’ts
– ❌ Don’t invent URLs or payload fields absent from OpenAPI
– ❌ Don’t edit both sides of a boundary without stacked PRs
– ❌ Don’t accept “temporary any” on generated types
– ❌ Don’t merge consumer before provider contract is published
– ❌ Don’t skip fixture-based contract tests
Related reading
- Cursor Rules for TypeScript Monorepos: Make AI Edits Stick
- AI Code Review Bots: IAM, Secrets, and Least-Privilege Pipelines
- Express.js Best Practices: Build Production-Ready APIs With Node.js
- LLM Coding Agents on AWS: Safe Tool Sandboxes with Lambda
Related: Vibe Coding: The Professional Developer Guide to Cursor, Claude, and Copilot · PostgreSQL Performance Tuning: The Configuration Changes That Actually Matter · Amazon Q in IDE: Customizations That Respect CODEOWNERS Boundaries
Related: OpenTelemetry for LLMs: Trace Prompt Latency Across Microservices · Python asyncio vs Threading: The Benchmark That Changes How You Think About Concurrency · Claude Code: The Developer Workflow That Replaces 80% of Manual Coding Tasks
Watch: 100 Days of AI on YouTube
Short videos from CheatCoders, one AI engineering topic per day.
Most viewed
- Python Decorators Explained: From Simple Wrappers to Production Patterns
- Claude Code vs Cursor vs GitHub Copilot: Choose by Workflow, and Set Up One Repo That Works With All Three
- AI Agent Frameworks in 2025: LangGraph vs CrewAI vs AutoGen vs Raw API
- Python String Methods: Every str Method With Real Production Examples
- Css Animation Performance: Performance-Optimized Motion for Modern UIs
Newly added
- AWS Systems Manager Parameter Store: Hierarchical Runtime Config for Coding Agents
- Amazon Cognito Identity Pools: Federate Coding-Agent Tool Callers Without Long-Lived Keys
- Amazon Athena for Coding Agents: Query Tool Audit Logs and Eval Traces on S3 Without a Warehouse
- AWS Batch for Coding Agents: Parallel Overnight PR Reviews and Long-Running Jobs Without Lambda Timeouts
- Amazon Bedrock Prompt Management: Version and A/B Test Coding-Agent System Prompts
Deep-dive PDF
Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.
Already subscribed? or open the subscribe page.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
