Skip to content

AI Workflow

AgentReady Stack is built from the ground up for AI-assisted development. Point Claude, Cursor, or ChatGPT at this codebase and watch them write code that actually works.

The Core Idea

Most codebases fail with AI agents because:

  • AI doesn't know your architecture
  • AI creates types that don't match your backend
  • AI puts code in the wrong places
  • AI-generated code breaks your tests

AgentReady Stack solves this with AGENTS.md—a comprehensive guide that AI agents read before writing code. When Claude reads your codebase, it reads AGENTS.md first and follows the patterns.

The AGENTS.md File

At the root of the repository, AGENTS.md contains instructions for AI agents:

markdown
# INSTRUCTIONS FOR AI AGENTS

When writing code for this repository, you MUST strictly adhere
to the following architectural constraints...

How Different AI Tools Discover AGENTS.md

ToolDiscovery Method
Claude CodeReads CLAUDE.md automatically, which references AGENTS.md
CursorReads .cursorrules which summarizes and references AGENTS.md
ChatGPT/OtherReads README.md which prominently links to AGENTS.md

All three discovery files are configured to direct agents to AGENTS.md for complete guidelines.

The Golden Rule: Type Flow

The most important pattern in AgentReady Stack:

Backend DTOs → OpenAPI → Generated Client → Frontend/CLI

AI agents must never:

  • Create duplicate types in the frontend
  • Manually write API response interfaces
  • Skip running pnpm codegen after backend changes

AI agents should always:

  • Define types as DTOs in the backend first
  • Use @ApiProperty() decorators for OpenAPI
  • Import types from @platform/api-client

Feature Scaffolding Workflow

When you ask an AI to add a new feature, it follows this order:

1. Create Backend DTOs

typescript
// apps/api/src/products/dto/create-product.dto.ts
export class CreateProductDto {
  @ApiProperty()
  @IsString()
  name!: string;

  @ApiPropertyOptional()
  @IsNumber()
  price?: number;
}

2. Create Backend Module

typescript
// apps/api/src/products/products.controller.ts
@ApiTags('Products')
@Controller('products')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
export class ProductsController {
  @Post()
  async create(@Body() dto: CreateProductDto) {
    return this.service.create(dto);
  }
}

3. Create Database Entity

typescript
// packages/database/src/entities/product.entity.ts
@Entity()
export class ProductEntity extends BaseEntity {
  @Property()
  name!: string;

  @Property({ nullable: true })
  price?: number;
}

4. Regenerate API Client

bash
pnpm codegen

5. Create Frontend Route

typescript
// apps/web/app/routes/products.tsx
export async function loader({ request }: Route.LoaderArgs) {
  const session = await requireUser(request);
  const products = await getProducts(session.accessToken);
  return { products };
}

export default function Products() {
  const { products } = useLoaderData<typeof loader>();
  return <ProductList items={products} />;
}

6. (Optional) Create CLI Command

typescript
// apps/cli/src/commands/products/list.ts
export default class ListProducts extends AuthenticatedCommand {
  async run() {
    const products = await this.apiClient.getProducts();
    this.table(products, { name: {}, price: {} });
  }
}

Layer-Specific Patterns

Backend Rules

RuleWhy
Always use @UseGuards(JwtAuthGuard) on protected endpointsSecurity
Transform entities to DTOs in controllersNever leak database structure
Use class-validator decoratorsAutomatic validation
Add @ApiProperty() decoratorsOpenAPI generation

Frontend Rules

RuleWhy
Fetch data in loader, never in useEffectSSR and performance
Mutations in action functionsReact Router pattern
Use typeof loader for type inferenceType safety
Return errors from actions, don't throwBetter UX

CLI Rules

RuleWhy
Extend AuthenticatedCommand for protected commandsAutomatic credential handling
Use ApiClient class for API callsConsistent auth headers
No business logic in command filesSeparation of concerns

Testing Patterns

AI agents write tests that follow these patterns:

Backend Unit Tests

typescript
describe('ProductsService', () => {
  let service: ProductsService;
  let mockRepo: ReturnType<typeof createMockRepository>;

  beforeEach(async () => {
    mockRepo = createMockRepository();
    const module = await Test.createTestingModule({
      providers: [
        ProductsService,
        { provide: getRepositoryToken(ProductEntity), useValue: mockRepo },
      ],
    }).compile();
    service = module.get(ProductsService);
  });

  it('should create a product', async () => {
    mockRepo.create.mockReturnValue({ id: '1', name: 'Test' });
    const result = await service.create({ name: 'Test' });
    expect(result.name).toBe('Test');
  });
});

Frontend Component Tests

typescript
vi.mock('react-router', async () => {
  const actual = await vi.importActual('react-router');
  return {
    ...actual,
    useLoaderData: () => ({ products: [{ id: '1', name: 'Test' }] }),
  };
});

describe('Products', () => {
  it('renders product list', () => {
    render(<Products />);
    expect(screen.getByText('Test')).toBeInTheDocument();
  });
});

Common Commands Reference

AI agents use these commands frequently:

bash
# Start development
pnpm dev

# After changing backend DTOs
pnpm codegen

# Type check everything
pnpm typecheck

# Run all tests
pnpm test

# Run E2E tests
pnpm test:e2e

# Start specific app
pnpm --filter @platform/api dev
pnpm --filter @platform/web dev

Tips for Working with AI

  1. Be specific about the layer: "Add a backend endpoint" vs "Add a frontend page"
  2. Mention the type flow: "Create the DTO first, then I'll run codegen"
  3. Reference existing patterns: "Follow the organization module pattern"
  4. Ask for tests: "Include unit tests following the existing patterns"

The Result

With AgentReady Stack:

  • AI writes code that fits — No more fighting hallucinations
  • Tests catch mistakes — AI-generated code is verified automatically
  • Types stay in sync — Change once, propagate everywhere
  • You ship faster — Hours instead of weeks

Example Prompts That Work

Here are prompts you can give Claude right after setup:

"Add a projects feature similar to organizations. Projects belong to
an organization and have a name, description, and status."
"Create a CLI command to list all projects in the current organization."
"Add a frontend page that shows all projects with a create button."

Claude will read AGENTS.md, understand the patterns, and write code that fits.