Skip to content

Chapter 1 · Course Overview and Environment Setup ​

Chapter goals: Understand the division of labor between @earendil-works/pi-agent-core and @earendil-works/pi-ai, set up the TypeScript development environment, and run the first program.

1.1 What This Course Does ​

The two packages most relevant to you in the Pi ecosystem:

PackageResponsibilityAnalogy
@earendil-works/pi-aiUnified multi-provider LLM API: model catalog, auth, streaming, tool calls, token billingA "model adapter" layer
@earendil-works/pi-agent-coreStateful Agent runtime: tool execution loop, event streaming, state management, steering queueAn "Agent engine" layer

The layering relationship is very clear — pi-agent-core is built on top of pi-ai:

text
┌─────────────────────────────────┐
│   Your application (CLI / Web / Service)   │
├─────────────────────────────────┤
│   pi-agent-core                 │  ← Agent state machine + tool loop + events
│   (Agent / agentLoop)           │
├─────────────────────────────────┤
│   pi-ai                         │  ← Unified LLM call layer
│   (Models / stream / complete)  │
├─────────────────────────────────┤
│   OpenAI / Anthropic / Google…  │  ← Actual vendor APIs
└─────────────────────────────────┘

Why not write directly with each vendor's official SDK

Because once you want to switch models or do cross-provider switching, each SDK has different message formats, tool protocols, and error semantics. pi-ai flattens these differences into a single unified interface — your business code pays zero refactoring cost for "switching models."

1.2 Initialize a TypeScript Project ​

bash
mkdir my-agent && cd my-agent
npm init -y
npm install @earendil-works/pi-agent-core @earendil-works/pi-ai
npm install -D typescript tsx @types/node

Create tsconfig.json:

jsonc
{
  "compilerOptions": {
    // Use NodeNext for correct ESM resolution behavior
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "target": "es2022",
    // Strict mode is required: pi's type system depends on strict checks
    "strict": true,
    "skipLibCheck": true,
    "outDir": "dist"
  },
  "include": ["src"]
}

Add a run script in package.json:

jsonc
{
  "scripts": {
    // Run TypeScript directly with tsx, skipping the compile step
    "start": "tsx src/index.ts"
  }
}

1.3 Hello World: Minimal Runnable Agent ​

Create src/index.ts:

typescript
// Import the Agent runtime and unified model collection
import { Agent } from "@earendil-works/pi-agent-core";
import { createModels } from "@earendil-works/pi-ai";
import { anthropicProvider } from "@earendil-works/pi-ai/providers/anthropic";

// Create the model collection and register the Anthropic provider
const models = createModels();
models.setProvider(anthropicProvider());

// Look up the specific model from the catalog (throws if not found)
const model = models.getModel("anthropic", "claude-sonnet-4-6");
if (!model) throw new Error("Model not found");

// Instantiate the Agent: inject system prompt, model, and stream function
const agent = new Agent({
  initialState: {
    systemPrompt: "You are a helpful assistant.",
    model,
  },
  streamFn: models.streamSimple.bind(models),
});

// Subscribe to the event stream: write incremental text to the terminal in real time
agent.subscribe((event) => {
  if (
    event.type === "message_update" &&
    event.assistantMessageEvent.type === "text_delta"
  ) {
    process.stdout.write(event.assistantMessageEvent.delta);
  }
});

// Send the first prompt
await agent.prompt("Introduce yourself in one sentence");

Make sure the API Key is set in environment variables before running:

bash
export ANTHROPIC_API_KEY=sk-ant-...
npm start

1.4 No Paid Key? Use the Faux Provider First ​

pi-ai ships a built-in fake provider for testing that validates the entire chain at zero cost:

typescript
// fauxProvider returns preset responses according to a script
import { createModels, fauxProvider } from "@earendil-works/pi-ai";
import { builtinModels } from "@earendil-works/pi-ai/providers/all";

// Approach 1: Register only faux (lightest)
const models = createModels();
const faux = fauxProvider();
models.setProvider(faux.provider);

// Approach 2: Register all built-in providers (including all real vendors besides faux)
const all = builtinModels();

console.log(faux.getModel()); // returns the first faux model

You will use it in unit tests throughout the subsequent chapters — get the logic running first, then plug in real models.

1.5 Learning Roadmap ​

ChapterTopic
02–03pi-ai basics: unified API, providers, and model catalog
04–05Agent essentials: instantiation, prompt, event streams
06–09Core: tool calls, message transformation, context transformation
10–15Advanced: auth, thinking/reasoning, images, error handling, custom providers, testing
16–20Production: Handoffs, persistence, browser usage, comprehensive projects

1.6 Chapter Summary ​

  • pi-ai is the unified LLM call layer; pi-agent-core is the stateful Agent runtime built on top of it;
  • The project requires a TypeScript config with strict: true; running directly with tsx is recommended;
  • A minimal Agent = Agent instance + initialState + streamFn;
  • When you don't have a key, fauxProvider() lets you wire up the full chain first.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. What is the relationship between pi-agent-core and pi-ai?

2. To create a minimal Agent instance, which configuration pair is required?

3. What should you use to verify code logic first when you don't have an API Key?

4. Why is it recommended to enable strict: true in tsconfig?

🛠️ Hands-on Practice ​

  1. Complete the environment setup in this chapter. Run Hello World with both ANTHROPIC_API_KEY (or any existing key) and fauxProvider(), and compare the output differences.
  2. Change the system prompt to "You are a pirate-style assistant" and observe how the response style changes.
  3. Read the exports field in node_modules/@earendil-works/pi-ai/package.json and list all sub-path entry points you can find.

With the environment ready, move on to Chapter 2 to dive deeper into pi-ai's unified API.