AI Agent Project Structure: Repository, Scripts and TypeScript Setup
When every file has an obvious home, a project stays easy to change. A clear AI agent project structure also helps an AI assistant work on one part without touching the rest. In this lesson you will install the tools, create the folders and add the scripts that you will use in every later lesson.
📖 What You’ll Learn
- How to organise an agent project
- Which packages you need, and why
- How to configure TypeScript and ESLint
- How to validate settings when the program starts
💡 The AI Agent Project Structure
Explain Like I’m 5: A Tidy Toy Box
Imagine: Cars go in one box and bricks in another. When you need a car, you know exactly where to look.
What it really means: Each kind of file has its own folder.
In testing: Agents, tools and validators never get mixed together.
qa-automation-ai-agent/
demo/ A small login page to test against
requirements/ Plain-text requirements
src/
app.ts The program's starting point
config/ Settings and project facts
core/ Orchestrator, guardrails, approvals, types
agents/ One file per agent
llm/ Model access, kept in one place
schemas/ Runtime contracts
tools/ Browser, file and test-runner tools
validators/ Checks on scenarios and generated code
evaluation/ Quality metrics and scoring
tests/
unit/ Fast tests with no browser
generated/ AI-written tests, after approval
artifacts/ Traces, screenshots and run state
reports/ Run reports
Keeping tests/generated/ separate is a safety feature. It is the only folder that the agent may write to.
🔍 Install the Packages
npm install zod dotenv
npm install -D typescript tsx @types/node @playwright/test eslint @eslint/js typescript-eslint
npx playwright install chromium
| Package | Job |
|---|---|
zod | Checks data at runtime |
dotenv | Loads your .env file |
typescript and tsx | Type-check and run TypeScript |
@playwright/test | Runs the browser tests |
eslint and its plugins | Finds code problems |
This project was tested with Playwright 1.65, TypeScript 6.0, Zod 4.6 and ESLint 10. If a command behaves differently, compare your versions with these.
Do not accept package lists blindly
AI assistants can suggest old or even non-existent packages. Check each name and read what it does before you install it.
🧩 Configure TypeScript
Explain Like I’m 5: Spelling Rules
Imagine: A strict teacher marks every mistake, so you learn quickly and your work gets better.
What it really means: Strict settings find problems before the code runs.
In testing: TypeScript reports a missing field before a test ever starts.
Create tsconfig.json.
{
"compilerOptions": {
"target": "ES2023",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"types": ["node"],
"strict": true,
"noEmit": true,
"skipLibCheck": true
},
"include": ["src", "tests", "demo", "scripts", "playwright.config.ts"]
}
Now create eslint.config.mjs.
import js from '@eslint/js';
import { defineConfig, globalIgnores } from 'eslint/config';
import tseslint from 'typescript-eslint';
export default defineConfig([
globalIgnores(['artifacts/', 'reports/', 'playwright-report/', 'test-results/']),
js.configs.recommended,
tseslint.configs.recommended,
]);
🛠️ Add the Scripts
Run this once to add your project’s commands.
npm pkg set scripts.typecheck="tsc --noEmit" scripts.lint="eslint ." scripts.test="playwright test" scripts.test:report="playwright show-report" scripts.test:unit="tsx --test tests/unit/*.test.ts" scripts.demo="tsx demo/server.ts" scripts.agent="tsx src/app.ts"
| Script | What it does |
|---|---|
npm run typecheck | Finds type errors |
npm run lint | Finds code problems |
npm test | Runs Playwright tests |
npm run test:unit | Runs fast tests with no browser |
npm run demo | Starts the demo login page |
npm run agent | Runs the whole agent |
📌 Validate Settings at Startup
Explain Like I’m 5: Checking Your Ticket
Imagine: The ticket inspector checks your ticket at the start of the journey, not halfway there.
What it really means: Check every setting when the program starts.
In testing: A missing test URL stops the agent immediately.
You practised this in LLM Structured Output. Create src/config/env.ts.
import 'dotenv/config';
import * as z from 'zod';
const EnvSchema = z.object({
LLM_PROVIDER: z.enum(['mock', 'anthropic']).default('mock'),
LLM_MODEL: z.string().default(''),
LLM_API_KEY: z.string().default(''),
BASE_URL: z.url(),
HEADLESS: z.enum(['true', 'false']).default('true'),
ALLOW_TEST_EXECUTION: z.enum(['true', 'false']).default('false'),
});
export type Env = z.infer<typeof EnvSchema>;
export function loadEnv(): Env {
return EnvSchema.parse(process.env);
}
Now one wrong setting fails with a clear message. It cannot cause a confusing error later.
🌍 Real-Life Example: The Missing Setting
A pipeline runs with BASE_URL unset. The tests try to open an undefined address and fail with a strange error, and a tester spends an hour on it. A schema check at startup reports the missing setting in one line.
🧪 Try It Yourself
- Create the folders shown in the structure.
- Install the packages and browser.
- Add both config files and the scripts.
- Run
npm run typecheckandnpm run lint. - Delete
BASE_URLfrom.envfor a moment, and predict whatloadEnvwill do.
📋 Ready-to-Copy Prompt
You are a senior TypeScript engineer reviewing a project setup.
My package.json:
[paste it]
My tsconfig.json:
[paste it]
Check that the packages are compatible and that nothing is unnecessary.
Explain in simple words what each dependency does.
Only suggest package names that you are sure exist. Tell me to confirm
current versions on the official package pages.
⚠️ Common Mistakes
- Mixing agents, tools and prompts in one folder
- Turning off strict TypeScript to remove errors
- Installing packages suggested by AI without checking them
- Letting an agent write anywhere in the repository
- Reading settings with no validation
🎯 Key Takeaways
- A clear structure keeps responsibilities separate.
- Generated tests get their own limited folder.
- Strict checks find problems early.
- Validate configuration as soon as the program starts.
🎤 Interview Questions
1. How would you structure an AI agent project?
Model answer: I would separate agents, tools, validators, schemas and model access into their own folders. Each has one responsibility, which makes them easier to test and to change.
2. Why keep generated tests in a separate folder?
Model answer: It lets me limit the agent’s write access to one place. It also makes generated code easy to review and easy to distinguish from hand-written tests.
3. Why validate environment variables at startup?
Model answer: It makes the program fail quickly with a clear reason. Otherwise, a missing setting can cause confusing failures much later.
4. Why use strict TypeScript?
Model answer: It catches missing fields and wrong types before the code runs. That is especially valuable when connecting many components through contracts.
5. How do you check packages suggested by an AI assistant?
Model answer: I confirm that the package exists on the official registry, check its publisher and maintenance, and read what it does. AI can suggest outdated or invented packages.
📝 Assignment
Complete the setup so that npm run typecheck and npm run lint both pass. Add a section to your README that explains what each top-level folder is for. Then read about TypeScript variables if any of the types look unfamiliar.
❓ FAQ
Why ES modules?
They are the modern JavaScript standard, and the MCP SDK used later ships only as ES modules.
Why do my imports end in .js when the files end in .ts?
With this configuration, TypeScript expects the name of the file that will exist after compiling. The tsx tool maps it back to your .ts file.
🚀 Next Steps
Well done on finishing this lesson. Complete the assignment, then continue with Deterministic Playwright Tests: The Foundation of Your QA Agent.