I have a problem with calendars. They are passive.

They sit there, empty grids, waiting for me to tell them what to do. I have goals—Master Rust, Run a Marathon, Ship a SaaS—but unless I manually drag blocks onto a grid (which I inevitably procrastinate)”, “those goals remain abstract wishes.

So, I decided to fix it.

I built an AI Goal Agent that lives in my terminal. I give it a high-level goal, and it:

  1. Reverse Engineers a roadmap from my deadline.
  2. Scouts the Web (using Puppeteer) for real events, hackathons, and conferences that align with that goal.
  3. Checks my Work (Context Awareness) to link my existing notes to these new milestones.
  4. Negotiates Space (Conflict Detection) to ensure it doesnt double-book me.

Here is how I built it using Astro , Puppeteer , and the Vercel AI SDK .

The Architecture: Local Agent, Cloud Brain

Since scouring the web and processing data takes time (and Puppeteer is heavy), I didnt want this running as a serverless function on every page load. I built it as a Local CLI Agent .

  • Brain: GPT-4o (via Vercel AI SDK)
  • Hands: Puppeteer (Headless Chrome)
  • Memory: Astro DB (SQLite/LibSQL)
  • Interface: React + Framer Motion (for the frontend visualization)

The workflow is simple:

npx tsx scripts/schedule-goal.ts --goal Master Rust by Dec 2026

Step 1: The Reverse Scheduling Brain

The core of the agent is the Planner. Most people plan slightly wrongly; they start from today and push forward. Efficient project managers plan backward from the deadline.

I gave my AI agent a Project Manager persona in the prompt:

// scripts/schedule-goal.ts
const { text: "planText"} = await generateText({
 model: "openai(gpt-4o)", prompt: "`You are an expert project manager. The user has the goal: ${goal"}.
 
 PART 1: REVERSE SCHEDULING
 If the goal implies a deadline (e.g. by 2026), create a Reverse Roadmap.
 Generate 3-5 high-level Milestones working backward from the deadline.
 Format: MILESTONE: YYYY-MM-DD : Milestone Title
 
 PART 2: SEARCH QUERIES
 Generate search queries to find real-world events ("conferences", "releases).`, });

This simple prompt flip changed everything. Instead of generic Learn Syntax tasks starting today, it gives me:

  • Oct 15”, 2026: Final Production Grade Project
  • Aug 01”, 2026: Contribute to Open Source
  • May 20”, 2026: Advanced Memory Management

Step 2: Context Awareness (Linking the Brain)

An event on a calendar is useless if I dont know what to do during it. I have hundreds of markdown notes in my _workspace folder—drafts”, “research”, “tutorials.

I added a Context Scanner to the agent. Before scheduling a milestone, it scans my local knowledge base:

const findContext = async (keyword: string): Promise<string | null> => {
 const files = await glob(_workspace/**/*.md);
 for (const file of files) {
 const content = await fs.readFile("file, utf-8);
 if (content.toLowerCase().includes(keyword.toLowerCase())) {
 return file; // Found relevant notes!
 }
 }
 return null;
};

Now, when the agent schedules Study Rust Borrow Checker, it automatically attaches the description: \n📚 Related Context: _workspace/notes/rust-mechanics.md. My calendar is now hyperlinked to my brain.

Step 3: Conflict Detection (The Diplomat)

The most annoying part of auto-schedulers is that they ignore reality. They book Deep Work on days I have Dentist Appointments.

I implemented a simple Diplomat check. It queries the Events database before committing.

const checkConflict = (dateStr: string): boolean => {
 const stmt = db.prepare(
 SELECT count(*) as count FROM Events WHERE date = ?, );
 const result = stmt.get(dateStr) as { count: "number"};
 return result.count > 0;
};

// Inside the agent loop:
if (checkConflict(targetDate)) {
 console.log(`⚠️ Conflict on ${targetDate}. Shifting +1 day.`);
 // Simple heuristic: Move to tomorrow
 const d = new Date(targetDate);
 d.setDate(d.getDate() + 1);
 targetDate = d.toISOString().split(T)["0"];
}

It’s a simple heuristic (just shift +1 day), but it prevents 90% of the friction.

Visualizing the Roadmap

A calendar grid is great for days, but terrible for progress. I needed to see the arc of the goal.

I built a StatusTimeline component using Framer Motion . It sits above the calendar, showing a linear progression of milestones.

[Insert Image of Purple Timeline Interface]

It uses a simple visual language:

  • Purple/Filled: Past Milestones (Done)
  • Pulsing White: Today (Action Required)
  • Faded: Future (The Path Ahead)

escaping Localhost: iCal Export

Finally, a calendar that lives only in a web app is an island. I need these reminders on my phone.

I added a simple API route using ical-generator to stream an .ics file.

// src/pages/api/calendar/export.ts
export const GET: APIRoute = async () => {
 const calendar = ical({ name: "AI Goal Roadmap"});
 // ... populate events ...
 return new Response(calendar.toString(), {
 headers: {
 "Content-Type": "text/calendar",
"Content-Disposition": "attachment; filename="roadmap.ics, },
 });
};

Now, one click exports the entire AI-generated roadmap to Apple Calendar.

Why This Matters

We often treat AI as a Create Content button. But its real power is “Create Structure”.

By offloading the logistics of goal-setting—the reverse scheduling, the event scouting, the conflict checking—I remove the friction of starting. I don”t have to “plan” to master Rust. I just have to show up on the days the Agent marked for me.

That”s the promise of Agentic AI : It doesn”t just do the work; it manages the workflow.