What comes to mind when you hear about “AI agents “ , Well the first time I encountered it ,I thought “Hmm, multiple AIs that can perform different tasks”, It turns out I wasn't far off .
AI agents or better Agentic AI refers to autonomous systems that perceive their environments , take actions , and learn in real time . Unlike traditional AIs that follow a fixed set of rules ,Agentic AIs dynamically set goals based on their environments and user needs .
https://dr-arsanjani.medium.com/the-anatomy-of-agentic-ai-0ae7d243d13c
Agentic AI exhibits key attributes that set it apart from conventional systems:
Operates independently and makes decisions without human intervention.
Interprets complex inputs to understand its environment.
Understands the purpose of tasks and prioritizes accordingly.
Takes initiative to execute tasks.
Continuously improves based on user interactions and changing contexts.
Before a head first dive into building your first AI agent , it is crucial to understand what task management is all about , and how Agentic AIs come into play .
Task management simply refers to the process of organizing and tracking tasks to ensure everything gets done on time, efficiently, and with minimal stress. In traditional task managers, you get to input your tasks , set deadlines etc and all that is a task in itself . Now, imagine a task manager that doesn't just wait for you to tell it what to do but actively learns from your needs and adapts to your changing priorities, this is where agentic AI comes in.
Agentic AIs are not your typical task management systems ,Unlike traditional tools that require you to input every detail, agentic AIs are autonomous. They perceive your environment, whether it's your calendar, your emails, or your past actions and take real-time actions to help you stay on top of things. They are goal-oriented, meaning that they don’t just manage tasks; they understand the bigger picture, they know why the tasks matter and can prioritize based on the urgency and importance of each one.
Imagine you’re working on a project with multiple moving parts. You may have some tasks that are urgent, while others can wait. A traditional task manager requires you to manually assess and adjust the priority, but an agentic AI doesn’t just wait for your commands it takes action on its own, adjusting priorities automatically, suggesting new tasks, and sending reminders when you need them. Take Agentic AIs in task management like having a virtual assistant who actually understands your workflow and proactively makes sure you stay on track.
Now that the need for Agentic AIs in task management has been established , and we have also looked at the core principles of Agentic AIs ,we take a deep dive into the nitty-gritty of creating your very own AI agent
First, let's set up our development environment. Our Agentic AI system requires several key libraries
!pip install langgraph !pip install langchain_openai !pip install langchain-community !pip install langchain-core !pip install langgraph !pip install --upgrade langchain_community !pip install openai langgraph langchain-core
from typing import TypedDict, Annotated, Sequence, Dict, List, TypeVar, Union from langgraph.graph import Graph, StateGraph from langchain_core.messages import HumanMessage, SystemMessage, AIMessage from datetime import datetime import json from enum import Enum from openai import OpenAI from langchain_core.runnables import RunnableConfig from langgraph.graph import Graph, StateGraph, END
Create a .env file in your project root:
class XAPI: def __init__(self, api_key: str): self.client = OpenAI( api_key=api_key, base_url="https://api.x.ai/v1" )
However , note that there are several LLMs you can use , or even models from HuggingFace , depending on their availability , and what you are trying to build . But I used Grok API ( XAI) , because it’s free for starters.
Remember that Agentic AIs have some attributes that make them intelligent , this is how they work in practice .
A.) Perception - Understanding the Environment
def analyze_input(state: TaskState) -> TaskState: """Determine what action to take based on the last message.""" if state.get("processed", False): new_state = state.copy() new_state["next_action"] = Action.DONE.value new_state["should_end"] = True return new_state messages = [ SystemMessage(content="""You are a task management assistant. Analyze the user's input and determine the appropriate action to take. Respond with one of: 'add_task', 'complete_task', 'get_recommendations', 'get_summary', or 'error'."""), state["messages"][-1] ] response = llm.invoke(messages) action = response.content.strip().lower()
Think of this as the agent's "eyes and ears." Just like a human assistant would listen to your request and understand what you need, this code analyzes your input to figure out what you're asking for. It's not just matching keywords , it's understanding context and intent, much like how a human would perceive and interpret requests.
B.) Autonomy - Making Independent Decisions
def generate_recommendations(state: TaskState) -> TaskState: """Generate recommendations based on current tasks.""" new_state = state.copy() pending_tasks = [t for t in state["tasks"] if t["status"] == "pending"] if not pending_tasks: new_state["recommendations"] = [ "No pending tasks. Consider adding new tasks to track your work.", "Use this time to plan upcoming projects or review completed work.", "Set up task categories and priorities for future tasks." ] new_state["messages"] = state["messages"] + [ AIMessage(content="No pending tasks found. This is a good time to:\n" + "\n".join(f"- {r}" for r in new_state["recommendations"])) ] else: messages = [ SystemMessage(content="""Analyze the current tasks and provide specific, actionable recommendations. Consider priorities, deadlines, and task relationships."""), AIMessage(content=f"Current pending tasks: {json.dumps(pending_tasks, indent=2)}") ]
This is where the "autonomous" part of our agent shines. Instead of waiting for specific commands, it actively analyzes your tasks and makes intelligent suggestions. It's like having a proactive assistant who doesn't just wait for orders but thinks ahead and offers helpful advice.
C.) Goal Orientation - Understanding the Bigger Picture
def add_task(state: TaskState) -> TaskState: messages = [ SystemMessage(content="""Extract task details from the user's message and format them as JSON. Include: - description (string) - priority (number 1-3) - deadline (string) Example output: { "description": "Review quarterly report", "priority": 1, "deadline": "2024-01-05" }"""), state["messages"][-1] ] try: response = llm.invoke(messages) content = response.content.strip() if content.startswith("```json"): content = content[7:-3] elif content.startswith("```"): content = content[3:-3] task_details = json.loads(content) if not all(key in task_details for key in ["description", "priority", "deadline"]): raise ValueError("Missing required task fields") task = { "description": task_details["description"], "priority": int(task_details["priority"]), "deadline": task_details["deadline"], "status": "pending", "created_at": datetime.now().isoformat() }
Notice how each task isn't just a simple to-do item. The agent understands that tasks have context ,they have priorities, deadlines, and relationships to other tasks. This demonstrates goal orientation by capturing not just what needs to be done, but why it matters and how it fits into the bigger picture.
D.) Action - Taking Initiative
def complete_task(state: TaskState) -> TaskState: new_state = state.copy() messages = [ SystemMessage(content="Extract the task description from the user's message."), state["messages"][-1] ] try: response = llm.invoke(messages) task_description = response.content.strip().lower() task_description = task_description.replace("mark", "").replace("task:", "").replace("complete", "").strip() # Finding the best matching task found = False for task in new_state["tasks"]: if (task["status"] == "pending" and (task_description in task["description"].lower() or task["description"].lower() in task_description)): task["status"] = "completed" task["completed_at"] = datetime.now().isoformat() found = True new_state["messages"] = state["messages"] + [ AIMessage(content=f"Task completed: {task['description']}") ] break if not found: new_state["error"] = f"No matching pending task found for: {task_description}" new_state["messages"] = state["messages"] + [ AIMessage(content=f"Could not find a pending task matching: {task_description}\nAvailable pending tasks:\n" + "\n".join(f"- {t['description']}" for t in new_state["tasks"] if t["status"] == "pending")) ] new_state["processed"] = True new_state["should_end"] = True return new_state
The agent doesn't just store tasks , it takes action. When you say you've completed something, it actively searches for the best match among your tasks, even if you don't remember the exact wording. It's like having an assistant who knows what you mean, even when you're not perfectly precise.
E.) Learning and Adaptation
def get_summary(state: TaskState) -> TaskState: """Generate a detailed summary of all tasks.""" new_state = state.copy() pending = [t for t in state["tasks"] if t["status"] == "pending"] completed = [t for t in state["tasks"] if t["status"] == "completed"] summary = { "total_tasks": len(state["tasks"]), "pending_tasks": len(pending), "completed_tasks": len(completed), "high_priority_pending": len([t for t in pending if t["priority"] == 1]) }
The agent maintains awareness of the overall state of your tasks. This ongoing analysis allows it to adapt its recommendations and actions based on your task completion patterns and changing priorities.
F.) State Management - Maintaining Context
class TaskState(TypedDict): tasks: List[Dict] next_action: str messages: List[Union[HumanMessage, AIMessage, SystemMessage]] current_task: Dict recommendations: List[str] error: str processed: bool should_end: bool
This is the agent's "memory" , it keeps track of everything that's happening. Like a good assistant who remembers your preferences and past decisions, this state management ensures the agent maintains context and can make informed decisions.
The beauty of this implementation is how it brings together all these aspects of Agentic AI into a cohesive system. It's not just about managing tasks, it's about creating an intelligent assistant that understands, thinks, and acts in ways that make task management more natural and effective.
Like any good assistant, it can handle uncertainty and errors gracefully, adapt to different ways of expressing the same request, and maintain a helpful, proactive approach to keeping you organized and on track. This is the power of Agentic AI , it transforms task management from a mechanical process into an intelligent collaboration between human and machine.
class XAPI: def __init__(self, api_key: str): self.client = OpenAI( api_key=api_key, base_url="https://api.x.ai/v1" ) def invoke(self, messages, model="grok-2-1212"): valid_models = ["grok-2-1212", "grok-2-vision-1212", "grok-beta", "grok-vision-beta"] if model not in valid_models: raise ValueError(f"Invalid model name. Choose from: {', '.join(valid_models)}") formatted_messages = [ {"role": "system" if isinstance(msg, SystemMessage) else "assistant" if isinstance(msg, AIMessage) else "user", "content": msg.content} for msg in (messages if isinstance(messages, list) else [messages]) ] try: response = self.client.chat.completions.create( model=model, messages=formatted_messages ) return AIMessage(content=response.choices[0].message.content) except Exception as e: raise Exception(f"X.AI API error: {str(e)}")
Like I said earlier , I made use of the Grok API for this AI agent , and the above code chunk is how to set it up for your use . LLM integration is very key in Agentic Ais’ , because they excel
at understanding and generating natural language.And thus , can help AI agents to communicate effectively with users.
def build_task_graph(): graph = StateGraph(TaskState) # Add nodes graph.add_node("analyze", analyze_input) graph.add_node("add_task", add_task) graph.add_node("complete_task", complete_task) graph.add_node("get_recommendations", generate_recommendations) graph.add_node("get_summary", get_summary) graph.add_node("handle_error", handle_error)
This is just an overview of how the Ai agent makes decisions eg next steps , what to do per time
You’re done building your first simple AI agent .
agent = TaskManagementAgent() # Add a task print(agent.run("Add a new task to review the quarterly report, high priority, due next Friday")) print(agent.run("Ive got to cook some stew , high priority, due next Friday")) print(agent.run("I need to feed my dogs, due next Friday")) # Complete a task print(agent.run("Mark the quarterly report review as complete")) # Get recommendations print(agent.run("What should I work on next?")) # Get summary print(agent.run("Show me a summary of all tasks"))
This is how you can put your Agent into a quick test
As you can see from the screenshot, the agent successfully:
Adds multiple tasks with different priorities and deadlines
Attempts to complete a task
Provides detailed recommendations based on task priorities and deadlines
Generates a comprehensive task summary
The agent demonstrates intelligent behavior by:
Properly formatting and storing task details
Maintaining priority levels (note the two high-priority tasks)
Providing actionable recommendations with context
Organizing tasks by deadline and priority
Giving clear feedback when actions cannot be completed (like the task completion attempt)
Agentic AI transforms task management from a mechanical process into intelligent collaboration. By combining autonomy, perception, and goal orientation, these agents simplify workflows and boost productivity. The Source code is available on my GitHub. I hope you Enjoyed reading through this simple walkthrough. Cheers, and happy building!
Connect with me on Linkedln : https://www.linkedin.com/in/tochi-obuzor?utm_source=share&utm_campaign=share_via&utm_content=profile&utm_medium=ios_app
https://github.com/tochi12ob/Agentic-Taskflow/blob/main/TaskAgent.ipynb
There are no datasets linked
There are no datasets linked