DEV Community

Cover image for Building a Personal Study Planner Agent in typescript with HazelJS
Nisa Fatima
Nisa Fatima

Posted on

Building a Personal Study Planner Agent in typescript with HazelJS

AI agents become more useful when they are not just chatbots, but small systems that can understand a request, call tools, retrieve knowledge, and return structured results.

For this example, we built a Personal Study Planner Agent with HazelJS.

The goal is simple:

A student gives their exam date, available study time, and weak topics. The agent creates a realistic study plan.

This is an easy project, but it still shows important HazelJS agent patterns.

What the Project Includes

The project uses:

  • @hazeljs/core for modules, controllers, and services
  • @hazeljs/agent for agents, tools, delegation, and supervisor routing
  • @hazeljs/rag for study-method retrieval
  • @hazeljs/guardrails for safer input/output handling
  • @hazeljs/eval for golden tests
  • @hazeljs/inspector for the /__hazel web view

The app has four agents:

  • StudyIntakeAgent
  • StudyResourceAgent
  • StudyScheduleAgent
  • StudyCoachAgent

Each agent has a focused job.

Why This Example Works Well

A study planner is simple enough to understand quickly, but it still has a real workflow:

  1. Extract study constraints
  2. Find useful study methods
  3. Build a schedule
  4. Return a clear plan

That makes it a good beginner-friendly HazelJS agent example.

A sample request looks like this:

I have 10 days before my algebra exam. I can study 60 minutes daily. Weak topics are quadratic equations and word problems.
Enter fullscreen mode Exit fullscreen mode

The system can extract the exam, timeline, daily capacity, weak topics, and urgency.

Agent 1: Study Intake

The first agent is StudyIntakeAgent.

Its job is to understand the student’s request.

@Agent({
  name: 'StudyIntakeAgent',
  description: 'Extracts exam goals, time constraints, weak topics, learning style, and urgency.',
})
@Service()
export class StudyIntakeAgent {
  @Tool({
    name: 'extractStudyProfile',
    description: 'Extract structured study planning information from a student request.',
  })
  async extractStudyProfile(input: { message: string; studentId?: string }) {
    // Extract exam, days, minutes, weak topics, and urgency
  }
}
Enter fullscreen mode Exit fullscreen mode

This keeps profile extraction separate from schedule creation.

That is a good agent design pattern: one agent, one responsibility.

Agent 2: Study Resources with RAG

The second agent is StudyResourceAgent.

It uses HazelJS RAG to retrieve study methods like:

  • active recall
  • spaced repetition
  • interleaving
  • exam review
  • healthy study breaks
@Agent({
  name: 'StudyResourceAgent',
  description: 'Retrieves evidence-based study methods and review tactics.',
  enableRAG: true,
})
@Service()
export class StudyResourceAgent {
  @Tool({
    name: 'searchStudyMethods',
    description: 'Search study method guidance for planning, review, recall, and exam preparation.',
  })
  async searchStudyMethods(input: { query: string; topK?: number }) {
    return this.knowledgeBase.answer(input.query, input.topK ?? 3);
  }
}
Enter fullscreen mode Exit fullscreen mode

This is better than asking the model to invent study advice. The agent retrieves known study methods and uses those as context.

Agent 3: Study Schedule

The third agent is StudyScheduleAgent.

It creates the actual day-by-day plan.

@Agent({
  name: 'StudyScheduleAgent',
  description: 'Creates realistic daily study plans with review checkpoints.',
})
@Service()
export class StudyScheduleAgent {
  @Tool({
    name: 'createStudySchedule',
    description: 'Create a day-by-day study schedule from exam constraints and weak topics.',
  })
  async createStudySchedule(input: {
    exam: string;
    daysUntilExam: number;
    minutesPerDay: number;
    weakTopics: string[];
  }) {
    // Build daily schedule
  }
}
Enter fullscreen mode Exit fullscreen mode

The tool returns a structured plan with:

  • day number
  • focus topic
  • study minutes
  • activities
  • checkpoint

This makes the output easier to use in a real app.

Agent 4: Study Coach Orchestrator

The StudyCoachAgent coordinates the other agents.

It uses HazelJS @Delegate:

@Delegate({
  agent: 'StudyIntakeAgent',
  description: 'Extract exam, timeline, weak topics, capacity, and urgency.',
  inputField: 'input',
})
async analyzeStudyRequest(input: string): Promise<string> {
  return '';
}
Enter fullscreen mode Exit fullscreen mode

It can delegate to:

  • StudyIntakeAgent
  • StudyResourceAgent
  • StudyScheduleAgent

This keeps orchestration clean without putting everything into one giant prompt.

Supervisor Routing

The project also uses HazelJS supervisor routing.

const supervisor = runtime.createSupervisor({
  name: 'study-planner-supervisor',
  workers: ['StudyIntakeAgent', 'StudyResourceAgent', 'StudyScheduleAgent'],
  maxRounds: 4,
});
Enter fullscreen mode Exit fullscreen mode

The supervisor decides which agent should handle the request.

For example, a schedule request is routed to StudyScheduleAgent.

A method question is routed to StudyResourceAgent.

This is useful when the app does not know ahead of time which specialist should run.

Runtime Safety and Observability

The app configures the HazelJS agent runtime with production-friendly settings:

AgentModule.forRoot({
  runtime: {
    defaultMaxSteps: 8,
    defaultTimeout: 15000,
    enableObservability: true,
    enableMetrics: true,
    enableRetry: true,
    enableCircuitBreaker: true,
    rateLimitPerMinute: 120,
  },
})
Enter fullscreen mode Exit fullscreen mode

This gives the agent system:

  • step limits
  • timeouts
  • retries
  • circuit breaker protection
  • metrics
  • rate limiting
  • observability

Even for a small demo, these are good habits.

Guardrails

The app enables HazelJS guardrails:

GuardrailsModule.forRoot({
  redactPIIByDefault: true,
  blockInjectionByDefault: true,
  blockToxicityByDefault: true,
})
Enter fullscreen mode Exit fullscreen mode

This helps keep inputs and outputs safer.

For a study planner, guardrails are useful because users may paste personal details, stress-related messages, or unsafe instructions.

Testing with Evals

The project includes golden evals with @hazeljs/eval.

The evals check:

  • whether the intake agent calls extractStudyProfile
  • whether the resource agent retrieves the right study methods
  • whether the schedule agent calls createStudySchedule

Example:

{
  "id": "schedule-biology",
  "input": "Build a plan for my biology exam in 14 days with 90 minutes daily. Weak topics are photosynthesis and genetics.",
  "expectedOutput": "Study schedule complete",
  "expectedToolCalls": ["createStudySchedule"]
}
Enter fullscreen mode Exit fullscreen mode

Run:

npm run eval
Enter fullscreen mode Exit fullscreen mode

Expected result:

[hazeljs/eval] personal-study-planner-agent@2026.06 avg=0.944 passed=true
Enter fullscreen mode Exit fullscreen mode

This proves the project is not only returning text, but also using the right tools.

Running the Project

Install dependencies:

npm install
Enter fullscreen mode Exit fullscreen mode

Run evals:

npm run eval
Enter fullscreen mode Exit fullscreen mode

Start the app:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Test the supervisor endpoint:

curl -s -X POST http://localhost:3000/study/supervisor \
  -H 'content-type: application/json' \
  -d '{"message":"I have 10 days before my algebra exam. I can study 60 minutes daily. Weak topics are quadratic equations and word problems.","userId":"student-2"}'
Enter fullscreen mode Exit fullscreen mode

Open the HazelJS inspector:

http://localhost:3000/__hazel
Enter fullscreen mode Exit fullscreen mode

You can also inspect registered agents and tools:

http://localhost:3000/study/runtime
Enter fullscreen mode Exit fullscreen mode

Why Use a Local Provider?

The demo uses a deterministic local provider.

That means:

  • no API key is required
  • outputs are stable
  • evals are repeatable
  • readers can run the project immediately

In production, you can replace it with a real model provider through HazelJS AI integrations.

Final Thoughts

This project is intentionally simple, but it shows strong HazelJS agent patterns:

  • focused agents
  • scoped tools
  • RAG-backed knowledge
  • delegation
  • supervisor routing
  • guardrails
  • runtime observability
  • evals

That makes the Personal Study Planner Agent a good beginner-friendly example for learning how to build practical AI agents with HazelJS.
Repo: Personal Study Planner

Top comments (0)