← Back to list

From To‑Do List to AI Agent: Building a Self‑Improving Task Platform

A developer’s journey through LLMs, graph databases, automation, and the messy reality of building something that actually works.

aitzaz akmal · 2026-07-10 09:51 · 0 claps · 10.3 min read
#dependency-hell #llm-integration #architecture-agent #automation #webhooks
Open on Medium ↗
Wiki topics: LLM · Large Language Models AGT · AI Agents 🏛️ · Architecture

From To‑Do List to AI Agent: Building a Self‑Improving Task Platform

A developer’s journey through LLMs, graph databases, automation, and the messy reality of building something that actually works.

Why Another Task Management Tool?

The project management software market was valued at over $9.7 billion in 2025 and is projected to reach $23 billion by 2031. Yet despite this massive industry, most tools still feel like they were designed for a world that no longer exists. You click through endless menus, create labels, set up workflows, and still end up spending more time managing the tool than doing the actual work.

I wanted to see if we could do better. What if instead of clicking through interfaces, you could just talk to your task manager? What if it could understand what you meant, break down your goals into actionable steps, and learn from what worked and what didn’t? That was the question that started this project — and the answer turned out to be far more complicated (and far more rewarding) than I ever expected.

The Original Plan: A Simple To‑Do List with AI

Like many developers, I started with a relatively modest ambition. I wanted to build a to‑do list application with a few “wow factor” features: natural language input, automated notifications, and maybe some basic collaboration. The stack seemed straightforward:

  • Rails API for the backend
  • PostgreSQL for relational data
  • Neo4j for graph relationships between tasks
  • n8n for workflow automation (Slack notifications)
  • Anthropic Claude for AI parsing of natural language requests

The vision was clear: a user could type “Create a marketing campaign with three tasks: social media, email, and ads” and the system would automatically create those tasks, assign priorities, set deadlines, and notify the team. Simple, elegant, and powerful.

It turned out to be anything but simple.

The First Major Pivot: From ORM to Raw HTTP

The first roadblock came early. I tried integrating Neo4j using the neo4j gem (the original Ruby ORM for Neo4j). The idea was to use Neo4j::ActiveNode models that would work similarly to Rails’ ActiveRecord. This seemed like the natural choice.

It didn’t work.

The activegraph gem (a fork of the original Neo4j ORM) had constant autoloading issues. The neo4j-ruby-driver gem required a native library called libseabolt17 that refused to install cleanly on my Ubuntu system. After hours of troubleshooting, I faced a choice: keep fighting the ORM, or find another way.

I chose another way.

Instead of using the driver and ORM, I built a simple HTTP client using HTTParty that communicates directly with Neo4j’s REST API. The endpoint http://localhost:7474/db/neo4j/tx/commit became my gateway to the graph database. I wrote Cypher queries by hand and parsed the JSON responses. This was more work upfront — but it eliminated the dependency hell and gave me complete control over every query.

Lesson learned: Sometimes the “right” way (using an ORM) isn’t the right way for your specific setup. Raw HTTP is underrated, and it’s often more reliable than adding yet another abstraction layer.

The Dependency Spiral: When Gems Fight Each Other

The next challenge emerged when I tried to integrate the AI component. I originally used langchainrb with Anthropic’s Claude API. But when Anthropic’s credit system became problematic (the API returned a “credit balance too low” error despite having a valid key), I switched to Google Gemini.

That’s when everything broke.

The google-genai gem required faraday ~> 2.0. The neo4j gem (which I was still using for some parts) required faraday_middleware which required faraday < 1.0 . The dependency conflict was unresolvable — Bundler couldn’t find a combination of gems that satisfied all requirements.

I spent hours trying to downgrade, upgrade, and patch my way out of the conflict. Eventually, I removed the neo4j gem entirely. Since I was already using raw HTTP for Neo4j queries, I didn’t actually need the ORM. This resolved the conflict and simplified the codebase at the same time.

Lesson learned: Dependency conflicts are a sign that your architecture might be overcomplicating things. Removing unnecessary abstractions often simplifies more than just the Gemfile.

The Model Deprecation: When “Free” Means “Soon to Be Gone”

With Anthropic out of the picture, I switched to Google Gemini’s free tier. It worked — briefly. Then I hit the 429 errors: “You exceeded your current quota, please check your plan and billing details”. No matter which model I tried (gemini-2.0-flash, gemini-1.5-flash, gemini-2.0-flash-lite), the response was always the same: quota exceeded, limit 0.

After extensive research, I discovered this was a known issue with new Gemini accounts. The API server simply wasn’t respecting the quota limits. The solution? Either enable billing (which I wanted to avoid) or switch providers.

That’s when I discovered Groq.

Groq offers a generous free tier with thousands of requests per day, and their inference speed is genuinely impressive. I signed up, got an API key, and integrated it using a simple HTTP client — no gem dependencies required. The integration took about 15 minutes.

Then I hit another snag: the model I was using (mixtral-8x7b-32768) had been deprecated. The API returned: “The model ‘mixtral-8x7b-32768’ has been decommissioned and is no longer supported.” A quick check of the available models revealed llama-3.3–70b-versatile as the best replacement. I switched to it, and everything worked.

Lesson learned: Free tiers are great — until they aren’t. Always have a fallback plan, and always check which models are actively supported before building on top of them.

The Agent Architecture: From Prompts to Planning

The core of the system is the TaskPlannerAgent. When a user sends a request like “Create a marketing campaign with three tasks”, the agent:

  1. Understands the request — It sends a structured prompt to the LLM asking for a JSON output with main_goal, subtasks, and dependencies.
  2. Creates a plan — It refines the plan based on previous feedback (if any).
  3. Executes the plan — For each subtask, it creates a node in Neo4j with the appropriate properties and relationships.
  4. Collects feedback — It asks the LLM to rate the quality of the plan (simulating user feedback).
  5. Reflects and improves — If the rating is below 3.5, it reflects on what went wrong and adjusts the strategy.
  6. Summarizes — It returns a summary of what was created.

This architecture, inspired by the agentic systems described in recent research, creates a feedback loop where the agent learns from its own performance. The model brings flexibility; the runtime controls what is possible.

The result: The agent produces high‑quality task breakdowns. In one test, it generated 12 tasks for a marketing campaign, each with appropriate priorities and descriptions. The reflection mechanism then suggested improvements for future plans.

The n8n Integration: Automation That Actually Works

One of the most satisfying parts of the project was integrating n8n for workflow automation. n8n is an open‑source tool that connects various apps using a visual editor. I set up a webhook that triggers whenever a task is created in Neo4j.

The workflow is simple but powerful:

  • The webhook receives the task data from Rails.
  • It formats the data and sends it to Slack.
  • The team gets instant notifications about new tasks.

The challenge: n8n’s webhook required the workflow to be “active” — not just saved, but explicitly published. I spent an embarrassing amount of time wondering why my curl tests were returning 404 errors. The solution was simple: click the “Publish” button and toggle the workflow to active.

Lesson learned: Always read the documentation. And if the documentation isn’t clear, test with curl before assuming the integration is broken.

The Fallback Mechanism: When AI Fails, Don’t Let Everything Fail

One design decision I’m particularly proud of is the fallback mechanism in the agent. If the LLM returns nil or an empty response, the agent automatically falls back to a dummy plan:

ruby:

@state[:plan] = { ‘main_goal’ => ‘Fallback: Create sample tasks’, ‘subtasks’ => [ { ‘title’ => ‘Task 1’, ‘description’ => ‘Sample task 1’, ‘priority’ => 1 }, { ‘title’ => ‘Task 2’, ‘description’ => ‘Sample task 2’, ‘priority’ => 2 } ] }

This means even if Groq is down, rate‑limited, or returning errors, the system still works. It creates tasks, triggers the webhook, and notifies Slack — just with generic task names instead of AI‑generated ones.

This is a principle I learned from building production systems: assume every external dependency will fail at some point, and design your system to degrade gracefully.

What I Achieved

By the end of this journey, I had built:

  • A Rails API with JWT‑style token authentication.
  • A Neo4j graph database with users, tasks, and relationships (creator, assignees, blocks).
  • An AI agent that parses natural language requests, creates structured plans, executes them, collects feedback, and improves over time.
  • An n8n workflow that sends Slack notifications whenever a task is created.
  • A fallback mechanism that keeps the system running even when the AI provider is unavailable.

The console output says it all:

12 tasks created for a marketing campaign, each with appropriate priorities and descriptions.

The agent works. The automation works. The system works.

What I Would Do Differently

  1. Skip the ORM earlier. The neo4j gem caused more problems than it solved. Raw HTTP queries are simpler, more reliable, and easier to debug.

  2. Check model support before committing. I wasted hours trying to make mixtral-8x7b-32768 work when it had already been deprecated. A simple curl to the models endpoint would have saved me that time.

  3. Build the fallback mechanism from day one. The fallback plan turned out to be one of the most valuable features. I should have implemented it earlier.

  4. Use a unified LLM client from the start. Switching between Anthropic, Gemini, and Groq required rewriting the LLM wrapper each time. A gem like RubyLLM or Intelligence would have abstracted this away and made the transitions smoother.

  5. Test the n8n webhook with curl before integrating with Rails. The 404 errors were frustrating, but they were entirely my fault for not testing the webhook independently first.

What I Learned

The AI hype is real, but the implementation is messy. Every AI provider has quirks, limitations, and undocumented behaviors. Building a reliable system requires constant adaptation.

Graph databases are powerful but require a different mental model. Relationships like “Task A blocks Task B” are trivial to query in Neo4j but require complex joins in SQL. The shift in thinking is worth it.

Automation is about connecting the right pieces. n8n’s visual workflow editor makes it easy to wire things together without writing code. The challenge is getting the data format right.

The best systems are the ones that handle failure gracefully. Your AI provider will go down. Your database will have connection issues. Your webhook will time out. Design for these failures from the beginning.

The Bigger Picture: What This Means for the Future

The project management software market is growing rapidly — from $9.7 billion in 2025 to a projected $23 billion by 2031. But most of that growth is in traditional, click‑based tools. The next wave of innovation will come from AI‑native systems that understand natural language, learn from feedback, and automate workflows.

This project is a proof of concept for that future. It demonstrates that you can build an AI‑powered task management system using off‑the‑shelf components:

  • Rails for the API layer.
  • Neo4j for the graph data model.
  • Groq for fast, affordable LLM inference.
  • n8n for workflow automation.
  • Slack for team notifications.

The components exist. The question is whether we can put them together in a way that feels seamless, reliable, and genuinely useful. This project suggests the answer is yes — but it also shows how much work is still required to get there.

For the Next Builder: What I Wish I Knew

If you’re reading this and thinking about building something similar, here’s the advice I wish I had received:

  1. Start with raw HTTP. ORMs are great for simple CRUD, but graph databases benefit from explicit, hand‑written queries.
  2. Always have a fallback. Your AI provider will fail. Your webhook will time out. Your database will have issues. Build for resilience.
  3. Use a unified LLM client. Switching providers is inevitable. Abstract the LLM layer early.
  4. Test webhooks with curl before integrating. It will save you hours of debugging.
  5. Document your decisions. I wish I had written down why I chose each component and each approach. Future me would have appreciated it.
  6. Embrace failure. Every error, every timeout, every 404 taught me something. The project is better for it.

Final Thoughts

This project started as a simple to‑do list with AI. It ended as a fully functional, self‑improving task management platform with graph databases, workflow automation, and an agent that learns from its own feedback.

The journey was messy. The code is imperfect. The architecture could be cleaner. But the system works. And in a world where most AI projects never make it past the prototype stage, that’s something worth celebrating.

The next step is scaling — multi‑agent collaboration, autonomous scheduling, real‑time communication, and a plugin marketplace. But that’s a story for another time.

For now, I have a working system that turns natural language into tasks, notifies teams, learns from feedback, and keeps running even when things break. That’s more than I set out to build — and it’s a foundation I’m proud of.

References

  1. Research and Markets. (2026). Project Management Software Systems — Market Share Analysis, Industry Trends & Statistics, Growth Forecasts (2026–2031). The project management software market is projected to grow from USD 11.27 billion in 2026 to USD 23.09 billion by 2031.
  2. Doximity Technology. (2022). Integrating Neo4j Into Your Stack. Discusses using Neo4j’s HTTP API for RESTful interaction with the database.
  3. Arize AI. (2026). How to Build Planning Into Your Agent (The Architecture That Actually Works). Describes the planning stage where agents pre‑emptively build plans for larger requests.
  4. Heavybit. (2026). Why Orchestration May Be the Future of Agentic Development. Discusses the need for orchestration and human supervision in multi‑step agent processes.
  5. Medium. (2025). Automating Without the Headache: My First Experience Using n8n. Describes n8n as an open‑source workflow automation tool.
  6. Industry reports. The global project management software market was valued at approximately $10.1 billion in 2025

AI #ArtificialIntelligence #MachineLearning #LLM #Rails #RubyOnRails #Neo4j #GraphDatabase #n8n #WorkflowAutomation #Slack #Groq #SoftwareEngineering #DevOps #TechJourney #BuildInPublic #IndieDev #IndieHacker #DevDiaries #OpenSource #StartupJourney #AIAgents #AgenticAI #LangChain #LangGraph #WebDevelopment #APIDesign #CodingLife #100DaysOfCode #DevLife #GenAI #GenerativeAI #LLM #Claude #Gemini #Groq #AIAgents #AgenticAI #PromptEngineering #AIApplications #NLP #Ruby #RubyOnRails #RailsAPI #PostgreSQL #Neo4j #GraphDatabase #Cypher #HTTParty #Sidekiq #Redis #Docker #n8n #WorkflowAutomation #SlackAPI #Webhooks #Integration #Automation #DevOps #CI_CD #BuildInPublic #OpenSource #StartupJourney #IndieHacker #DevDiaries #100DaysOfCode #CodeNewbie #DevCommunity #WomenInTech #TechForGood #TechJourney #SoftwareEngineering #Coding #Programming #Developer #FullStack #WebApp #MVP #ProductDevelopment

. https://github.com/Aitzaz94/task-platform


메타데이터
post_id
5eb166ec58e8
slug
from-to-do-list-to-ai-agent-building-a-self-improving-task-platform-5eb166ec58e8
url
https://medium.com/@aitzazakmal/from-to-do-list-to-ai-agent-building-a-self-improving-task-platform-5eb166ec58e8
canonical_url
https://medium.com/@aitzazakmal/from-to-do-list-to-ai-agent-building-a-self-improving-task-platform-5eb166ec58e8
author_url
https://medium.com/@aitzazakmal
status
ok
fetched_at
2026-08-25 20:21:51