flare-agent Bài 2: Thiết kế Types & Interfaces — Nền tảng của mọi abstraction
Hướng dẫn thiết kế @flare-agent/types — package zero-dependency định nghĩa toàn bộ interfaces cho LLM, Agent, Tool, Memory và Runtime của framework.
flare-agent Bài 2: Thiết kế Types & Interfaces
Series: Build Your Own AI Agent Framework trên Cloudflare Bài: 2 / 7 —
@flare-agent/types
Tại sao Types là bài đầu tiên?
Trong một framework, interfaces là hợp đồng giữa các layer. Nếu interfaces sai, mọi thứ phía trên sẽ sai theo.
@flare-agent/types là package duy nhất không có dependency nào — nó chỉ export TypeScript interfaces và types. Mọi package khác đều import từ đây.
Cấu trúc package
packages/types/
src/
llm.ts # Message, LLMResponse, LLMProvider
agent.ts # AgentConfig, AgentContext
tool.ts # ToolSchema, ToolDefinition
memory.ts # MemoryAdapter
runtime.ts # AgentRuntime (Cloudflare abstraction)
workflow.ts # WorkflowDefinition, Step
index.ts
package.json
tsconfig.json
LLM Types
// src/llm.ts
export type Role = 'system' | 'user' | 'assistant' | 'tool';
export interface Message {
role: Role;
content: string;
toolCallId?: string; // khi role = 'tool'
name?: string;
}
export interface ToolCall {
id: string;
name: string;
args: Record<string, unknown>;
}
export interface LLMResponse {
type: 'text' | 'tool_call';
content?: string;
toolCall?: ToolCall;
}
// Interface mọi provider phải implement
export interface LLMProvider {
chat(
messages: Message[],
tools?: ToolSchema[]
): Promise<LLMResponse>;
stream(
messages: Message[],
tools?: ToolSchema[]
): ReadableStream<string>;
}
Tool Types
// src/tool.ts
export interface ToolSchema {
name: string;
description: string;
parameters: {
type: 'object';
properties: Record<string, unknown>;
required?: string[];
};
}
// Generic để type-safe args và result
export interface ToolDefinition<
TArgs = Record<string, unknown>,
TResult = unknown
> {
schema: ToolSchema;
execute: (args: TArgs, ctx: AgentContext) => Promise<TResult>;
}
Agent Types
// src/agent.ts
import type { ToolDefinition } from './tool';
export type ProviderName = 'workersai' | 'groq' | 'ollama';
export interface ModelConfig {
provider: ProviderName;
model: string;
}
export interface AgentConfig {
name: string;
model: ModelConfig;
systemPrompt?: string | ((ctx: AgentContext) => string);
tools?: ToolDefinition[];
memory?: 'kv' | 'd1' | 'none';
maxIterations?: number;
}
// Context được inject vào mỗi agent run
export interface AgentContext {
sessionId: string;
userId?: string;
env: Record<string, unknown>;
metadata?: Record<string, unknown>;
}
export interface AgentResult {
output: string;
iterations: number;
toolCalls: Array<{ name: string; args: unknown; result: unknown }>;
}
Memory Types
// src/memory.ts
import type { Message } from './llm';
export interface MemoryAdapter {
getMessages(sessionId: string): Promise<Message[]>;
addMessage(sessionId: string, message: Message): Promise<void>;
clearSession(sessionId: string): Promise<void>;
}
export interface VectorAdapter {
insert(vectors: VectorItem[]): Promise<void>;
query(vector: number[], topK: number): Promise<VectorMatch[]>;
delete(ids: string[]): Promise<void>;
}
export interface VectorItem {
id: string;
values: number[];
metadata?: Record<string, unknown>;
}
export interface VectorMatch {
id: string;
score: number;
metadata?: Record<string, unknown>;
}
Runtime Types — chống lock-in Cloudflare
Đây là interface quan trọng nhất — nó abstract hóa Cloudflare primitives để core không phụ thuộc trực tiếp:
// src/runtime.ts
export interface AgentRuntime {
// Persistent state (Durable Object storage)
getState<T>(key: string): Promise<T | null>;
setState<T>(key: string, value: T): Promise<void>;
deleteState(key: string): Promise<void>;
// Scheduling
scheduleTask(
delayMs: number,
taskName: string,
payload: unknown
): Promise<string>; // returns taskId
cancelTask(taskId: string): Promise<void>;
// Real-time messaging
sendToClient(connectionId: string, data: unknown): Promise<void>;
broadcast(data: unknown): Promise<void>;
}
Khi Cloudflare thay đổi API, chỉ cần sửa CloudflareRuntime implements AgentRuntime — core không đổi gì.
Workflow Types
// src/workflow.ts
export interface WorkflowStep<TInput = unknown, TOutput = unknown> {
name: string;
execute(
input: TInput,
ctx: WorkflowContext
): Promise<TOutput>;
}
export interface WorkflowContext {
agentCtx: AgentContext;
results: Record<string, unknown>; // kết quả từ steps trước
metadata: Record<string, unknown>;
}
export interface WorkflowDefinition {
name: string;
steps: WorkflowStep[];
// Hàm quyết định step tiếp theo dựa trên kết quả
next?: (
stepName: string,
result: unknown,
ctx: WorkflowContext
) => string | null; // null = kết thúc
}
package.json
{
"name": "@flare-agent/types",
"version": "0.1.0",
"type": "module",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
}
},
"scripts": {
"build": "tsup src/index.ts --format esm --dts",
"dev": "tsup src/index.ts --format esm --dts --watch"
},
"devDependencies": {
"tsup": "^8.0.0",
"typescript": "^5.0.0"
}
}
Chú ý: Package này zero runtime dependencies — chỉ có
devDependencies.
Checklist trước khi sang bài 3
- Scaffold Turborepo monorepo với pnpm
- Tạo
packages/types/ - Viết đủ 6 files:
llm.ts,tool.ts,agent.ts,memory.ts,runtime.ts,workflow.ts - Build thành công, không có TypeScript error
Bài tiếp theo: Bài 3 — LLM Router: Groq, Workers AI, Ollama trong 1 interface