Task-Centric Structure
Design your tasks in a crystal clear format.
Overview
The Upsonic framework employs the Task class as its fundamental building block for defining and executing tasks, whether through agents or direct LLM calls. Tasks can be configured with various parameters, tools, and contextual elements, enabling the construction of comprehensive systems. Through context management, you can establish connections between tasks, link them to knowledge bases, or associate them with string values.
You don’t have to create tasks like steps. The agent will automatically generate these steps for you.
Unlike other systems that employ non-task structures, Upsonic addresses two critical limitations commonly found in alternative solutions. First, it eliminates the restriction of binding one agent to a single task, allowing agents to handle multiple tasks efficiently. Second, it significantly improves programmability. When creating tasks that involve dependencies—such as referenced websites, company information, or competitor data—Upsonic enables you to define these elements programmatically rather than embedding them within individual agents. This approach prevents the need to create separate agents for repetitive operations like competitor analysis, resulting in a more scalable and maintainable system architecture.
Creating a Task
The Task class is an integral component of Upsonic and can be easily imported into your project. Once imported, you can define multiple tasks by assigning them identifiers such as “task1,” “task2,” “task3,” or any other descriptive names of your choice.
Task Attributest
Tasks within the framework can range from basic to complex, depending on your specific requirements. The framework is designed with simplicity in mind, requiring only one mandatory parameter: the description. All other parameters are optional, providing flexibility in task configuration.
Attribute | Parameters | Type | Description |
---|---|---|---|
Description | description | str | A clear and concise statement of what the task. |
Response Format (Optional) | response_format | Optional[List[Union(BaseModal, ObjectResponse)]] | Describe the response you expect. |
Tools (Optional) | tools | Optional[List[Union(MCP, Function)]] | The tools needed to complete the task. |
Context (Optional) | context | Optional[List[Union(Task, KnowledgeBase, str)]] | Context that helps accomplish the task |
Adding Tools to a Task
Tools play a crucial role in agent functionality by bridging the gap between LLMs and real-world applications such as APIs, services, and search engines.
The framework supports two distinct types of tool implementation. The first option allows you to utilize Python functions directly as tools within Upsonic agents. The second approach leverages the Model Context Protocol (MCP), a standardized protocol for LLM tools that supports multiple platforms including Python, Node.js, and Docker. MCP tools are continuously developed and maintained by both companies and the community, with detailed information available in the “Tools” section.
Integrating a tool into your task is straightforward: simply create a list containing the desired tool’s class name and assign it to the “tools” parameter in the Task object.
Function Tools
Let’s define a class called MyTools that includes a function named is_page_available. This function will perform a simple URL validation check, returning True if the specified URL is accessible, making it useful for verifying web resources.
MCP Tools
This example demonstrates integration with the HackerNews MCP Server, which provides several functions including get_stories, get_story_info, search_stories, and get_user_info. The MCP framework simplifies the process of connecting our agents to external services, as illustrated by this HackerNews integration.
Put to Task
Once you’ve configured your custom tools, they can be directly incorporated into the Task object. The agent will then automatically utilize these tools as needed during task execution.
Putting Task to Another Task as Context
The framework supports the combination of multiple tasks to handle complex operations, particularly useful in scenarios requiring deep analysis followed by report generation. While individual tasks may be complex, the true power lies in their interconnection. By creating task chains and linking them through shared context, you can build sophisticated workflows that seamlessly pass information between tasks.
The Upsonic framework explains the context to the LLM for your purposes. You don’t have to worry about sharing multiple contexts.
Giving Knowledge Base as Context
The framework incorporates a robust KnowledgeBase feature designed to extend LLM models beyond their inherent knowledge limitations. While LLM models are constrained by their training data boundaries, real-world applications frequently demand access to external information sources such as PDFs, documents, and spreadsheets. Through seamless integration with the Context system, the KnowledgeBase feature enables you to efficiently incorporate these external data sources into your tasks, enhancing the model’s capability to process and utilize supplementary information.
You can see the supported files and options of the Knowledge Base System from here.
Define a KnowledgeBase
In this example, we’ll use a PDF and a web link to make a knowledge base.
Add as Context to Task
Giving string as Context
Tasks represent specific objectives that need to be accomplished within the system. These tasks often contain variable elements such as URLs, names, individuals, or topics. Traditionally, all these components would need to be incorporated directly into the prompt, resulting in a non-programmatic approach. This conventional method relies heavily on f-strings or format operations, which significantly limits prompt management capabilities and constrains it within the main execution flow.
In the context system we also support str as context. This provide an capability to put your variables to outside of the prompt.
Use this when you need to separate your prompt and variable, like in a city list. You don’t need to use it if your prompt doesn’t have variables.
When you need to create task for different cities, you can use this method:
City List and Base Description
Creating a for loop
Response Format
The Upsonic framework leverages Pydantic BaseModel compatibility for defining expected results, enabling programmatic handling of agent responses. By specifying a response format, the system returns structured objects rather than raw text, allowing for seamless integration and logic implementation within your application.
For instance, when requesting a list of cities, the system returns a structured list of strings containing city names. This approach emphasizes value-oriented development by abstracting away the implementation details, allowing developers to focus on utilizing the data rather than managing its format and parsing.
You can use Pydantic’s BaseModel instead of ObjectResponse. We created this wrapper to make it easier to understand.
Running Task on Direct LLM Call
After task definition, you have the flexibility to choose between two runtime options: Agent execution or direct LLM calls. While Agents provide powerful capabilities for complex tasks, they may not always be the most efficient choice. For simple tasks without potential sub-steps, utilizing an Agent can result in unnecessary time and cost overhead.
Direct LLM calls are particularly advantageous for straightforward operations that don’t require sub-task generation or characterization. This runtime selection can be strategically implemented within your Agent application logic, allowing you to optimize performance and resource utilization based on task complexity.
Direct LLM Calls Support Tools
Don’t sweat it—Direct LLM Calls takes care of all your tools. They’ll work like agents, no sweat!
Running Task on Agent
Tasks can be executed through characterized LLM agents, a key feature that enables specialized, task-focused LLM implementations tailored to your company’s needs. The agent mechanism is governed by “AgentConfiguration” objects, which serve as the foundation for defining and customizing agent characteristics and behaviors.
This characterization system allows for precise control over how agents process and respond to tasks, ensuring alignment with specific business requirements and objectives. Through these configurations, you can create purpose-built agents that maintain consistency and relevance in their operations while adhering to your organization’s specific requirements.
You can view the details of agent creation and customization here.
Creating Agent
To create an agent, we’re going to import the “AgentConfiguration” and make a basic customization.
Creating Task
Running Task with Agent
We’ve got a function called “agent” in the client that we’ll use to give product_manager_agent and task1.
Accessing to Task Results
Tasks can be executed through two distinct runners: direct LLM calls or agents. These runners serve as execution mechanisms for task processing and result generation, offering flexibility in implementation. The system supports both parallel processing and multi-client operations, enhancing scalability and performance.
To maintain a controlled and organized infrastructure, all results are stored within the Task object itself. This architectural decision provides a centralized approach to result management, enabling better monitoring, access, and control over task outcomes. Such design creates a robust and manageable infrastructure that can be effectively tailored to your specific requirements.
When you run the task, the results are stored in the Task.response. You can get it directly.
Hey, just a heads-up: if you set a response_format, the task response will be an object of your class.