Video Editing Agent
A production system that automates complex video editing workflows, built on a single hard rule: separate thinking from doing. The model plans, a deterministic worker executes, and every decision is written down.
Summary & core philosophy
Many agentic systems lean on fuzzy state management. This one does the opposite: the orchestrator does all the thinking, the worker does all the doing, and the boundary between them is a structured plan rather than a guess.
LLM planning
Deterministic worker
No VectorDB for state
Database schema
Drizzle ORM manages the PostgreSQL schema, designed for high observability and strict data integrity. Four tables hold the entire lifecycle of a job.
| Table | Role | Key columns |
|---|---|---|
jobs | Top-level edit request and its lifecycle status. | status, edit_plan_id |
assets | Source media: raw footage, b-roll, and audio. | asset_type, metadata |
edit_plans | The structured LLM output, versioned per job. | plan_data, version |
traces | Per-step observability for every FFmpeg call. | trace_id, ffmpeg_args |
import { pgTable, uuid, varchar, text, timestamp, jsonb, integer, pgEnum } from 'drizzle-orm/pg-core'; export const jobStatusEnum = pgEnum('job_status', ['pending', 'processing', 'completed', 'failed', 'review_required']); // Core Jobs Tableexport const jobs = pgTable('jobs', { id: uuid('id').primaryKey().defaultRandom(), userId: uuid('user_id').notNull(), title: varchar('title', { length: 255 }).notNull(), status: jobStatusEnum('status').default('pending').notNull(), editPlanId: uuid('edit_plan_id').references(() => editPlans.id), createdAt: timestamp('created_at').defaultNow().notNull(), updatedAt: timestamp('updated_at').defaultNow().notNull(),}); // Assets Tableexport const assets = pgTable('assets', { id: uuid('id').primaryKey().defaultRandom(), jobId: uuid('job_id').references(() => jobs.id).notNull(), storageUrl: text('storage_url').notNull(), assetType: varchar('asset_type', { length: 50 }).notNull(), // 'raw_footage', 'b-roll', 'audio' metadata: jsonb('metadata').notNull(), // duration, resolution, fps, bitrate createdAt: timestamp('created_at').defaultNow().notNull(),}); // Edit Plans Table (The LLM Output)export const editPlans = pgTable('edit_plans', { id: uuid('id').primaryKey().defaultRandom(), jobId: uuid('job_id').references(() => jobs.id).notNull(), planData: jsonb('plan_data').notNull(), // Array of instructions: cut, transition, overlay version: integer('version').default(1).notNull(), llmModel: varchar('llm_model', { length: 50 }), promptTokens: integer('prompt_tokens'), completionTokens: integer('completion_tokens'), createdAt: timestamp('created_at').defaultNow().notNull(),}); // Observability & Trace Logsexport const traces = pgTable('traces', { id: uuid('id').primaryKey().defaultRandom(), jobId: uuid('job_id').references(() => jobs.id).notNull(), traceId: varchar('trace_id', { length: 100 }).notNull(), stepName: varchar('step_name', { length: 255 }).notNull(), ffmpegArgs: text('ffmpeg_args'), renderTimeMs: integer('render_time_ms'), logs: text('logs'), payload: jsonb('payload'), // Input/Output snapshots isFailure: varchar('is_failure', { length: 5 }).default('false'), createdAt: timestamp('created_at').defaultNow().notNull(),});Video evaluation pipeline
An automated scoring engine guards quality before a render is finalized. Six metrics run on every candidate edit.
Clarity & resolution
Punchiness
Retention scoring
Caption readability
Brand fit
Watchability
Golden rendersscore > 0.85
Observability & tracing
A trace-first architecture makes complex FFmpeg pipelines debuggable. Every job carries a root trace_id; every sub-task inherits it and adds its own span.
- 1
Job created
- 2
Sub-tasks inherit
- 3
Real-time shipping
Logged properties
ffmpeg_argsrender_timecpu_usage / gpu_usagefailures
Local-friendly stack
The whole system runs efficiently on high-end local hardware or private cloud instances. PostgreSQL doubles as the persistent queue and state store, so a worker restart never loses work.