AI Agents Technical Documentation
Implementation Details
Database Schema
// Agent Version
PK: "AGENT_VERSION"
SK: "{versionId}" // ULID
Data: {
name: string;
prompt: string;
previousVersion?: string;
changelog?: string;
timestamp: string;
hidden?: boolean;
}
// Tasks
PK: "AGENT_TASK"
SK: "{userEmail}#{taskId}" // ULID
Data: {
agentVersionId: string;
prompt: string;
timestamp: string;
isComplete: boolean;
error?: string;
parentTaskId?: string;
}
// Task Stream Parts
PK: "TASK_STREAM#{taskId}"
SK: "{partNumber}" // Padded sequential number
Data: StreamPart; // See StreamPart interface
// Agent Name to Version Mapping
PK: "AGENTS_BY_NAME/{userEmail}"
SK: "{agentName}"
Data: string; // Latest version ID
Architecture Decision Records (ADRs)
- Use Deno Fresh because it enables a quick development workflow - Windsurf generates code changes, and the page updates in the browser almost immediately
- Use SSR by default, as this is the philosophy of Deno Fresh
- Use DaisyUI and Tailwind for styling because these are easy to integrate with Fresh
- Use Vercel AI SDK for LLMs because I want to give it a try
- Use serverless key-value database to store state
- Center the user interface around "tasks" - each task is a single request-response interaction
- Use client polling to stream agent responses. This is OK since LLM generation produces a constant stream of tokens and 1-second polling until end of stream is fine
User Interface Structure
- NavBar: Tasks, Agents, New Agent
- List of tasks with feedback option
- Task detail view with streaming response
- List of agent versions with Invoke/Archive/New Version actions
- Agent version creation form
Implementation Notes
- Use streaming for all LLM interactions
- Store task results with ULID identifiers
- Use TTL for temporary data (e.g., response streams)
- Keep version history for audit and rollback capability