# Initialization Source: https://docs.upsonic.ai/CLI/initialization Set up your development environment and initialize an Agent Project ## Overview Initializing an Agent Project sets up the foundation for building your AI agent. This process involves creating a virtual environment, installing the Upsonic CLI, and generating the project structure with template files. If you don't have `uv` installed, you can install it by following the instructions at [this link](https://docs.astral.sh/uv/getting-started/installation/). ## Creating Virtual Environment Before installing Upsonic, create a virtual environment to isolate your project dependencies: ```bash theme={null} # Initializing uv uv init # Using uv uv venv # Naming uv venv my-name # Setting up python version uv venv --python 3.11 # Activate the virtual environment source .venv/bin/activate # On macOS/Linux .venv\Scripts\activate # On Windows ``` ## Installing Upsonic CLI Install Upsonic using pip: ```bash theme={null} uv add upsonic ``` This installs the `upsonic` command-line tool globally or within your virtual environment. Verify the installation: ```bash theme={null} upsonic ``` ## Initialize your Agent Project Navigate to your project directory and run: ```bash theme={null} upsonic init ``` The CLI will prompt you for an agent name. This creates: * `agent.py`: Template agent file with a basic `main()` function * `upsonic_config.json`: Configuration file with your agent's metadata, schemas, and dependencies The generated `agent.py` includes a simple example that uses Upsonic's Agent class to process questions. You can customize this file to implement your agent's specific logic. ## Run your Agent Project After initialization, install the required dependencies: ```bash theme={null} upsonic install ``` This installs all dependencies listed in the `api` section of `upsonic_config.json`, including FastAPI and uvicorn. Then start your agent as a FastAPI server: ```bash theme={null} upsonic run ``` By default, the server runs on `http://localhost:8000`. You can customize the host and port: ```bash theme={null} upsonic run --host 0.0.0.0 --port 8080 ``` Access the interactive API documentation at `http://localhost:8000/docs` to test your agent's endpoint. # Overview Source: https://docs.upsonic.ai/CLI/overview Learn about Agent Projects and how they work in Upsonic ## What is Agent Project? An Agent Project is a structured way to build production-ready AI agents using Upsonic. It provides a standardized project structure with: * **Agent Logic**: Your agent's core functionality defined in `agent.py` * **Configuration**: Project settings, input/output schemas, and dependencies in `upsonic_config.json` * **FastAPI Integration**: Automatic API generation from your agent configuration * **Dependency Management**: Organized dependency sections for API, Streamlit, and development tools Agent Projects enable you to quickly scaffold, develop, and deploy AI agents as RESTful APIs with minimal boilerplate code. ## How Agent Project Works When you initialize an Agent Project, Upsonic creates two essential files: 1. **`agent.py`**: Contains your agent's `main()` function that processes inputs and returns outputs 2. **`upsonic_config.json`**: Defines your agent's metadata, input/output schemas, dependencies, and runtime configuration The framework automatically: * Generates a FastAPI server from your configuration * Creates OpenAPI documentation with interactive forms * Handles both JSON and multipart/form-data requests * Validates inputs and outputs based on your schema definitions * Manages dependencies across different environments Your agent's `main()` function receives inputs as a dictionary, processes them using Upsonic's Agent class, and returns a dictionary with results. The FastAPI server exposes this as a `/call` endpoint that can be consumed by any HTTP client. # Start Agent API Source: https://docs.upsonic.ai/CLI/start-agent-api Configure inputs, outputs, and run your agent as a FastAPI server ## Overview The Agent API automatically generates a FastAPI server from your `upsonic_config.json` configuration. The server exposes a `/call` endpoint that accepts inputs defined in your input schema and returns outputs matching your output schema. The API supports both `application/json` and `multipart/form-data` content types, making it compatible with web forms, file uploads, and JSON-based clients. ## Configure Inputs Inputs are defined in the `input_schema` section of `upsonic_config.json`: ```json theme={null} { "input_schema": { "inputs": { "question": { "type": "string", "description": "The question of the User", "required": True, "default": None } } } } ``` Supported input types include: * `string`: Text input * `number`: Numeric values * `integer`: Whole numbers * `boolean`: True/false values * `array` or `list`: Arrays of values * `json` or `object`: JSON objects * `file` or `binary`: File uploads Set `required: true` for mandatory inputs and provide `default` values for optional fields. ## Configure Outputs Outputs are defined in the `output_schema` section: ```json theme={null} { "output_schema": { "answer": { "type": "string", "description": "Answer of the agent" } } } ``` Your agent's `main()` function should return a dictionary matching the output schema structure. The API automatically validates and formats the response according to these definitions. ## Run FastAPI of your Agent Start the FastAPI server with: ```bash theme={null} upsonic run ``` The server starts on `http://localhost:8000` by default. Customize the host and port: ```bash theme={null} upsonic run --host 0.0.0.0 --port 8080 ``` Once running, you can: * Access interactive API docs at `http://localhost:8000/docs` * Test the `/call` endpoint directly from the Swagger UI * Send HTTP requests to `POST http://localhost:8000/call` The API automatically generates OpenAPI schemas from your input/output configurations, enabling full type validation and interactive testing through the documentation interface. # Changelog Source: https://docs.upsonic.ai/changelog Latest updates and improvements to Upsonic AI Agent Framework > Product updates, improvements, and bug fixes for Upsonic ## v0.76.3 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.76.3) ## Improvements: * **AppliedScientist: `current_data` is now optional**. When omitted, the agent reads the current notebook and figures out the data source itself. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.76.2...v0.76.3](https://github.com/Upsonic/Upsonic/compare/v0.76.2...v0.76.3) ### Pull Requests: * feat: current\_data optional, agent infers data source from notebook: [onuratakan](https://github.com/onuratakan) in [#575](https://github.com/Upsonic/Upsonic/pull/575) ## v0.76.2 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.76.2) ## Improvements: * **AppliedScientist: flexible `research_source`**: Accepts anything — local path, URL, git / Kaggle / arXiv / Hugging Face link, or a plain-text idea. The agent-side skill inspects the value, fetches it with whichever tool fits (`cp` / `git clone` / `curl` / `kaggle` CLI / `huggingface-cli` / …), and for text ideas saves the description verbatim to `research_source.md`. No hardcoded scheme sniffing on the Python side. * **Auto-derived `inputs`**: `scientist.new_experiment(...)` no longer needs an `inputs=[...]` argument. Any of `research_source`, `current_notebook`, `current_data` that points at an existing local path is auto-copied into the workspace. * **`experiments_directory` optional**: now defaults to `./experiments`. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.76.1...v0.76.2](https://github.com/Upsonic/Upsonic/compare/v0.76.1...v0.76.2) ### Pull Requests: * feat: AppliedScientist accepts any research\_source + auto inputs: [onuratakan](https://github.com/onuratakan) in [#571](https://github.com/Upsonic/Upsonic/pull/571) * chore: New Version 0.76.2: [onuratakan](https://github.com/onuratakan) in [#572](https://github.com/Upsonic/Upsonic/pull/572) ## v0.76.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.76.1) ## Improvements: * **AppliedScientist `research_paper` → `research_source`**: The prebuilt Applied Scientist agent now accepts any reference describing a new method — local file (PDF, Markdown, HTML, `.ipynb`, text), web URL (blog post, arXiv, documentation), git repository URL, or Kaggle notebook / dataset page — not just a PDF. The agent detects the source kind at Phase 0 and materializes it into the experiment folder (as `research.pdf`, `research_source.{ext}`, or `research_source/`) before reading it in Phase 2. * **Upsonic/Docs submodule**: Added the public docs repository as a git submodule at `Docs/` so the docs site can be kept in lockstep with code changes. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.76.0...v0.76.1](https://github.com/Upsonic/Upsonic/compare/v0.76.0...v0.76.1) ### Pull Requests: * feat: rename AppliedScientist research\_paper to research\_source: [onuratakan](https://github.com/onuratakan) in [#570](https://github.com/Upsonic/Upsonic/pull/570) * chore: New Version 0.76.1: [onuratakan](https://github.com/onuratakan) in [#571](https://github.com/Upsonic/Upsonic/pull/571) ## v0.76.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.76.0) ## New Features: * **New Prebuilt Applied Scientist**: Added a new prebuilt Autonomous Agent for automating the testing of new papers on current ML models. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.75.0...v0.76.0](https://github.com/Upsonic/Upsonic/compare/v0.75.0...v0.76.0) ### Pull Requests: * feat: added prebuilt agent, AppliedScientist: [onuratakan](https://github.com/onuratakan) in [#568](https://github.com/Upsonic/Upsonic/pull/568) * chore: New Version 0.76.0: [onuratakan](https://github.com/onuratakan) in [#569](https://github.com/Upsonic/Upsonic/pull/569) ## v0.75.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.75.0) ## New Features: * KnowledgeBase State Machine: Added `KBState` enum state machine (`UNINITIALIZED → CONNECTED → INDEXED → CLOSED`) replacing boolean flags, with `RuntimeError` guards on invalid states for safer lifecycle management. * KnowledgeBase Content Management APIs: New sync + async APIs including `aadd_source`, `aadd_text`, `aremove_document`, `arefresh`, `adelete_by_filter`, and `aupdate_document_metadata` for comprehensive document management. * KnowledgeBase Storage Table: Added `KnowledgeRow` dataclass with full CRUD support across all 7 storage providers (SQLite, PostgreSQL, MongoDB, Redis, JSON, InMemory, Mem0) for document tracking and content-hash deduplication. * Incremental Change Detection: KnowledgeBase now checks `doc_content_hash` in vectordb to skip unchanged documents and delete stale chunks before re-indexing edited documents. * Isolated Search for KnowledgeBase: New `isolate_search` parameter (default `True`) auto-injects `knowledge_base_id` filter, allowing multiple KnowledgeBases to safely share one collection. ## Improvements: * VectorDB Payload Standardization: Enforced a strict, uniform payload contract across all 6 vector database providers (Qdrant, Milvus, Pgvector, Pinecone, Weaviate, Chroma), making `VectorSearchResult.payload` shape identical regardless of backend. * KnowledgeBase Architecture Refactor: Dropped `ToolKit` inheritance in favor of `get_tools()` returning `FunctionTool.from_callable()`, added `build_context()`/`abuild_context()` for system-prompt generation, and auto-derived collection naming. * VectorDB `aupsert` Validation: Added strict length validation on all per-item arrays with clear `ValueError` messages, and introduced `knowledge_base_ids` as a dedicated parameter across all 6 providers. ## Bug Fixes: * Fixed Autonomous Agent Print Default: Set the autonomous agent class `print` attribute to `True` as default so agent output is visible without manual configuration. * Fixed MCP Streamable HTTP Client: Resolved issues with the MCP Streamable HTTP client connection handling. * Fixed MCP Session Duplication: Fixed a bug where MCP sessions were being duplicated. * Fixed Milvus Metadata Leak: `aupdate_metadata` no longer silently reverts user-specified fields to config defaults. * Fixed Pgvector Delete Bug: Resolved dotted-path bug in `adelete_by_metadata` and fixed JSONB flattening in `_row_to_payload`. * Fixed Qdrant Payload Flattening: Neutered `_flatten_payload` which was actively undoing the standardized payload contract on reads. * Fixed VectorDB Standard Fields Drift: Corrected 3 stale hardcoded literals in Milvus and Weaviate that were missing `knowledge_base_id`, causing silent filter failures and missing scalar indexes. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.74.4...v0.75.0](https://github.com/Upsonic/Upsonic/compare/v0.74.4...v0.75.0) ### Pull Requests: * fix: set autonomous agent class print attribute True as default: [DoganK01](https://github.com/DoganK01) in [#565](https://github.com/Upsonic/Upsonic/pull/565) * Rag refactors: [DoganK01](https://github.com/DoganK01) in [#566](https://github.com/Upsonic/Upsonic/pull/566) * Version 0.75.0: [DoganK01](https://github.com/DoganK01) in [#567](https://github.com/Upsonic/Upsonic/pull/567) ## v0.74.4 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.74.4) ## New Features: * **Mail Interface**: A full-featured SMTP/IMAP-based mail interface that enables agents to send, receive, and process emails with attachment handling, whitelist-based access control, and heartbeat auto-poll. Works with any standard mail provider including Gmail, Outlook, Yahoo, Zoho, and self-hosted servers. ## Improvements: * **Memory flags separation**: Save and load memory flags have been separated, giving more granular control over agent memory persistence behavior. * **VectorDB flags separation**: Setup and query vectordb flags have been separated, allowing independent control over vector database initialization and querying. * **KnowledgeBase query default**: `query_knowledge_base` is now set to `True` by default, enabling knowledge base querying out of the box without explicit configuration. * **PromptLayer threading**: Fixed a threading issue in PromptLayer integration to prevent race conditions during concurrent agent operations. * **StreamableHTTPClientParams auth**: Added `auth` attribute to `StreamableHTTPClientParams`, enabling authentication support for streamable HTTP MCP connections. ## Bug Fixes: * **Command injection in `check_command_exists` (CWE-78)**: Replaced unsafe `subprocess.run` shell invocation with `shutil.which()` to prevent arbitrary command execution via shell metacharacters. * **Profanity policy implementation**: Corrected the profanity policy logic in the safety engine to ensure proper content filtering and policy enforcement. **Full Changelog address:** [v0.74.3...v0.74.4](https://github.com/Upsonic/Upsonic/compare/v0.74.3...v0.74.4) ### Pull Requests: * fix: prevent command injection in check\_command\_exists (CWE-78): [spidershield-contrib](https://github.com/spidershield-contrib) in [#559](https://github.com/Upsonic/Upsonic/pull/559) * feat: mail interface: [DoganK01](https://github.com/DoganK01) in [#560](https://github.com/Upsonic/Upsonic/pull/560) ## v0.74.3 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.74.3) ## New Features: * **Exa web search toolkit**: Agents can use Exa for neural and keyword web search, URL content retrieval, similar-page discovery, and LLM-oriented answers with citations via `ExaTools`. * **E2B sandbox toolkit**: Agents can run Python, JavaScript, Java, R, and Bash in isolated E2B cloud sandboxes with file transfer, shell commands, package installs, and lifecycle controls via `E2BTools`. * **Daytona sandbox toolkit**: Agents can execute code and manage files, Git workflows, and sandbox lifecycle in Daytona cloud environments via `DaytonaTools`. ## Improvements: * **User policy coverage**: Safety policies now evaluate all configured input sources (task description, context, system prompt, chat history, and tool outputs where scoped), not only the task description, so sanitization matches policy scope consistently. * **OCR engine initialization**: OCR providers use thread-safe lazy initialization so concurrent callers share a single reader instance instead of racing during first load. ## Bug Fixes: * **OCR duplicate downloads**: Parallel or repeated initialization of OCR engines could trigger redundant model downloads; locking ensures the engine is created once per provider. **Full Changelog address:** [v0.74.2...v0.74.3](https://github.com/Upsonic/Upsonic/compare/v0.74.2...v0.74.3) ### Pull Requests: * fix: add threading for initializing ocr engines preventing multiple download: [DoganK01](https://github.com/DoganK01) in [#557](https://github.com/Upsonic/Upsonic/pull/557) ## v0.74.2 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/tag/v0.74.2) ## New Features * **Skills safety policies**: Optional safety-engine policies for skill content (prompt injection, secret leak, and code injection) that run when skills are validated, with structured logging and Rich panels for pass/block visibility. ## Improvements * **Execution timing and metrics**: Clearer reporting of total duration, model time, tool time, paused time, and framework overhead, aligned with usage metadata and OpenTelemetry-style attributes where applicable. * **Agent pipeline / message construction**: Former monolithic message build work is split into focused steps (system prompt, context, user input, assembly) so ordering and observability match the rest of the pipeline. * **Streaming parity**: Build-related steps that were missing from the streaming path are now included so streamed runs expose the same step progression as non-streaming runs. ## Bug Fixes * **Total duration tracking**: Fixed incorrect total-duration aggregation so end-to-end timing matches actual wall-clock behavior. * **Metric setting**: Corrected how run-level metrics are set and propagated so dashboards and traces show consistent values. * **Unit tests**: Adjusted tests that incorrectly depended on API keys so they run reliably in CI without live credentials. **Full Changelog:** [v0.74.1…v0.74.2](https://github.com/Upsonic/Upsonic/compare/v0.74.1...v0.74.2) ### Pull Requests * refactor: metric setting fix, safety policies for skills: [DoganK01](https://github.com/DoganK01) in [#552](https://github.com/Upsonic/Upsonic/pull/552) ## v0.74.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.74.1) ## Bug Fixes * **Skill integration smoke tests**: Some tests for skill integration were failing; they are updated so the suite matches current skills behavior and passes reliably. **Full Changelog:** [v0.74.0...v0.74.1](https://github.com/Upsonic/Upsonic/compare/v0.74.0...v0.74.1) ### Pull Requests * fix: fix tests for skill integration: [DoganK01](https://github.com/DoganK01) in [#551](https://github.com/Upsonic/Upsonic/pull/551) ## v0.74.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.74.0) ## New Features * **Apify tools (parameter support)**: Apify actor and run tools accept parameters so agents pass structured inputs to actors and runs. * **Discord interface**: New Discord integration via `DiscordInterface`—Gateway WebSocket, per-user CHAT sessions, attachments, HITL via buttons, streaming edits, whitelist and typing options. * **Skills integration**: Skills load from multiple sources and apply in agent runs as first-class context. ## Improvements * **PgVector provider (identifier safety)**: Schema and table names are validated (alphanumeric and underscores) and DDL uses quoted identifiers, hardening against unsafe identifiers when collection names come from config or agents. ## Bug Fixes * **MCP `call_tool` (streamable-HTTP / SSE)**: Tool calls failed because streamable-HTTP/SSE return a `(read, write, session_id)` tuple like stdio, not a session object—aligned with `connect` so TaskGroup errors no longer occur on every tool call. * **MCP tool results (`EmbeddedResource`)**: `AnyUrl` on embedded resource URIs broke JSON serialization; URIs are normalized with `str()`. * **MCP smoke tests**: Smoke tests updated for the streamable-HTTP/SSE `call_tool` behavior. ## New Contributors * [@RinZ27](https://github.com/RinZ27) made their first contribution in [#541](https://github.com/Upsonic/Upsonic/pull/541) * [@Jimgitsit](https://github.com/Jimgitsit) made their first contribution in [#550](https://github.com/Upsonic/Upsonic/pull/550) **Full Changelog:** [v0.73.2...v0.74.0](https://github.com/Upsonic/Upsonic/compare/v0.73.2...v0.74.0) ### Pull Requests * vectordb: hardening pgvector provider against potential SQL injection: [RinZ27](https://github.com/RinZ27) in [#541](https://github.com/Upsonic/Upsonic/pull/541) * fix: MCP call\_tool fails for streamable-http and SSE transports: [Jimgitsit](https://github.com/Jimgitsit) in [#550](https://github.com/Upsonic/Upsonic/pull/550) * feat: parameter support for apify tools: [DoganK01](https://github.com/DoganK01) in [#547](https://github.com/Upsonic/Upsonic/pull/547) ## v0.73.2 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.73.2) ## Bug Fixes * **Apify tool function schema**: Corrected function tool schema setting for Apify actors so the framework passes the expected schema to the model. **Full Changelog:** [v0.73.1...v0.73.2](https://github.com/Upsonic/Upsonic/compare/v0.73.1...v0.73.2) ### Pull Requests * fix: apify tool function schema fix: [DoganK01](https://github.com/DoganK01) in [#546](https://github.com/Upsonic/Upsonic/pull/546) ## v0.73.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.73.1) ## New Features * **Clanker type alias**: `Clanker` is an alias for `Agent`, exported from `upsonic` / `upsonic.agent` so you can standardize on one symbol or the other without duplicate implementations. * **README IDE integration**: New README section for Cursor, Windsurf, and VS Code using Mintlify-generated `llms-full.txt` to give IDEs full framework context. ## Improvements * **PromptLayer & Langfuse integrations**: Logging flows support primary and named scores (0–100), post-hoc `score`/`ascore`, and dataset run IDs; Langfuse integration adds dataset and dataset-item APIs for evaluation and dataset workflows. ## Bug Fixes * **Unit tests for tracing**: Tests updated/fixed to align with the refactored PromptLayer and Langfuse clients. **Full Changelog:** [v0.73.0...v0.73.1](https://github.com/Upsonic/Upsonic/compare/v0.73.0...v0.73.1) ### Pull Requests * doc: add IDE integration section to README: [IremOztimur](https://github.com/IremOztimur) in [#544](https://github.com/Upsonic/Upsonic/pull/544) * feat: clanker type alias: [DoganK01](https://github.com/DoganK01) in [#545](https://github.com/Upsonic/Upsonic/pull/545) ## v0.73.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.73.0) ## New Features * **Model setting dataclasses for providers**: Typed model configuration classes for multiple LLM providers for clearer, type-safe model setup. * **Langfuse and PromptLayer integration**: Tracing and observability integration with Langfuse and PromptLayer for agent runs. * **HITL integrations (User input, User confirmation, Dynamic user input)**: New human-in-the-loop flows for user input, confirmation, and dynamic input during execution. * **Telegram HITL integration**: Human-in-the-loop support via Telegram for remote confirmation and input. * **Apify integration**: Integration with Apify for using Apify actors and tools from the framework. * **Examples repository as git submodule**: Official [Upsonic/Examples](https://github.com/Upsonic/Examples) repository added as a git submodule under `examples/`. * **Model and tool execution time tracking and metrics table**: Execution time for model and tool calls plus framework overhead surfaced in the metrics table. * **New model providers**: Additional LLM provider support beyond existing providers. ## Improvements * **README content and examples**: Simplified overview and key features; added AutonomousAgent section with code example; Safety Engine example updated to PIIAnonymizePolicy; OCR installation and usage example; AgentOS section condensed. * **Discord community badge and CTA**: Discord badge in the header badge row and invite link in quick nav and Community & Support section for better community visibility. * **ToolKit refactor**: Refactored ToolKit implementation for clearer structure and maintainability. * **Task and Agent metrics refactor**: Refactored task and agent metrics collection and reporting. * **Anthropic input type**: Enhanced input type handling for the Anthropic provider. * **Team printing logic**: Team printing behavior aligned with Agent printing for consistent console output. * **Usage tracking**: Refactored usage tracking implementation. ## Bug Fixes * **AutonomousAgent streaming**: Fixed streaming behavior for AutonomousAgent. * **ContextManagementMiddleware**: Fixed context management middleware behavior. * **Bedrock environment variable**: Corrected environment variable handling for AWS Bedrock. **Full Changelog**: [https://github.com/Upsonic/Upsonic/compare/v0.72.6...v0.73.0](https://github.com/Upsonic/Upsonic/compare/v0.72.6...v0.73.0) ### Pull Requests * docs: update README content and examples: [@IremOztimur](https://github.com/IremOztimur) in [#535](https://github.com/Upsonic/Upsonic/pull/535) * feat: add Examples repository as a git submodule: [@IremOztimur](https://github.com/IremOztimur) in [#542](https://github.com/Upsonic/Upsonic/pull/542) * doc: add Discord community badge to README: [@IremOztimur](https://github.com/IremOztimur) in [#543](https://github.com/Upsonic/Upsonic/pull/543) * feat: new model setting classes for models: [@DoganK01](https://github.com/DoganK01) in [#540](https://github.com/Upsonic/Upsonic/pull/540) ## v0.72.6 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.72.6) ## New Features: * **Qdrant config smoke tests:** Test classes for every QdrantConfig attribute in IN\_MEMORY and CLOUD modes. ## Improvements: * **Qdrant text index creation:** TextIndexParams now always include a tokenizer and defaults so Cloud and local work without "unknown tokenizer type." * **Qdrant error handling:** Field index failures raise one VectorDBError; full-text index and collection\_exists no longer swallow exceptions (only 404/not-found is handled). * **Qdrant smoke test assertions:** Smoke test enhanced ## Bug Fixes: * **Qdrant text index on Cloud:** Fixed "unknown tokenizer type" by always setting tokenizer and default params in schema and index creation. * **Qdrant swallowed exceptions:** \_create\_field\_indexes, \_server\_side\_full\_text\_search, and collection\_exists now propagate errors instead of silently ignoring them. Full Changelog: [v0.72.5...v0.72.6](https://github.com/Upsonic/Upsonic/compare/v0.72.5...v0.72.6) ### Pull Requests: * *(Add PR name and link when merged.)* ## v0.72.5 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.72.5) ## New Features: * **Agent metrics**: Agent runs now expose accumulated usage (tokens, cost) and tool execution tracking for observability and cost monitoring. * **SuperMemory integration**: New vector database provider `SuperMemoryProvider` for RAG and knowledge base, with async SuperMemory API support, configurable via `SuperMemoryConfig` or `upsonic[supermemory]`. ## Improvements: * **Tool managers (Task vs Agent)**: Task-level tools use a dedicated `ToolManager` on the task; agent and task tool definitions are combined and resolved correctly for validation and execution. * **Anthropic default max tokens**: Default `max_tokens` for Anthropic API increased from 4096 to 16384 for longer responses. * **Pydantic response format in streaming**: When using a Pydantic `response_format` on a task, streaming tool calls for the output tool are validated with `model_validate` and handled correctly in streaming mode. ## Bug Fixes: * **finish\_reason "length"**: When the model hits `max_tokens` and returns `finish_reason == "length"`, tool calls are no longer executed with possibly truncated arguments; the agent is informed via a tool-return message and can retry with shorter content or smaller steps. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.72.4...v0.72.5](https://github.com/Upsonic/Upsonic/compare/v0.72.4...v0.72.5) ### Pull Requests: * feat: supermemory storage, agent metrics: [DoganK01](https://github.com/DoganK01) in [#536](https://github.com/Upsonic/Upsonic/pull/536) ## v0.72.4 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.72.4) ## Bug Fixes: * **Firecrawl & Anthropic API:** Fixed incorrect Firecrawl and Anthropic API usage so the framework works with current API versions. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.72.3...v0.72.4](https://github.com/Upsonic/Upsonic/compare/v0.72.3...v0.72.4) ### Pull Requests: * fix: fix wrong api usage and anthropic api usage for new versions: [DoganK01](https://github.com/DoganK01) in [#533](https://github.com/Upsonic/Upsonic/pull/533) * Version 0.72.4: [DoganK01](https://github.com/DoganK01) in [#534](https://github.com/Upsonic/Upsonic/pull/534) ## v0.72.3 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.72.3) ## New Features: * Agent execution timeout: Optional `timeout` (seconds) on `do`, `do_async`, `print_do`, and `print_do_async`; execution is cancelled after the limit and `ExecutionTimeoutError` is raised unless partial results are requested. * Partial result on timeout: When `partial_on_timeout=True` and a timeout is set, the agent returns whatever text was generated so far instead of raising; uses streaming internally to accumulate output progressively. * Firecrawl custom tool: New Firecrawl integration with sync/async support; added as optional dependency `firecrawl-py>=4.14.1`. * ExecutionTimeoutError: New exception in `upsonic.exceptions` for timeout scenarios, carrying the timeout value for programmatic handling. ## Improvements: * Persistent background event loop: Sync entry points use a single daemon-thread event loop instead of `asyncio.run()` per call, avoiding "Event loop is closed" and connection-pool issues with SDK clients. * Token usage on partial/timeout: When execution ends due to timeout with partial results, usage is recorded so task token counts remain accurate. * Pipeline cancellation handling: Pipeline manager handles `GeneratorExit` gracefully when execution is cancelled by timeout; `RunCompletedEvent` only emitted when step results exist. * Mem0 storage: Implementation and tests updated for mem0 sync/async storage. * Retry and usage utilities: Adjusted for timeout and partial-result flows; Firecrawl and custom tools aligned with shared patterns and tests added. ## Bug Fixes: * Sync execution event loop: Fixed sync agent/team methods failing or leaving closed event loops when called repeatedly by using a persistent background loop. * Firecrawl tool attributes: Corrected tool attribute definitions and usage in Firecrawl custom tool and tests. * Unit test usage: Fixed unit test usage and expectations for new timeout and partial-result behavior. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.72.2...v0.72.3](https://github.com/Upsonic/Upsonic/compare/v0.72.2...v0.72.3) ### Pull Requests: * feat: add timeout and partial result handling in Agent execution [@onuratakan](https://github.com/onuratakan) in [#532](https://github.com/Upsonic/Upsonic/pull/532) ## v0.72.2 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.72.2) ## New Features: * Agent/Team as MCP tool: Agent and Team can be exposed as MCP via `as_mcp()` and consumed as MCP tools by other agents. * Nested Teams: Teams can contain both Agents and other Teams for hierarchical multi-agent workflows. * Team leader and router: Optional `leader` and `router` Agent arguments when creating a Team for coordinate and route modes. * Team async and streaming: Team supports `do_async`/`ado` and `astream`/`stream` for use as an entity inside another Team or in async pipelines. * Task list execution: Agent and Team accept a list of tasks for `do`, `do_async`, `print_do`, and `print_do_async`, returning a list of results. * Eval and MCP smoke tests: New smoke tests for Accuracy/Performance/Reliability evals and for Agent/Team as MCP; nested team and task metrics tests added. * Makefile deps\_smoke: New target to install optional deps (storage, faiss) for smoke tests. ## Improvements: * Printing and cost tracking: Price tracking runs even when `print_output` is False; new `show_tool_calls` allows showing tool-calls tables independently. * Jupyter compatibility: Team and Autonomous Agent sync methods run async work in a separate thread when a loop is already running, fixing `print_do`/`do` in notebooks. * MCP environment: MCP server subprocesses inherit the full process environment (API keys, PYTHONPATH, .env) with user overrides. * Workspace: References use `AGENTS.md`; greeting prompt and behavior refined. * Storage: Optional backends use safe lazy loading so missing deps do not break other storage imports. * Team internals: Coordinator, task assignment, context sharing, delegation, and result combiner support both Agent and Team entities; delegation tool simplified and debug option added. * Agent: Added `get_entity_id()` for unified entity interface with Team. ## Bug Fixes: * print\_do in Jupyter: Fixed sync `do`/`print_do` hanging or failing when a reactor (e.g. Jupyter) already has a running event loop by using a dedicated thread for async execution. * Smoke tests: Updated to new printing behavior, print capture, and optional deps so the smoke suite passes with current Agent/Team and eval usage. * Fixed retry and Task error status conflict. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.72.1...v0.72.2](https://github.com/Upsonic/Upsonic/compare/v0.72.1...v0.72.2) ### Pull Requests: * feat: Agent/Team as mcp tool, Team can be put inside Team [@DoganK01](https://github.com/DoganK01) in [#526](https://github.com/Upsonic/Upsonic/pull/526) * fix: fix smoke tests by using new printing usage [@DoganK01](https://github.com/DoganK01) in [#529](https://github.com/Upsonic/Upsonic/pull/529) * chor: version 0.72.2 [@DoganK01](https://github.com/DoganK01) in [#530](https://github.com/Upsonic/Upsonic/pull/530) * fix: fix retry and task error status collision [@DoganK01](https://github.com/DoganK01) in [#531](https://github.com/Upsonic/Upsonic/pull/531) ## v0.72.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.72.1) ## New Features: * **Asynchronous OCR processing**: Added async-first OCR pipeline with `get_text_async` and `process_file_async` entry points so document processing can run without blocking. * **Document conversion layer (Layer 0)**: New document-to-image conversion layer using PyMuPDF for PDF rendering, EXIF-based orientation correction, and optional downscaling for large images before OCR. * **OCR engine API and timeouts**: OCR providers refactored into instantiated engine classes (e.g. `EasyOCREngine`, `RapidOCREngine`, `TesseractOCREngine`, `DeepSeekOCREngine`, Paddle engines); added `OCRTimeoutError` and optional per-page timeouts for long-running jobs. ## Improvements: * **OCR PDF backend**: PDF conversion switched from pdf2image/poppler to PyMuPDF (fitz) for rendering; `ocr` extra dependency updated accordingly. * **OCR image preprocessing**: `load_image` now applies EXIF-based orientation correction so rotated images are normalized before OCR. * **Dependency and tooling**: Updated vulnerable packages and pinned/specified uv version for reproducible installs. ## Bug Fixes: * **LLM usage tracking**: Fixed usage (input/output/reasoning tokens and details) not being accumulated when agent runs used `do_async` without returning output, or when `RunUsage.incr` received usage objects with non-dict or missing `details`; usage is now correctly aggregated across agent, safety engine LLM, reflection, reliability layer, cache, culture, tools, and storage. **Full Changelog:** [https://github.com/Upsonic/Upsonic/compare/v0.72.0...v0.72.1](https://github.com/Upsonic/Upsonic/compare/v0.72.0...v0.72.1) ### Pull Requests: * fix: fix LLM usage tracking – [DoganK01](https://github.com/DoganK01) in [#525](https://github.com/Upsonic/Upsonic/pull/525) * chore: update vulnerable packages and specify uv version – [angryfoxx](https://github.com/angryfoxx) in [#523](https://github.com/Upsonic/Upsonic/pull/523) * feat: implement asynchronous OCR processing and add new document conversion layer – [onuratakan](https://github.com/onuratakan) in [#527](https://github.com/Upsonic/Upsonic/pull/527) * chore: version 0.72.1 – [DoganK01](https://github.com/DoganK01) in [#528](https://github.com/Upsonic/Upsonic/pull/528) ## v0.72.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/tag/v0.72.0) ## New Features: * Telegram interface: Adds a full Telegram bot interface and tooling so agents can be used over Telegram (webhook, messages, media). * Chat and Task modes for interfaces: All interfaces (Slack, WhatsApp, Gmail, Telegram) support Chat mode (single Chat instance) and Task mode (single Agent instance) for consistent behavior. * Autonomous Agent: New AutonomousAgent class — a pre-configured agent with built-in filesystem and shell toolkits, workspace sandboxing, and default in-memory storage for coding assistants, DevOps automation, and system administration tasks. * Context management middleware: Automatic context window management that prunes tool call history and summarizes old messages when the conversation approaches the model's context limit, replacing the previous compression strategy. * Workspace support: Agents can be configured with a workspace folder containing an Agents.md file whose content is included in the system prompt and used to generate a greeting message before the first task or chat. ## Improvements: * Benchmarks documentation: benchmarks/QUICKSTART.md was translated from Turkish to English for consistent English docs. * CLI and interface compatibility: Interfaces can now be started via the upsonic run CLI command instead of only programmatically. * Optional context compression model: Context management middleware accepts an optional context\_compression\_model parameter, allowing a separate (typically larger-context-window) model for the summarization step while keeping the primary model for regular operations. ## Bug Fixes: * Gmail encoding: Fixed encoding for non-ASCII characters in the Gmail interface so messages with non-ASCII letters are handled correctly. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.71.6...v0.72.0](https://github.com/Upsonic/Upsonic/compare/v0.71.6...v0.72.0) ### Pull Requests: * docs: translate benchmarks QUICKSTART.md to English: [IremOztimur](https://github.com/IremOztimur) in [#522](https://github.com/Upsonic/Upsonic/pull/522) * feat: telegram interface, chat/task modes for interfaces: [DoganK01](https://github.com/DoganK01) in [#521](https://github.com/Upsonic/Upsonic/pull/521) * refactor: cli and interface compatibility: [DoganK01](https://github.com/DoganK01) in [#524](https://github.com/Upsonic/Upsonic/pull/524) ## v0.71.6 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.71.6) ## Improvements: * Anonymization: We moved the anonymization step to an earlier part of the pipeline for a better developer experience. **Full Changelog**: [https://github.com/Upsonic/Upsonic/compare/v0.71.5...v0.71.6](https://github.com/Upsonic/Upsonic/compare/v0.71.5...v0.71.6) ## v0.71.5 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.71.5) ## New Features: * Benchmark Module: Added a benchmark module for analyzing framework speed * New Tool: Added Bocha Web Search Tool ## Improvements: * Anonymization: Resolved an issue with the anonymization action in the safety policies * Test Run Commands: Updated the test run commands for a better test run experience ## New Contributors * @weijintaocode made their first contribution in [https://github.com/Upsonic/Upsonic/pull/518](https://github.com/Upsonic/Upsonic/pull/518) **Full Changelog**: [https://github.com/Upsonic/Upsonic/compare/v0.71.4...v0.71.5](https://github.com/Upsonic/Upsonic/compare/v0.71.4...v0.71.5) ### Pull Requests: * feat: add comprehensive benchmark system for performance analysis by @IremOztimur in [https://github.com/Upsonic/Upsonic/pull/511](https://github.com/Upsonic/Upsonic/pull/511) * add bocha web search tool by @weijintaocode in [https://github.com/Upsonic/Upsonic/pull/518](https://github.com/Upsonic/Upsonic/pull/518) * fix: Resolved anonymization action logic by @onuratakan in [https://github.com/Upsonic/Upsonic/pull/519](https://github.com/Upsonic/Upsonic/pull/519) * docs: fix test command in CONTRIBUTING.md to use uv run by @IremOztimur in [https://github.com/Upsonic/Upsonic/pull/520](https://github.com/Upsonic/Upsonic/pull/520) ## v0.71.4 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.71.4) ## New Features: * Event Streaming Chat: Added event streaming capability to chat functionality, enabling real-time visibility into tool calls, text deltas, and execution events through `chat.stream(events=True)`. ## Improvements: * Agent Printing Hierarchy: Refactored the agent printing system with a clear priority hierarchy (environment variable > constructor parameter > method name) for better control over output behavior. ## Bug Fixes: *(No bug fixes in this release)* Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.71.3...v0.71.4](https://github.com/Upsonic/Upsonic/compare/v0.71.3...v0.71.4) ### Pull Requests: * Refactor agent printing hierarchy: [@DoganK01](https://github.com/DoganK01) in [#515](https://github.com/Upsonic/Upsonic/pull/515) * Add event streaming chat: [@DoganK01](https://github.com/DoganK01) in [#516](https://github.com/Upsonic/Upsonic/pull/516) * Version 0.71.4: [@DoganK01](https://github.com/DoganK01) in [#517](https://github.com/Upsonic/Upsonic/pull/517) ## v0.71.2 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.71.2) ## New Features: ## Improvements: ## Bug Fixes: * Fixed Agent Printing: Resolved issue with Agent instance string representation and display functionality. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.71.1...v0.71.2](https://github.com/Upsonic/Upsonic/compare/v0.71.1...v0.71.2) ### Pull Requests: * fix: fix Agent printing: [@DoganK01](https://github.com/DoganK01) in [#513](https://github.com/Upsonic/Upsonic/pull/513) ## v0.71.1/v0.71.2 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.71.1) ## New Features: ## Improvements: * Developer Onboarding Documentation: Enhanced the CONTRIBUTING.md file with improved developer onboarding flow, clearer setup instructions, and comprehensive development guidelines to help new contributors get started faster. * Infrastructure Documentation Section: Added a dedicated infrastructure section to the documentation, providing developers with essential information about the project's technical infrastructure, setup requirements, and development environment configuration. * Culture Module Refactoring: Instructions are improved so that Agent strictly follows the culture. * Agent and Direct class printing: Made Agent and Direct class printings dependent on 'print' flag. ## Bug Fixes: Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.71.0...v0.71.1](https://github.com/Upsonic/Upsonic/compare/v0.71.0...v0.71.1) ### Pull Requests: * docs: improve developer onboarding flow and add infrastructure section: [IremOztimur](https://github.com/IremOztimur) in [#509](https://github.com/Upsonic/Upsonic/pull/509) * refactor: refactor culture: [DoganK01](https://github.com/DoganK01) in [#512](https://github.com/Upsonic/Upsonic/pull/512) ## v0.71.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.71.0) ## New Features: * Culture and CultureManager: Added a new Culture system that allows defining agent behavior and communication guidelines through user descriptions, with CultureManager automatically extracting structured guidelines (tone of speech, topics to avoid/help with, attention points) using LLM extraction and formatting them for system prompt injection. ## Improvements: * Makefile for Smoke Tests: Created Makefile to streamline smoke testing processes with automated docker-compose integration, health checks, and better test execution workflows. * README Documentation: Refactored README to follow open-source standards, improving project documentation quality and accessibility for new contributors and users. * Interface Testing: Enhanced testing coverage for interface components (WhatsApp, Slack, Gmail) to ensure better reliability and stability of communication platform integrations. ## Bug Fixes: * Fixed metrics not being set using Direct class. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.70.0...v0.71.0](https://github.com/Upsonic/Upsonic/compare/v0.70.0...v0.71.0) ### Pull Requests: * Cultural Knowledge: [DoganK01](https://github.com/DoganK01) in [#506](https://github.com/Upsonic/Upsonic/pull/506) * refactor: Makefile for smoke tests: [DoganK01](https://github.com/DoganK01) in [#505](https://github.com/Upsonic/Upsonic/pull/505) * docs: refactor README to follow open-source standards: [IremOztimur](https://github.com/IremOztimur) in [#507](https://github.com/Upsonic/Upsonic/pull/507) * Interface testing: [DoganK01](https://github.com/DoganK01) in [#508](https://github.com/Upsonic/Upsonic/pull/508) * chore: version 0.71.0: [DoganK01](https://github.com/DoganK01) in [#510](https://github.com/Upsonic/Upsonic/pull/510) ## v0.70.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.70.0) ## New Features: * Agent Run Implementation: Introduced "Agent Run" architecture with `AgentRunInput` and `AgentRunOutput` dataclasses, providing type safety, clear contracts, and a single source of truth for agent execution state. * Memory Modes for UEL: Added `user_memory_mode` parameter with 'update' and 'replace' options to solve conflicts between placeholder history and model history. * AgentSession Class: New session management class for storing agent-related information across multiple runs with proper lifecycle management. * Parallel Tool Call Support: Added support for parallel tool calls when external tool execution is enabled, improving throughput for multi-tool operations. * Agent Metadata Attribute: New `metadata` attribute in Agent class that enables users to inject any metadata directly into the prompt. * Dynamic Search Tool for KnowledgeBase: Introduced dynamic `search` tool when KnowledgeBase is used as a tool (RAG as tool functionality). * MCP Tool Name Prefix: Added tool name prefix support for MCP tools, allowing different function tools with the same name to be used for different purposes. * RunRequirement Class: New class for managing Human-in-the-Loop (HITL) requirements with clear distinction between confirmation, user input, and external execution needs. * Run Cancellation Manager: Thread-safe cancellation management with proper lifecycle methods (`register_run`, `cancel_run`, `cleanup_run`). * External Tool Callable Support: For one-tool-at-a-time calls with external tool execution, callable is provided as argument for background handling. * Debug Level 2: Enhanced debugging capabilities with additional logging and visibility. ## Improvements: * Context Managers Refactored: Converted context managers to regular classes to align with the step-based architecture in Agent flow. * HITL Logic Refactored: Human-in-the-Loop logics are now managed by the `RunRequirement` class with improved and cleaner usage patterns. * Streaming Logic Refactored: Removed unnecessary and confusing stream methods in Agent class, consolidating streaming functionality. * Storage Providers Refactored: Comprehensive storage system overhaul with abstract `Storage` base class and support for multiple backends (In-Memory, JSON, SQLite, Redis, PostgreSQL, MongoDB, Mem0). * Improved Event System: Enhanced event streaming architecture with comprehensive event types for better observability. * Test Organization: Reorganized tests by moving smoke tests from unit\_tests directory into dedicated smoke\_tests directory for clearer separation. * AgentRunContext Removal: Removed `AgentRunContext` class and made everything dependent on `AgentRunOutput` for simplified state management. ## Bug Fixes: * Fixed System Prompt Setup: Resolved issue where system prompt was not being set up correctly in certain scenarios. * Fixed Test Compatibility: Addressed test compatibility issues across different Python versions. * Fixed Notebook Issues: Resolved issues with Jupyter notebook examples. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.69.0...v0.70.0](https://github.com/Upsonic/Upsonic/compare/v0.69.0...v0.70.0) ### Pull Requests: * Agent Run Implementation: [DoganK01](https://github.com/DoganK01) in [#504](https://github.com/Upsonic/Upsonic/pull/504) ## v0.69.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.69.1) ## New Features: * **Model ID Normalization**: Allows simplified model IDs (e.g., `bedrock/claude-3-5-sonnet:v2`) to be automatically normalized to full provider IDs. ## Improvements: * **Structured Output Mode**: Changed `output_mode` from "native" to "auto" for better cross-model compatibility. * **Output Tools Support**: Added tool-based structured output for models that don't support native JSON schemas (like Bedrock). ## Bug Fixes: * **Fixed Structured Output for Bedrock**: Resolved `UserError: Native structured output is not supported by this model` when using Pydantic response formats with Bedrock models. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.69.0...v0.69.1](https://github.com/Upsonic/Upsonic/compare/v0.69.0...v0.69.1) ### Pull Requests: * fix: fix normalizing model ids: [DoganK01](https://github.com/DoganK01) in [#498](https://github.com/Upsonic/Upsonic/pull/498) ## v0.69.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.69.0) ## New Features: * Event-Based Streaming System: Introduced an event-based streaming architecture with 30+ event types providing granular visibility into agent execution, including PipelineEvents, StepEvents, and LLM Stream Events with proper timestamp tracking and type-safe event handling. * Profanity Safety Policy: Added profanity detection capabilities using Detoxify ML library with support for 5 different models (original, unbiased, multilingual variants) with configurable sensitivity thresholds and proper lazy loading for optimal performance. * Policy Feedback Loop: Implemented user and agent policy feedback mechanisms that provide constructive feedback instead of hard blocking, allowing policies to guide users and agents with helpful messages and configurable retry counts to prevent wasted agent cycles. * CLI Remove Command: Added new "remove" command for removing packages from upsonic\_configs.json, providing better package management capabilities in the CLI interface. * Azure and Grok Model Providers: Added support for Azure and Grok model providers, expanding the framework's model compatibility and integration options. * ismethod Support for Tool Management: Added support for handling methods in tool management, enabling more flexible tool registration and usage patterns. ## Improvements: * Runtime Performance Optimization: Enhanced runtime performance through lazy importing to reduce initial load times and improve overall framework responsiveness. * Memory Logging: Added informative logging for Memory operations to improve debugging and monitoring capabilities during agent execution. * DeepAgent TODO Printing: Enhanced DeepAgent with TODO printing functionality to provide better visibility into planning and execution steps. * CLI Configuration Management: Refactored CLI initialization to use upsonic\_configs.json for all configurations, removing io.py dependency and improving maintainability and performance. ## Bug Fixes: * LLMLingua Prompt Compression API Fix: Resolved issues with the LLMLingua prompt compression API integration to ensure proper prompt compression functionality. * Milvus Import Error Handling: Fixed unnecessary import error for Milvus by moving error management to **init** to prevent import failures when Milvus is not installed. * Bedrock Model Profile Creation: Fixed Bedrock provider model profile creation to ensure proper initialization and configuration of AWS Bedrock models. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.68.3...v0.69.0](https://github.com/Upsonic/Upsonic/compare/v0.68.3...v0.69.0) ### Pull Requests: * feat: version 0.69.0: [@DoganK01](https://github.com/DoganK01) in [#497](https://github.com/Upsonic/Upsonic/pull/497) ## v0.68.2 & v0.68.3 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.68.2) ## New Features: * DeepSeek OCR Provider: Added new OCR provider using Ollama's deepseek-ocr:3b model for image text extraction with customizable host, model, and prompt support * New Model Support: Expanded model compatibility with additional model integrations for enhanced AI capabilities ## Improvements: * Smoke Tests & Refactoring: Added comprehensive smoke tests and refactored codebase for improved reliability and maintainability * Image Output Utilities: Added utility functions for enhanced image output processing and handling capabilities ## Bug Fixes: * Bedrock Profile Creation: Fixed AWS Bedrock API profile creation issue that prevented proper inference profile setup and model initialization Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.68.1...v0.68.2](https://github.com/Upsonic/Upsonic/compare/v0.68.1...v0.68.2) ### Pull Requests: * feat: Added deepseek-ocr with ollama: [@onuratakan](https://github.com/onuratakan) in [#491](https://github.com/Upsonic/Upsonic/pull/491) * refactor: new smoke tests and bug fix: [@DoganK01](https://github.com/DoganK01) in [#492](https://github.com/Upsonic/Upsonic/pull/492) * New models: [@DoganK01](https://github.com/DoganK01) in [#493](https://github.com/Upsonic/Upsonic/pull/493) * chore: image output utils: [@DoganK01](https://github.com/DoganK01) in [#494](https://github.com/Upsonic/Upsonic/pull/494) * fix: bedroc profile creation fix: [@DoganK01](https://github.com/DoganK01) in [#495](https://github.com/Upsonic/Upsonic/pull/495) ## v0.68.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.68.1) ## New Features: ## Improvements: ## Bug Fixes: * Fixed Knowledge Base Search Tool Docstring: Corrected the docstring for the search tool from knowledge base to ensure accurate documentation. * Fixed MCP Closing Logic: Added proper closing logic for MCP (Model Context Protocol) connections to prevent resource leaks. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.68.0...v0.68.1](https://github.com/Upsonic/Upsonic/compare/v0.68.0...v0.68.1) ### Pull Requests: * fix docstring of search tool from knowledgebase, add mcp closing logic: [@DoganK01](https://github.com/DoganK01) in [#489](https://github.com/Upsonic/Upsonic/pull/489) * version 0.68.1: [@DoganK01](https://github.com/DoganK01) in [#490](https://github.com/Upsonic/Upsonic/pull/490) ## v0.68.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/tag/v0.68.0) ## New Features: * **Dynamic Tool Management via Agent Class**: Added `add_tools()` and `remove_tools()` methods to the Agent class and Task class, enabling runtime tool configuration and dynamic tool lifecycle management. * **KnowledgeBase as Tool (RAG as Tool)**: KnowledgeBase can now be injected as a tool, allowing RAG capabilities to be seamlessly integrated into agent workflows through the tool system. * **Gmail Integration Interface**: New Gmail tools and interface with OAuth 2.0 authentication support, enabling agents to send and manage emails through Gmail API. * **WhatsApp Integration Interface**: New WhatsApp tools and interface for sending messages and managing WhatsApp communications programmatically. * **Slack Integration Interface**: New Slack tools and interface for interacting with Slack workspaces, channels, and messages. * **Tool Safety Policy Framework**: Introduced `ToolPolicyManager` with pre-execution and post-execution validation capabilities, providing robust security layers for tool registration and invocation. * **String Task Auto-Conversion**: Agents now support string task descriptions that are automatically converted to Task objects, simplifying the API with `agent.do("task description")` and `agent.do_async("task description")` syntax. ## Improvements: * **DeepAgent Architecture Refactoring**: Complete refactoring of DeepAgent from monolithic structure to modular architecture with clear separation of concerns, including new backend abstractions (BackendProtocol, StateBackend, MemoryBackend) and toolkit-based design. * **Centralized Tool Handling**: Tool management has been centralized and streamlined, removing unnecessary complexity and providing better organization through the improved ToolManager system. * **Import Error Handling**: Added comprehensive `import_error()` helper function across 73 files to provide better user experience and clearer error messages when optional dependencies are missing. * **Tool Deduplication**: Enhanced tool registration system with smart deduplication logic to prevent duplicate tool registrations and improve tool lifecycle management. * **Async Tool Validation**: Improved async/await patterns in tool policy validation. ## Bug Fixes: * **Groq Client Import Fix**: Fixed import issues with Groq client to ensure proper module loading and error handling. * **Test Suite Fixes**: Fixed various unit tests to align with the refactored architecture and new tool management system. * **Conftest Configuration Fix**: Resolved configuration issues in test setup files to ensure proper test execution. * **Tool Registration Edge Cases**: Fixed issues with tool registration duplication and improved handling of edge cases in the tool management system. Full Changelog: [https://github.com/Upsonic/Upsonic/compare/v0.67.4...v0.68.0](https://github.com/Upsonic/Upsonic/compare/v0.67.4...v0.68.0) ### Pull Requests: * New features: [@DoganK01](https://github.com/DoganK01) in [#488](https://github.com/Upsonic/Upsonic/pull/488) ## v0.67.4 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.67.4) ## New Features: ## Improvements: ## Bug Fixes: * Fixed Run Command Import Functionality: The run command was not properly importing other files from the same directory or project structure. This has been fixed by correctly setting up sys.path, **package**, and **name** attributes to ensure proper module resolution and relative imports work correctly when executing agents. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.67.3...v0.67.4](https://github.com/Upsonic/Upsonic/compare/v0.67.3...v0.67.4) ### Pull Requests: * fix: fix run command not importing other files: [@DoganK01](https://github.com/DoganK01) in [#486](https://github.com/Upsonic/Upsonic/pull/486) * chor: new version 0.67.4: [@DoganK01](https://github.com/DoganK01) in [#487](https://github.com/Upsonic/Upsonic/pull/487) ## v0.67.3 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.67.3) ## New Features: ## Improvements: * Import Error Handling: Added comprehensive error logging for import errors and fixed circular import issues to improve code reliability and debugging capabilities. ## Bug Fixes: * Circular Import Fix: Resolved circular import dependencies that were causing import errors in the codebase. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.67.2...v0.67.3](https://github.com/Upsonic/Upsonic/compare/v0.67.2...v0.67.3) ### Pull Requests: * refactor: import error log adding and circular import fix: [@DoganK01](https://github.com/DoganK01) in [#484](https://github.com/Upsonic/Upsonic/pull/484) ## v0.67.2 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.67.2) ## New Features: * CLI Update for AgentOS Compatibility: Updated CLI structure to align with AgentOS standards, including improved project structure with src/ directory, consistent naming conventions, and enhanced configuration management. ## Improvements: * Comprehensive Unit Tests for Team Feature: Added extensive unit test coverage for the team/multi-agent functionality, including tests for context sharing, coordinator setup, delegation management, result combining, task assignment, and team execution modes. * MCP Tool Handling Class Refactor: Refactored MCP tool handling architecture with better separation of concerns, transitioning from direct session management to a cleaner composition-based design where MultiMCPHandler delegates to individual MCPHandler instances, improving code maintainability and introspection capabilities. * Unit Tests for Graph Feature: Added comprehensive unit tests for the graph feature, ensuring better code quality and reliability. * Unit Tests for Tools Feature: Added comprehensive unit tests for the tools system, improving test coverage and ensuring robust tool functionality. ## Bug Fixes: * Fixed YFinanceTools Import and Notebook Cells: Corrected incorrect YFinanceTools import and updated notebook cells to ensure proper functionality of financial data tools. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.67.1...v0.67.2](https://github.com/Upsonic/Upsonic/compare/v0.67.1...v0.67.2) ### Pull Requests: * unit tests added for team feature: [@sxroads](https://github.com/sxroads) in [#478](https://github.com/Upsonic/Upsonic/pull/478) * refactor: mcp tool handling class refactor: [@DoganK01](https://github.com/DoganK01) in [#481](https://github.com/Upsonic/Upsonic/pull/481) * unit tests added for the graph feature: [@sxroads](https://github.com/sxroads) in [#477](https://github.com/Upsonic/Upsonic/pull/477) * tests : unit tests added for the tools feauture: [@sxroads](https://github.com/sxroads) in [#476](https://github.com/Upsonic/Upsonic/pull/476) * fix: correct YFinanceTools import and update notebook cells: [@IremOztimur](https://github.com/IremOztimur) in [#473](https://github.com/Upsonic/Upsonic/pull/473) * cli update for agentos: [@DoganK01](https://github.com/DoganK01) in [#482](https://github.com/Upsonic/Upsonic/pull/482) ## v0.67.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.67.1) ## New Features: * Image Output Support: Added comprehensive image output support for agent responses, enabling agents to generate and return images through the Agent and Whatsapp interfaces. Supports multiple image outputs with proper base64 encoding/decoding and media upload handling. * Interface support: Added Whatsapp interface support enabling users to communicate with Agents through Whatsapp. ## Improvements: * Interfaces System Enhancement: Improved WebSocket authentication flow with message-based action handling, better connection management, and cleaner API design. Added support for action-based messages (authenticate, ping, message) with structured event responses and enhanced error handling. ## Bug Fixes: * No bug fixes in this release. Full Changelog address: [https://github.com/Upsonic/Upsonic/compare/v0.67.0...v0.67.1](https://github.com/Upsonic/Upsonic/compare/v0.67.0...v0.67.1) ### Pull Requests: * Interfaces: [@DoganK01](https://github.com/DoganK01) in [#479](https://github.com/Upsonic/Upsonic/pull/479) * refactor: image output support adding and general refactor: [@DoganK01](https://github.com/DoganK01) in [#474](https://github.com/Upsonic/Upsonic/pull/474) * chore: v0.67.1: [@DoganK01](https://github.com/DoganK01) in [#480](https://github.com/Upsonic/Upsonic/pull/480) ## v0.67.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.67.0) ## New Features: * CLI Support: Added comprehensive command-line interface support for Upsonic, enabling users to interact with the framework directly from the terminal with intuitive commands and workflows. ## Improvements: * VectorDB v2 Refactoring: Complete architectural overhaul of the vector database system with improved async-first design, enhanced provider abstraction, and better performance optimization for vector operations across all supported providers. * Dependency Management: Removed the 'run' optional dependency group to streamline package installation and reduce unnecessary dependencies, making the framework more lightweight and easier to install. ## Bug Fixes: * Unit Tests: Fixed various unit test issues and improved test reliability to ensure better code quality and framework stability across different environments and configurations. **Full Changelog**: [https://github.com/Upsonic/Upsonic/compare/v0.66.1...v0.67.0](https://github.com/Upsonic/Upsonic/compare/v0.66.1...v0.67.0) ### Pull Requests: * refactor: vectordb v2: [@DoganK01](https://github.com/DoganK01) in [#467](https://github.com/Upsonic/Upsonic/pull/467) * feat: CLI support for upsonic: [@DoganK01](https://github.com/DoganK01) in [#468](https://github.com/Upsonic/Upsonic/pull/468) * fix of unit tests commit: [@sxroads](https://github.com/sxroads) in [#469](https://github.com/Upsonic/Upsonic/pull/469) * refactor: remove 'run' optional dependency group: [@DoganK01](https://github.com/DoganK01) in [#471](https://github.com/Upsonic/Upsonic/pull/471) * feat: 0.67.0 release: [@DoganK01](https://github.com/DoganK01) in [#472](https://github.com/Upsonic/Upsonic/pull/472) ## v0.66.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.66.1) ## Improvements: * **Ollama Model Configuration**: Enhanced Ollama provider integration by enabling "model as string" support, allowing simplified string-based model configuration instead of requiring model class instantiation. Users can now specify Ollama models using the convenient `"ollama/model-name"` string format, making it easier to switch between models and configure them via environment variables. ## Bug Fixes: * **Model Configuration**: Improved model initialization flow for Ollama provider to ensure proper string-based model handling and compatibility with existing Upsonic model interfaces. Full Changelog: [v0.66.0...v0.66.1](https://github.com/Upsonic/Upsonic/compare/v0.66.0...v0.66.1) ### Pull Requests: * Model as string ollama: [@onuratakan](https://github.com/onuratakan) in [#463](https://github.com/Upsonic/Upsonic/pull/463) ## v0.66.0 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/v0.66.0) ## New Features: * Expression Language: Introduced Upsonic Expression Language (UEL) enabling declarative chain composition with pipe operators, runnables, and dynamic workflow construction for building sophisticated AI agent pipelines. * State Graph and Recursive Tool Handling for Streaming: Added recursive tool handling capabilities for streaming in Agent class and StateGraph logic. ## Improvements: * MCP Smoke Test Coverage: Added comprehensive smoke tests for Model Context Protocol (MCP) integration to ensure reliable MCP server connections and tool discovery functionality. ## Bug Fixes: * External Tool Execution: Fixed issues with external tool execution handling that prevented proper pausing and resumption of agent workflows when tools require external processing. * Logging and Memory Error Handling: Resolved logging inconsistencies and added robust error handling for memory operations to prevent framework crashes during memory storage and retrieval operations. * Documentation Links: Fixed broken links in README documentation to ensure accurate navigation and improve developer experience. Full Changelog address: [v0.65.1...v0.66.0](https://github.com/Upsonic/Upsonic/compare/v0.65.1...v0.66.0) ### Pull Requests: * Expression Language: [@DoganK01](https://github.com/DoganK01) in [#453](https://github.com/Upsonic/Upsonic/pull/453) * smoke test for mcp added: [@sxroads](https://github.com/sxroads) in [#454](https://github.com/Upsonic/Upsonic/pull/454) * docs: fix broken links in README: [@gokborayilmaz](https://github.com/gokborayilmaz) in [#456](https://github.com/Upsonic/Upsonic/pull/456) * feat: state graph, recursive tool handling for streaming logic: [@DoganK01](https://github.com/DoganK01) in [#455](https://github.com/Upsonic/Upsonic/pull/455) * External tool fix: [@DoganK01](https://github.com/DoganK01) in [#457](https://github.com/Upsonic/Upsonic/pull/457) * fix: logging fix, memory error handling adding: [@DoganK01](https://github.com/DoganK01) in [#458](https://github.com/Upsonic/Upsonic/pull/458) ## v0.65.1 [View releases on GitHub](https://github.com/Upsonic/Upsonic/releases/tag/v0.65.1) ## New Features: * Centralized Logging System: Introduced a unified logging configuration system that replaces ad-hoc logging instances across the framework, providing consistent logging behavior and centralized control. * Sentry Integration: Added comprehensive Sentry integration for telemetry and error tracking, enabling better monitoring and debugging of agent executions and pipeline operations. ## Improvements: * Improved Logging Configuration: Enhanced logging system with flexible module-level log control, multiple format options, and environment variable-based configuration for better developer experience. * Pipeline Tracing: Added systematic transaction and span tracking in pipeline manager for improved observability and debugging of agent execution flows. ## Bug Fixes: * Fixed Logging Issues: Resolved logging problems and inconsistencies across the framework by implementing a centralized logging system with proper error handling. Full Changelog: [v0.65.0...v0.65.1](https://github.com/Upsonic/Upsonic/compare/v0.65.0...v0.65.1) ### Pull Requests: * Redesigned Logging system: [@onuratakan](https://github.com/onuratakan) in [#452](https://github.com/Upsonic/Upsonic/pull/452) # Community Source: https://docs.upsonic.ai/community Join the Upsonic community, contribute, share ideas, and build together # Welcome to the Upsonic Community 💚 Upsonic is built by developers, for developers. Whether you're already using Upsonic in production or just getting started, **we'd love to have you involved**. Ask questions, share what you're building, and get help from the team and community. *** ## Contributing Upsonic is open source under the MIT License and we welcome contributions of all kinds: code, ideas, bug reports, and documentation improvements. You don't need to be an expert to contribute. If you've used Upsonic and found something that could be better, that's a great starting point. ### Areas We're Focused On We're actively building and improving these core areas. If any of them excite you, we'd love your help: Workspace sandboxing, filesystem and shell tools, and multi-step task execution. Ideas for new capabilities or improvements to existing ones are welcome. Policy-based content filtering for PII, compliance, and content moderation. New policy ideas, edge case fixes, and performance improvements are all valuable. Multi-engine OCR pipeline with PDF and image support. Engine integrations, accuracy improvements, and preprocessing enhancements are great ways to contribute. ### Ways to Contribute Found something broken? Open an issue on [GitHub](https://github.com/Upsonic/Upsonic/issues) with: * A clear description of the problem * Steps to reproduce it * Your environment (Python version, OS, Upsonic version) That's it. Short and specific is perfect. Have an idea that would make Upsonic better? We want to hear it. * Open a [GitHub issue](https://github.com/Upsonic/Upsonic/issues) with the **feature request** label * Or share it in our [Discord](https://discord.gg/7648R8JahY). Sometimes a quick conversation is the best way to start Ready to write some code? 1. Fork the [repository](https://github.com/Upsonic/Upsonic) 2. Create a branch for your change 3. Make your changes and add tests where applicable 4. Open a pull request with a clear description of what you did and why Clear docs help everyone. If you spot a typo, a missing example, or something that could be explained better, feel free to open a PR. *** ## Get in Touch Chat with the community and the Upsonic team in real time. Report bugs, request features, and track progress. Follow us for updates and announcements. Connect with us professionally. *** Upsonic is MIT licensed. Every contribution, big or small, makes a difference. Thank you for being part of this. 💚 # Accessing Agent Output Source: https://docs.upsonic.ai/concepts/agents/access_output Working with AgentRunOutput for complete execution results After running an agent, you can access the complete execution context via `AgentRunOutput`. This provides the final output, tool executions, usage statistics, and more. ## Using `return_output` Flag The simplest way to get the full `AgentRunOutput` is using `return_output=True`: ```python theme={null} from upsonic import Agent, Task # Create agent agent = Agent("anthropic/claude-sonnet-4-5") # Run with return_output=True to get full AgentRunOutput task = Task("What is 2 + 2?") run_output = agent.print_do(task, return_output=True) # Access the output print(run_output.output) # "4" print(run_output.status.value) # "completed" ``` ### Async Version ```python theme={null} import asyncio from upsonic import Agent, Task async def main(): agent = Agent("anthropic/claude-sonnet-4-5") task = Task("What is the capital of France?") # Get full output with return_output=True run_output = await agent.print_do_async(task, return_output=True) print(f"Output: {run_output.output}") print(f"Status: {run_output.status.value}") asyncio.run(main()) ``` ## Using `get_run_output()` Method Alternatively, access the last run's output via `agent.get_run_output()`: ```python theme={null} from upsonic import Agent, Task agent = Agent("anthropic/claude-sonnet-4-5") # Run normally (returns just the content) result = agent.print_do("What is 2 + 2?") print(result) # "4" # Access the full run output after execution run_output = agent.get_run_output() print(run_output.output) # "4" print(run_output.status.value) # "completed" ``` ## Key Properties | Property | Type | Description | | ------------------ | -------------------------------- | ------------------------------------------------------------------ | | `output` | `str \| bytes \| None` | Final agent output | | `status` | `RunStatus` | Run status: `running`, `completed`, `paused`, `cancelled`, `error` | | `usage` | `RunUsage \| None` | Token usage and cost statistics | | `tools` | `List[ToolExecution] \| None` | All tool executions during the run | | `messages` | `List[ModelMessage] \| None` | New messages from this run | | `chat_history` | `List[ModelMessage]` | Full conversation history | | `thinking_content` | `str \| None` | Reasoning content (for supported models) | | `images` | `List[BinaryContent] \| None` | Generated images | | `files` | `List[BinaryContent] \| None` | Generated files | | `step_results` | `List[StepResult]` | Execution step tracking | | `execution_stats` | `PipelineExecutionStats \| None` | Pipeline execution statistics | ## Status Checking ```python theme={null} from upsonic import Agent, Task agent = Agent("anthropic/claude-sonnet-4-5") run_output = agent.do(Task("Hello!"), return_output=True) # Check run status if run_output.is_complete: print("Run completed successfully") elif run_output.is_paused: print(f"Run paused: {run_output.pause_reason}") elif run_output.is_error: print(f"Run failed: {run_output.error_details}") elif run_output.is_cancelled: print("Run was cancelled") ``` ## Accessing Usage Statistics ```python theme={null} from upsonic import Agent, Task agent = Agent("anthropic/claude-sonnet-4-5") run_output = agent.do(Task("Explain AI briefly"), return_output=True) if run_output.usage: print(f"Input tokens: {run_output.usage.input_tokens}") print(f"Output tokens: {run_output.usage.output_tokens}") print(f"Total tokens: {run_output.usage.total_tokens}") print(f"Cost: ${run_output.usage.cost}") print(f"Duration: {run_output.usage.duration}s") print(f"Tool calls: {run_output.usage.tool_calls}") ``` ## Accessing Tool Executions ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def calculate(x: int, y: int) -> int: """Add two numbers.""" return x + y agent = Agent("anthropic/claude-sonnet-4-5", tools=[calculate]) run_output = agent.do(Task("Calculate 5 + 3"), return_output=True) if run_output.tools: for tool_exec in run_output.tools: print(f"Tool: {tool_exec.tool_name}") print(f"Args: {tool_exec.tool_args}") print(f"Result: {tool_exec.result}") ``` ## Accessing Messages ```python theme={null} from upsonic import Agent, Task agent = Agent("anthropic/claude-sonnet-4-5") run_output = agent.do(Task("Hello!"), return_output=True) # Get only new messages from this run new_messages = run_output.new_messages() print("\n--------------------------------\n") print(new_messages) # Get all messages all_messages = run_output.all_messages() print("\n--------------------------------\n") print(all_messages) # Get the last model response last_response = run_output.get_last_model_response() print("\n--------------------------------\n") print(last_response) ``` ## Serialization `AgentRunOutput` supports full serialization for persistence: ```python theme={null} from upsonic import Agent, Task from upsonic.run.agent.output import AgentRunOutput agent = Agent("anthropic/claude-sonnet-4-5") run_output = agent.do(Task("Hello!"), return_output=True) # Serialize to dict data = run_output.to_dict() # Serialize to JSON json_str = run_output.to_json() # Deserialize restored = AgentRunOutput.from_dict(data) print(restored.output) ``` ## Streaming with Output Access After streaming completes, access the final output: ```python theme={null} import asyncio from upsonic import Agent, Task async def main(): agent = Agent("anthropic/claude-sonnet-4-5") task = Task("Write a haiku") async for chunk in agent.astream(task): print(chunk, end='', flush=True) # Access complete output after streaming run_output = agent.get_run_output() print(f"\n\nFinal output: {run_output.output}") print(f"Status: {run_output.status.value}") asyncio.run(main()) ``` ## HITL (Human-in-the-Loop) Requirements For external tool execution: ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool(external_execution=True) def send_email(to: str, subject: str, body: str) -> str: """ Send an email to a recipient. This tool requires external execution - the actual email sending must be handled by an external process or service. Args: to: Email address of the recipient subject: Email subject line body: Email body content Returns: Confirmation message indicating email was sent """ # This function body won't execute - it requires external execution # The external executor will handle the actual email sending return f"Email sent to {to} with subject: {subject}" agent = Agent("anthropic/claude-sonnet-4-5", tools=[send_email]) run_output = agent.do(Task("Send an email to john@example.com with subject 'Hello' and body 'This is a test email'"), return_output=True) # Check for pending external tools if run_output.has_pending_external_tools(): print("External tools detected:") for req in run_output.active_requirements: if req.needs_external_execution: print(f" - Tool: {req.tool_execution.tool_name}") print(f" Arguments: {req.tool_execution.tool_args}") print(f" Tool Call ID: {req.tool_execution.tool_call_id}") confirm = input(f"Execute the tool yourself? {req.tool_execution.tool_args} (yes/no): ") if confirm == "yes": result = send_email(**req.tool_execution.tool_args) req.tool_execution.result = result else: req.tool_execution.result = "Operation cancelled by user" # Get tools awaiting external execution (from requirements) external_requirements = run_output.get_external_tool_requirements() print(f"\nExternal tool requirements: {len(external_requirements)}") # Also check tools directly (may be empty if stored in requirements) pending_tools = run_output.tools_awaiting_external_execution print(f"Tools awaiting execution (direct): {len(pending_tools)}") ``` # Adding Tools Source: https://docs.upsonic.ai/concepts/agents/adding-tools Managing tools for agents in the Upsonic framework Agents can use tools during initialization or add/remove them dynamically. ## During Initialization ```python theme={null} from upsonic import Agent from upsonic.tools import tool @tool def web_search(query: str) -> str: """Search the web for information.""" return f"Search results for: {query}" agent = Agent( model="anthropic/claude-sonnet-4-5", tools=[web_search] ) ``` ## Dynamic Tool Management ```python theme={null} from upsonic import Agent from upsonic.tools import tool @tool def calculator(a: float, b: float) -> float: """Add two numbers.""" return a + b # Create agent agent = Agent("anthropic/claude-sonnet-4-5") # Add tools dynamically agent.add_tools([calculator]) # Remove tools (by name or object) agent.remove_tools([calculator]) # Or: agent.remove_tools(["calculator"]) ``` ## Accessing Registered Tools Access registered tools via the `registered_agent_tools` attribute: ```python theme={null} from upsonic import Agent from upsonic.tools import tool @tool def calculator(a: float, b: float) -> float: """Add two numbers.""" return a + b agent = Agent("anthropic/claude-sonnet-4-5") agent.add_tools([calculator]) # Access registered tools print("\nRegistered tools:", agent.registered_agent_tools) # Dict mapping tool names to wrapped tools # Get tool definitions tool_defs = agent.get_tool_defs() # List[ToolDefinition] print("\nTool definitions:", tool_defs) agent.remove_tools([calculator]) # Access registered tools print("\nRegistered tools:", agent.registered_agent_tools) # Dict mapping tool names to wrapped tools # Get tool definitions tool_defs = agent.get_tool_defs() # List[ToolDefinition] print("\nTool definitions:", tool_defs) ``` # Adding a Memory Source: https://docs.upsonic.ai/concepts/agents/advanced/adding-a-memory Set up memory management for your agents with comprehensive context storage The Memory system in Upsonic provides comprehensive, configurable memory management for AI agents, enabling them to maintain context across conversations, build user profiles, and store session summaries. ## Memory System Overview The `Memory` class serves as a centralized module for managing different types of memory and respects the specific data formats and logic established in the original application design for handling chat history. ### Key Features * **Session Memory**: Full conversation history storage and retrieval * **Summary Memory**: Automatic conversation summarization * **User Analysis Memory**: Dynamic user profile building and trait analysis * **Flexible Storage**: Support for various storage backends (SQLite, etc.) * **Context Injection**: Automatic injection of relevant memory into system prompts ## Setting Up Memory with SQLite Here's how to set up memory with SQLite storage: ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage from upsonic.models.anthropic import AnthropicModel # Create storage backend storage = SqliteStorage(db_file="agent_memory.db") # Create memory system memory = Memory( storage=storage, session_id="banking_session_001", user_id="user_001", full_session_memory=True, summary_memory=True, user_analysis_memory=True, model=AnthropicModel(model_name="claude-sonnet-4-5") ) # Create agent with memory agent = Agent( model="anthropic/claude-sonnet-4-5", name="BankingAssistant", memory=memory, feed_tool_call_results=True ) task = Task("My name is Alice") result = agent.do(task) print(result) task2 = Task("What is my name?") result2 = agent.do(task2) print(result2) ``` ## Memory Configuration Options ### Basic Memory Setup ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage # Create storage backend storage = SqliteStorage(db_file="basic_memory.db") # Basic memory configuration memory = Memory( storage=storage, session_id="session_001", user_id="user_001" ) # Create agent with memory agent = Agent( model="anthropic/claude-sonnet-4-5", memory=memory ) # Test memory task = Task("Hello, my name is Bob") result = agent.do(task) print(result) ``` ### Full Memory Configuration ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage from upsonic.models.anthropic import AnthropicModel # Create storage and model storage = SqliteStorage(db_file="full_memory.db") model = AnthropicModel(model_name="claude-sonnet-4-5") # Full memory configuration with all options memory = Memory( storage=storage, session_id="advanced_session", user_id="user_001", full_session_memory=True, # Store complete conversation history summary_memory=True, # Generate conversation summaries user_analysis_memory=True, # Build user profiles and traits user_profile_schema=None, # Custom user profile schema dynamic_user_profile=False, # Use dynamic profile generation num_last_messages=None, # Limit conversation history model=model, # LLM for analysis tasks debug=False, # Enable debug logging feed_tool_call_results=False, # Include tool results in memory user_memory_mode='update' # 'update' or 'replace' user profiles ) # Create agent with full memory agent = Agent( model="anthropic/claude-sonnet-4-5", name="AdvancedMemoryAgent", memory=memory ) # Test conversation with memory task = Task("I prefer conservative investments and my goal is retirement savings") result = agent.do(task) print(result) ``` ### Memory Types Explained #### Full Session Memory Stores complete conversation history for context retrieval: ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage # Create storage storage = SqliteStorage(db_file="session_memory.db") # Memory with full session history memory = Memory( storage=storage, session_id="session_001", full_session_memory=True ) # Create agent agent = Agent(model="anthropic/claude-sonnet-4-5", memory=memory) # First message result1 = agent.do(Task("My favorite color is blue")) print(result1) # Second message - agent should remember the first result2 = agent.do(Task("What is my favorite color?")) print(result2) ``` #### Summary Memory Automatically generates and maintains conversation summaries: ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage from upsonic.models.anthropic import AnthropicModel # Create storage storage = SqliteStorage(db_file="summary_memory.db") # Memory with automatic summarization memory = Memory( storage=storage, session_id="session_001", summary_memory=True, model=AnthropicModel(model_name="claude-sonnet-4-5") ) # Create agent agent = Agent(model="anthropic/claude-sonnet-4-5", memory=memory) # Have a conversation that will be summarized task = Task("Tell me about the benefits of cloud computing") result = agent.do(task) print(result) ``` #### User Analysis Memory Builds and maintains user profiles based on interactions: ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage from upsonic.models.anthropic import AnthropicModel # Create storage storage = SqliteStorage(db_file="user_analysis_memory.db") # Memory with user profile analysis memory = Memory( storage=storage, session_id="session_001", user_id="user_001", user_analysis_memory=True, model=AnthropicModel(model_name="claude-sonnet-4-5") ) # Create agent agent = Agent(model="anthropic/claude-sonnet-4-5", memory=memory) # Share user preferences task = Task("I'm a software developer interested in AI and machine learning") result = agent.do(task) print(result) ``` ## Using Memory in Task Execution Once configured, memory automatically integrates with your agent: ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage from upsonic.models.anthropic import AnthropicModel # Setup storage and memory storage = SqliteStorage(db_file="task_execution_memory.db") memory = Memory( storage=storage, session_id="investment_session", user_id="investor_001", full_session_memory=True, user_analysis_memory=True, model=AnthropicModel(model_name="claude-sonnet-4-5") ) # Create agent with memory agent = Agent( model="anthropic/claude-sonnet-4-5", name="InvestmentAdvisor", memory=memory ) # Create a task - memory will automatically be used task = Task( description="Analyze the user's investment portfolio and provide recommendations based on their risk tolerance and previous conversations." ) # Execute with memory context result = agent.do(task) print(result) ``` The memory system will: 1. Inject relevant user profile information into the system prompt 2. Include conversation summaries for context 3. Provide full conversation history if needed 4. Update user profiles based on the interaction ## Memory Management Methods ### Accessing Memory Data ```python theme={null} import asyncio from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage from upsonic.models.anthropic import AnthropicModel async def main(): # Create storage and memory storage = SqliteStorage(db_file="access_memory.db") memory = Memory( storage=storage, session_id="session_001", user_id="user_001", full_session_memory=True, user_analysis_memory=True, summary_memory=True, model=AnthropicModel(model_name="claude-sonnet-4-5") ) # Create agent with memory agent = Agent(model="anthropic/claude-sonnet-4-5", memory=memory) # First, have a conversation to build memory task = Task("My name is John and I'm interested in technology stocks") result = agent.do(task) print("Agent response:", result) # Access session data via memory session = await agent.memory.get_session_async() if session: print("Session ID:", session.session_id) print("Messages count:", len(session.messages) if session.messages else 0) print("Session summary:", session.summary) # Access user memory via storage user_memory = storage.get_user_memory(user_id="user_001") if user_memory: print("User memory:", user_memory.user_memory) # Run the async function asyncio.run(main()) ``` ### Memory Configuration in Agent ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage # Create storage and memory storage = SqliteStorage(db_file="advisor_memory.db") memory = Memory( storage=storage, session_id="advisor_session", user_id="client_001", full_session_memory=True ) # Create agent with memory configuration agent = Agent( model="anthropic/claude-sonnet-4-5", name="FinancialAdvisor", memory=memory, feed_tool_call_results=True, # Include tool results in memory debug=True # Enable memory debug logging ) # Test the agent task = Task("What investment strategies do you recommend for a 30-year-old?") result = agent.do(task) print(result) ``` ## Advanced Memory Features ### Custom User Profile Schema ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage from upsonic.models.anthropic import AnthropicModel from pydantic import BaseModel, Field from typing import List # Define custom user profile schema class CustomUserTraits(BaseModel): risk_tolerance: str = Field(description="User's risk tolerance level") investment_goals: str = Field(description="User's investment objectives") preferred_assets: List[str] = Field(default=[], description="User's preferred asset classes") # Create storage and model storage = SqliteStorage(db_file="custom_profile_memory.db") model = AnthropicModel(model_name="claude-sonnet-4-5") # Create memory with custom profile schema memory = Memory( storage=storage, session_id="session_001", user_id="user_001", user_analysis_memory=True, user_profile_schema=CustomUserTraits, model=model ) # Create agent agent = Agent(model="anthropic/claude-sonnet-4-5", memory=memory) # Share investment preferences task = Task("I have a high risk tolerance and I'm interested in tech stocks and crypto") result = agent.do(task) print(result) ``` ### Dynamic User Profile Generation ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage from upsonic.models.anthropic import AnthropicModel # Create storage and model storage = SqliteStorage(db_file="dynamic_profile_memory.db") model = AnthropicModel(model_name="claude-sonnet-4-5") # Memory with dynamic profile generation memory = Memory( storage=storage, session_id="session_001", user_id="user_001", user_analysis_memory=True, dynamic_user_profile=True, # Automatically generate profile schema model=model ) # Create agent agent = Agent(model="anthropic/claude-sonnet-4-5", memory=memory) # The agent will dynamically build a profile based on the conversation task = Task("I'm a retired teacher looking for safe investments with steady income") result = agent.do(task) print(result) ``` ### Memory with Limited History ```python theme={null} from upsonic import Agent, Task from upsonic.storage import Memory, SqliteStorage # Create storage storage = SqliteStorage(db_file="limited_history_memory.db") # Memory with limited conversation history memory = Memory( storage=storage, session_id="session_001", full_session_memory=True, num_last_messages=10 # Keep only last 10 conversation turns ) # Create agent agent = Agent(model="anthropic/claude-sonnet-4-5", memory=memory) # Test limited history task = Task("Remember that my favorite number is 42") result = agent.do(task) print(result) ``` ## Storage Configuration Options The `SqliteStorage` class accepts the following parameters: ```python theme={null} from upsonic.storage import SqliteStorage # Full configuration example storage = SqliteStorage( db_file="agent_data.db", # Path to SQLite database file session_table="custom_sessions", # Custom session table name (optional) user_memory_table="custom_users", # Custom user memory table name (optional) id="storage_instance_1" # Unique storage instance ID (optional) ) ``` ## Best Practices 1. **Choose Appropriate Memory Types**: Enable only the memory types you need to optimize performance 2. **Set Session IDs**: Always provide meaningful session IDs for proper memory isolation 3. **User ID Management**: Use consistent user IDs for proper profile building 4. **Model Provider**: Provide a model provider for summary and analysis features 5. **Storage Backend**: Choose appropriate storage backend based on your deployment needs 6. **Memory Limits**: Use `num_last_messages` to prevent memory from growing too large 7. **Debug Mode**: Enable debug mode during development to understand memory behavior 8. **Tool Results**: Consider whether to include tool call results in memory based on your use case The Memory system provides a robust foundation for building conversational AI applications that can maintain context, learn from interactions, and provide personalized experiences. # Adding Reasoning Source: https://docs.upsonic.ai/concepts/agents/advanced/adding-reasoning Enable advanced reasoning for complex multi-tool analysis with step-by-step evaluation Reasoning capabilities extend thinking with **mandatory analysis after each tool execution**. This "Act-then-Analyze" pattern enables the agent to evaluate results and adapt its strategy dynamically, making it ideal for complex scenarios requiring iterative refinement. ## Thinking vs. Reasoning | Feature | Thinking | Reasoning | | -------------- | -------------------------------- | ------------------------------------- | | **Planning** | Creates execution plan | Creates execution plan | | **Execution** | Runs tools sequentially | Runs tools sequentially | | **Analysis** | Final synthesis only | Analyzes after EACH tool | | **Adaptation** | Follows original plan | Can revise plan mid-execution | | **Best For** | Straightforward multi-tool tasks | Complex analysis requiring evaluation | ## Enabling Reasoning Reasoning requires **both** thinking and reasoning tools to be enabled: ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def get_stock_price(symbol: str) -> str: """Get current stock price.""" return f"Current price of {symbol}: $185.50" @tool def get_analyst_ratings(symbol: str) -> str: """Get analyst ratings and recommendations.""" return f"Analyst consensus for {symbol}: Buy (78% recommend)" @tool def get_company_news(symbol: str) -> str: """Get recent company news.""" return f"Recent news for {symbol}: Strong Q4 earnings reported" # Enable reasoning for advanced analysis agent = Agent( model="anthropic/claude-sonnet-4-5", name="InvestmentAnalyst", tools=[get_stock_price, get_analyst_ratings, get_company_news], enable_thinking_tool=True, # Required for reasoning enable_reasoning_tool=True, # Enables act-then-analyze debug=True ) # Run the agent with reasoning capabilities task = Task("Should I invest in AAPL? Analyze the stock thoroughly.") result = agent.print_do(task) print(result) ``` **Warning**: `enable_reasoning_tool` requires `enable_thinking_tool` to be `True`. Setting reasoning without thinking will raise a `ValueError`. ## How Reasoning Works Reasoning follows an advanced "Act-then-Analyze" pattern: 1. **Strategic Planning**: Create initial execution plan 2. **Execute One Step**: Run the next tool in the plan 3. **Mandatory Analysis**: Evaluate the result and decide next action 4. **Dynamic Adaptation**: Continue, revise plan, or finalize answer 5. **Final Synthesis**: Comprehensive conclusion with all insights ``` Example Flow: 1. Agent receives: "Should I invest in AAPL?" 2. Plan: [get_stock_price, get_analyst_ratings, get_company_news] 3. Execute get_stock_price → Analyze: "Price is high, need more context" 4. Execute get_analyst_ratings → Analyze: "Analysts bullish, aligns with price" 5. Execute get_company_news → Analyze: "Strong earnings support the rating" 6. Synthesize: "AAPL shows positive indicators across price, analysts, and news" ``` ## Reasoning Configuration ### Agent-Level Reasoning ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_market_data(query: str) -> str: """Search for market data and trends.""" return f"Market data for {query}: Upward trend, 15% YoY growth" @tool def analyze_competitors(company: str) -> str: """Analyze competitive landscape.""" return f"Competitors of {company}: Strong market position, 35% market share" @tool def get_financial_metrics(symbol: str) -> str: """Get key financial metrics.""" return f"Financials for {symbol}: P/E 28, Revenue $394B, Profit margin 25%" # Enable reasoning for all tasks agent = Agent( model="anthropic/claude-sonnet-4-5", name="StrategicAnalyst", tools=[search_market_data, analyze_competitors, get_financial_metrics], enable_thinking_tool=True, enable_reasoning_tool=True ) # Execute a strategic analysis task task = Task("Analyze the competitive position and financials of Apple") result = agent.print_do(task) print(result) ``` ### Task-Level Reasoning ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_market_data(query: str) -> str: """Search for market data and trends.""" return f"Market data for {query}: Upward trend, 15% YoY growth" @tool def analyze_competitors(company: str) -> str: """Analyze competitive landscape.""" return f"Competitors of {company}: Strong market position, 35% market share" # Create agent without reasoning enabled at agent level agent = Agent( model="anthropic/claude-sonnet-4-5", name="MarketAnalyst", tools=[search_market_data, analyze_competitors] ) # Override agent settings for specific task - enable reasoning task = Task( description="Conduct a comprehensive competitive analysis of Apple", enable_thinking_tool=True, enable_reasoning_tool=True ) result = agent.print_do(task) print(result) ``` ### Mixed Configuration ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_market_data(query: str) -> str: """Search for market data and trends.""" return f"Market data for {query}: Upward trend, 15% YoY growth" @tool def analyze_competitors(company: str) -> str: """Analyze competitive landscape.""" return f"Competitors of {company}: Strong market position, 35% market share" @tool def get_financial_metrics(symbol: str) -> str: """Get key financial metrics.""" return f"Financials for {symbol}: P/E 28, Revenue $394B, Profit margin 25%" # Agent with reasoning enabled agent = Agent( model="anthropic/claude-sonnet-4-5", name="AnalysisAgent", tools=[search_market_data, analyze_competitors, get_financial_metrics], enable_thinking_tool=True, enable_reasoning_tool=True ) # Simple lookup - disable reasoning for speed simple_task = Task( description="Get the current market data for MSFT", enable_thinking_tool=False, enable_reasoning_tool=False # Single tool, no analysis needed ) result1 = agent.print_do(simple_task) print("Simple task result:", result1) # Complex analysis - use full reasoning complex_task = Task( description="Evaluate if GOOGL is a good investment considering market position, competitors, and financials", enable_thinking_tool=True, enable_reasoning_tool=True ) result2 = agent.print_do(complex_task) print("Complex task result:", result2) ``` ## When to Use Reasoning Reasoning is ideal for: * **Iterative Analysis**: When each step's result affects the next * **Strategic Decisions**: Complex scenarios requiring evaluation at each step * **Adaptive Workflows**: When the plan may need mid-course corrections * **Quality-Critical Tasks**: Where analyzing intermediate results improves accuracy ### Example: Investment Research with Analysis ```python theme={null} from upsonic import Agent, Task from upsonic.tools.common_tools.financial_tools import YFinanceTools # Create comprehensive financial tools finance_tools = YFinanceTools(enable_all=True) # Create agent with reasoning for thorough analysis agent = Agent( model="anthropic/claude-sonnet-4-5", name="InvestmentResearcher", tools=finance_tools.functions(), enable_thinking_tool=True, enable_reasoning_tool=True, debug=True ) # Complex multi-step analysis task task = Task( description=""" Conduct a thorough investment analysis of Tesla (TSLA): 1. Get current stock price and historical trends 2. Review analyst recommendations 3. Examine company fundamentals and financials 4. Provide a reasoned investment recommendation At each step, evaluate if the information changes your assessment. """ ) # Agent will execute tools with analysis after each step result = agent.print_do(task) print(result) ``` ### Example: Multi-Source Research ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_news(topic: str) -> str: """Search for recent news on a topic.""" return f"News on {topic}: 3 positive articles, 1 neutral, 0 negative" @tool def get_expert_opinions(topic: str) -> str: """Get expert opinions and analysis.""" return f"Experts on {topic}: Generally optimistic with caveats" @tool def analyze_social_sentiment(topic: str) -> str: """Analyze social media sentiment.""" return f"Social sentiment for {topic}: 72% positive, trending up" @tool def check_regulatory_status(topic: str) -> str: """Check regulatory environment.""" return f"Regulatory status for {topic}: Favorable, no pending actions" agent = Agent( model="anthropic/claude-sonnet-4-5", name="ResearchAnalyst", tools=[search_news, get_expert_opinions, analyze_social_sentiment, check_regulatory_status], enable_thinking_tool=True, enable_reasoning_tool=True, debug=True ) task = Task( description=""" Research the outlook for electric vehicles in 2025. Gather information from news, experts, social sentiment, and regulatory sources. After each source, assess how it changes the overall picture. Provide a balanced conclusion. """, enable_thinking_tool=True, enable_reasoning_tool=True ) result = agent.print_do(task) print(result) ``` ## Reasoning Output Structure When reasoning is enabled, the agent provides: 1. **Initial Strategy**: High-level approach to the problem 2. **Step-by-Step Analysis**: Evaluation after each tool execution 3. **Adaptation Decisions**: Whether to continue, revise, or conclude 4. **Evidence Chain**: How each tool's output influenced the conclusion 5. **Final Recommendation**: Synthesized answer with full reasoning ## Performance Considerations **Warning**: Reasoning consumes significantly more tokens than thinking alone due to the mandatory analysis after each tool call. Use reasoning when the analytical depth justifies the cost. ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_news(topic: str) -> str: """Search for recent news on a topic.""" return f"News on {topic}: 3 positive articles, 1 neutral, 0 negative" @tool def get_expert_opinions(topic: str) -> str: """Get expert opinions and analysis.""" return f"Experts on {topic}: Generally optimistic with caveats" # Monitor performance with debug mode agent = Agent( model="anthropic/claude-sonnet-4-5", name="Analyst", tools=[search_news, get_expert_opinions], enable_thinking_tool=True, enable_reasoning_tool=True, debug=True # Shows detailed reasoning steps ) # Run task to see performance metrics task = Task("What is the current outlook for renewable energy investments?") result = agent.print_do(task) print(result) ``` ## Best Practices 1. **Use for Complex Scenarios**: Enable reasoning when intermediate analysis adds value 2. **Requires Thinking**: Always enable `enable_thinking_tool` when using reasoning 3. **Multiple Tools**: Reasoning shines with 3+ tools where results interact 4. **Clear Instructions**: Tell the agent to "evaluate at each step" or "adjust based on findings" 5. **Monitor Costs**: Reasoning uses more tokens than thinking alone 6. **Debug First**: Use `debug=True` to understand the reasoning chain Reasoning provides the most sophisticated analytical capabilities for complex scenarios, making it essential for applications that require deep analysis and adaptive decision-making based on intermediate results. # Adding Thinking Source: https://docs.upsonic.ai/concepts/agents/advanced/adding-thinking Enable thinking capabilities for structured multi-tool orchestration Thinking capabilities enable your agent to **plan and orchestrate multiple tool calls** in a structured, step-by-step manner. This feature is essential when tasks require coordinating several tools to reach a comprehensive conclusion. ## Why Use Thinking? Thinking is most valuable when your agent has **multiple tools** and needs to: * Create an execution plan before acting * Call tools in a specific sequence * Synthesize results from multiple sources Without thinking, agents make ad-hoc tool calls. With thinking, agents strategically plan their approach first. ## Enabling Thinking To enable thinking capabilities, set `enable_thinking_tool=True` when creating your agent: ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool # Define tools the agent can use @tool def get_weather(city: str) -> str: """Get current weather for a city.""" return f"Weather in {city}: Sunny, 25°C" @tool def get_population(city: str) -> str: """Get population for a city.""" return f"Population of {city}: 2.1 million" # Enable thinking for multi-tool orchestration agent = Agent( model="anthropic/claude-sonnet-4-5", name="CityAnalyst", tools=[get_weather, get_population], enable_thinking_tool=True, debug=True ) # Create task and execute task = Task("Tell me about Paris's weather and population") result = agent.do(task) print(result) ``` ## How Thinking Works When thinking is enabled, the agent follows a structured "blueprint" approach: 1. **Strategic Planning**: The agent creates a complete, sequential plan of tool calls 2. **Orchestrated Execution**: Tools are executed step-by-step according to the plan 3. **Final Synthesis**: Results from all tools are combined into a comprehensive answer ``` Example Flow: 1. Agent receives: "Tell me about Paris's weather and population" 2. Agent creates plan: [get_weather("Paris"), get_population("Paris")] 3. Orchestrator executes: get_weather → get_population 4. Agent synthesizes: "Paris has sunny weather at 25°C and 2.1 million residents" ``` ### Thinking vs. Basic Mode | Feature | Basic Mode | Thinking Mode | | ------------- | --------------------- | ----------------------------------- | | **Planning** | Ad-hoc tool calls | Structured blueprint creation | | **Execution** | Direct tool execution | Orchestrated step-by-step execution | | **Best For** | Single tool tasks | Multi-tool coordination | ## Thinking Configuration ### Agent-Level Thinking ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_web(query: str) -> str: """Search the web for information.""" return f"Search results for: {query}" @tool def analyze_sentiment(text: str) -> str: """Analyze sentiment of text.""" return "Sentiment: Positive (85% confidence)" # Enable thinking for all tasks agent = Agent( model="anthropic/claude-sonnet-4-5", name="ResearchAgent", tools=[search_web, analyze_sentiment], enable_thinking_tool=True ) # Execute a research task task = Task("Search for information about AI trends and analyze the sentiment") result = agent.do(task) print(result) ``` ### Task-Level Thinking ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_web(query: str) -> str: """Search the web for information.""" return f"Search results for: {query} - Found 5 relevant articles" @tool def analyze_sentiment(text: str) -> str: """Analyze sentiment of text.""" return "Sentiment: Positive (85% confidence)" # Create agent without thinking enabled by default agent = Agent( model="anthropic/claude-sonnet-4-5", name="ResearchAgent", tools=[search_web, analyze_sentiment] ) # Override agent settings for specific task - enable thinking task = Task( description="Search for recent AI news and analyze the sentiment", enable_thinking_tool=True # Enable thinking for this specific task ) result = agent.do(task) print(result) ``` ### Mixed Configuration ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_web(query: str) -> str: """Search the web for information.""" return f"Search results for: {query}" @tool def analyze_sentiment(text: str) -> str: """Analyze sentiment of text.""" return "Sentiment: Positive (85% confidence)" # Agent with thinking enabled agent = Agent( model="anthropic/claude-sonnet-4-5", name="AnalysisAgent", tools=[search_web, analyze_sentiment], enable_thinking_tool=True ) # Simple task without thinking (single tool) simple_task = Task( description="What time is it in Tokyo?", enable_thinking_tool=False # Disable thinking for simple queries ) result1 = agent.do(simple_task) print("Simple result:", result1) # Complex task with thinking (multiple tools) complex_task = Task( description="Research the topic of electric vehicles and analyze public sentiment", enable_thinking_tool=True # Keep thinking for complex analysis ) result2 = agent.do(complex_task) print("Complex result:", result2) ``` ## When to Use Thinking Thinking is ideal for: * **Multi-source Research**: Gathering data from multiple tools and synthesizing * **Step-by-Step Analysis**: Tasks requiring sequential tool execution * **Complex Workflows**: When tool outputs feed into subsequent tool calls * **Data Aggregation**: Combining results from several sources ### Example: Financial Analysis with Multiple Tools ```python theme={null} from upsonic import Agent, Task from upsonic.tools.common_tools.financial_tools import YFinanceTools # Create financial tools finance_tools = YFinanceTools( stock_price=True, analyst_recommendations=True, company_news=True ) # Create agent with thinking for multi-step analysis agent = Agent( model="anthropic/claude-sonnet-4-5", name="FinancialAnalyst", tools=finance_tools.functions(), enable_thinking_tool=True, debug=True ) # Task requiring multiple tool calls task = Task( description=""" Analyze Apple (AAPL) stock: 1. Get the current stock price 2. Fetch analyst recommendations 3. Get recent company news 4. Provide a comprehensive investment summary """ ) # Agent will plan and execute: get_current_stock_price, get_analyst_recommendations, get_company_news # Then synthesize results into investment summary result = agent.do(task) print(result) ``` ### Example: Multi-City Research ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def get_weather(city: str) -> str: """Get current weather for a city.""" return f"Weather in {city}: Sunny, 25°C" @tool def get_population(city: str) -> str: """Get population statistics for a city.""" return f"Population of {city}: 2.1 million" @tool def get_attractions(city: str) -> str: """Get top attractions in a city.""" return f"Top attractions in {city}: Museums, Parks, Historic sites" agent = Agent( model="anthropic/claude-sonnet-4-5", name="TravelAdvisor", tools=[get_weather, get_population, get_attractions], enable_thinking_tool=True, debug=True ) task = Task( description="Give me a complete travel briefing for Paris including weather, population, and attractions", enable_thinking_tool=True ) # Agent creates plan: [get_weather, get_population, get_attractions] # Executes each tool, then synthesizes into travel briefing result = agent.do(task) print(result) ``` ## Thinking Output Structure When thinking is enabled, the agent provides: 1. **Reasoning**: Detailed strategy for approaching the task 2. **Execution Plan**: Step-by-step tool call sequence 3. **Criticism**: Self-assessment identifying potential issues 4. **Final Synthesis**: Comprehensive answer combining all tool results ## Performance Considerations **Important**: Thinking capabilities consume more tokens and processing time than basic mode due to the planning and synthesis steps. Use thinking when the orchestration value outweighs the cost. ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def get_weather(city: str) -> str: """Get current weather for a city.""" return f"Weather in {city}: Sunny, 25\u00b0C" @tool def get_population(city: str) -> str: """Get population for a city.""" return f"Population of {city}: 2.1 million" # Monitor performance with debug mode agent = Agent( model="anthropic/claude-sonnet-4-5", name="Analyst", tools=[get_weather, get_population], enable_thinking_tool=True, debug=True # Shows detailed execution metrics ) # Run task to see performance metrics task = Task("Compare the weather and populations of London and Paris") result = agent.do(task) print(result) ``` ## Best Practices 1. **Use for Multi-Tool Tasks**: Enable thinking when you have 2+ tools that need coordination 2. **Disable for Simple Queries**: Use basic mode for single-tool or no-tool tasks 3. **Provide Clear Instructions**: Help the agent plan by being specific about what you need 4. **Include Multiple Tools**: Thinking shines when there are tools to orchestrate 5. **Monitor with Debug Mode**: Use `debug=True` to understand the planning process Thinking provides a powerful way to handle complex scenarios that require multiple tools working together, making it essential for sophisticated multi-step analysis and research tasks. # Expose Agent as MCP Server Source: https://docs.upsonic.ai/concepts/agents/advanced/agent-as-mcp Turn any Agent into an MCP server so other agents or MCP clients can use it as a tool ## Overview Any Upsonic Agent can be exposed as an MCP (Model Context Protocol) server using `as_mcp()`. This lets other agents, tools, or MCP-compatible clients consume your agent over stdio, SSE, or Streamable HTTP. ## Creating an MCP Server from an Agent ```python theme={null} from upsonic import Agent agent = Agent( model="anthropic/claude-sonnet-4-5", name="Math Expert", role="Mathematics specialist", goal="Solve math problems accurately", ) agent.as_mcp().run() ``` Run this script and it starts an MCP server over stdio, exposing a `do` tool that accepts a task string and returns the agent's response. ## Using an Agent MCP Server from Another Agent ```python theme={null} from upsonic import Agent, Task from upsonic.tools.mcp import MCPHandler math_agent = MCPHandler(command="python math_agent_server.py") orchestrator = Agent( model="anthropic/claude-sonnet-4-5", name="Orchestrator", ) task = Task( description="Use the do tool to ask: What is 12 * 15?", tools=[math_agent], ) result = orchestrator.do(task) print(result) ``` The `MCPHandler` spawns the server as a subprocess, discovers the `do` tool, and makes it available to the orchestrator agent. ## Multiple Agent Servers as Tools Use `tool_name_prefix` to avoid name collisions when combining multiple agent servers: ```python theme={null} from upsonic import Agent, Task from upsonic.tools.mcp import MCPHandler math = MCPHandler(command="python math_server.py", tool_name_prefix="math") writer = MCPHandler(command="python writer_server.py", tool_name_prefix="writer") orchestrator = Agent( model="anthropic/claude-sonnet-4-5", name="Orchestrator", tools=[math, writer], ) result = orchestrator.do("Calculate 2^10 and write a sentence about the result.") ``` ## Customizing the Server `as_mcp()` returns a standard `FastMCP` server object. You can add extra tools before running: ```python theme={null} from upsonic import Agent agent = Agent(name="Assistant", model="anthropic/claude-sonnet-4-5") mcp = agent.as_mcp() @mcp.tool def get_current_date() -> str: """Get today's date.""" from datetime import date return str(date.today()) mcp.run() ``` ## How It Works 1. `as_mcp()` creates a `FastMCP` server named after the agent. 2. It registers a `do` tool whose description includes the agent's `role`, `goal`, and `instructions`. 3. When a client calls `do(task="...")`, the agent runs its full workflow internally (reasoning, tool use, memory) and returns the result as text. 4. `.run()` starts the server and blocks, waiting for client connections. For more information on MCP tools, see [MCPHandler](/concepts/tools/mcp-tools/mcp-handler). # Automatic Model Selection Source: https://docs.upsonic.ai/concepts/agents/advanced/automatic-model-selection Intelligent model recommendation system for optimal task performance Upsonic Agent Framework includes an intelligent model selection system that automatically recommends the most appropriate AI model for your specific task. This feature helps you optimize performance, cost, and speed by selecting the best model based on task requirements and constraints. Model selection system may recommend models from various providers (OpenAI, Anthropic, Google, etc.). **Ensure you have the required API keys configured** for the recommended model's provider before using it. If authentication is not set up for the recommended model, the agent will fail at runtime. Always verify you have the necessary credentials, or use the `preferred_provider` criteria to limit recommendations to providers you have configured. ## Overview Automatic model selection system analyzes your task description and selection criteria to recommend the most suitable model from a comprehensive registry of leading AI models including OpenAI, Anthropic, Google, Meta, DeepSeek, Qwen, Mistral, Cohere, and Grok models. ### Key Features * **Intelligent Analysis**: Automatically detects task requirements (reasoning, coding, math, vision, etc.) * **Dual Selection Methods**: Choose between fast rule-based or advanced LLM-based selection * **Comprehensive Model Registry**: Access to 15+ top-tier AI models with detailed metadata * **Flexible Criteria**: Specify constraints like cost, speed, context window, and capabilities * **Confidence Scoring**: Get confidence scores and alternative recommendations * **Seamless Integration**: Use recommendations directly with your agent ## Selection Methods The framework provides two approaches to model selection: ### Rule-Based Selection (Default) Fast, deterministic selection using keyword analysis and scoring algorithms. Ideal for most use cases. * ✅ **Fast**: No additional API calls required * ✅ **Cost-Effective**: No LLM usage for selection * ✅ **Predictable**: Consistent results based on rules * ❌ **Limited Context**: May miss nuanced requirements ### LLM-Based Selection (Advanced) Uses GPT-4o to analyze your task and intelligently select the best model. Recommended for complex or ambiguous tasks. * ✅ **Intelligent**: Deep understanding of task nuances * ✅ **Context-Aware**: Considers subtle requirements * ✅ **Adaptive**: Better handling of complex scenarios * ❌ **Slower**: Requires additional API call * ❌ **Cost**: Uses tokens for selection process ## Basic Usage ### Simple Recommendation Get a model recommendation for any task description: ```python theme={null} from upsonic import Agent agent = Agent() # Get recommendation (rule-based by default) recommendation = agent.recommend_model_for_task( "Write a complex sorting algorithm in Python with detailed explanations" ) print(f"Recommended: {recommendation.model_name}") print(f"Reason: {recommendation.reason}") print(f"Confidence: {recommendation.confidence_score:.2f}") print(f"Alternatives: {recommendation.alternative_models}") ``` ### Using the Recommendation Once you have a recommendation, use it to execute your task: ```python theme={null} from upsonic import Agent, Task agent = Agent() task = Task("Solve this complex mathematical proof: prove that sqrt(2) is irrational") # Get recommendation recommendation = agent.recommend_model_for_task(task) print(f"Recommended model: {recommendation.model_name}") # Use recommended model result = agent.do(task, model=recommendation.model_name) print(result) ``` ## Advanced Usage with Criteria ### Specifying Selection Criteria Use `SelectionCriteria` to define specific requirements and constraints: ```python theme={null} from upsonic import Agent, Task agent = Agent() # Define specific criteria criteria = { "requires_code_generation": True, "requires_math": True, "prioritize_quality": True, "max_cost_tier": 7, "min_context_window": 100000 } recommendation = agent.recommend_model_for_task( task="Implement a machine learning algorithm with mathematical proofs", criteria=criteria ) print(f"Selected: {recommendation.model_name}") print(f"Cost Tier: {recommendation.estimated_cost_tier}/10") print(f"Speed Tier: {recommendation.estimated_speed_tier}/10") # Use the recommended model task = Task("Implement a machine learning algorithm with mathematical proofs") result = agent.do(task, model=recommendation.model_name) print(result) ``` ### LLM-Based Selection Enable LLM-based selection for more intelligent recommendations: ```python theme={null} from upsonic import Agent, Task agent = Agent() # Use LLM for intelligent selection recommendation = agent.recommend_model_for_task( task="Analyze customer sentiment in multilingual support tickets", use_llm=True # Enable LLM-based selection ) print(f"Method: {recommendation.selection_method}") # "llm" print(f"Selected: {recommendation.model_name}") # Use the recommended model task = Task("Analyze customer sentiment in multilingual support tickets") result = agent.do(task, model=recommendation.model_name) print(result) ``` ### Async Model Recommendation For async workflows, use the async version: ```python theme={null} from upsonic import Agent, Task import asyncio async def main(): agent = Agent() recommendation = await agent.recommend_model_for_task_async( task="Process and analyze 500 page legal document", criteria={"requires_long_context": True, "min_context_window": 200000} ) print(f"For long documents: {recommendation.model_name}") # Use the recommended model task = Task("Summarize the key legal provisions in this document") result = agent.do(task, model=recommendation.model_name) print(result) asyncio.run(main()) ``` ## Selection Criteria Reference Configure model selection with these criteria parameters: | Criteria | Type | Default | Description | | --------------------------- | ------------ | ------- | -------------------------------------------------- | | requires\_reasoning | bool \| None | None | Task needs advanced reasoning capabilities | | requires\_code\_generation | bool \| None | None | Task involves writing or analyzing code | | requires\_math | bool \| None | None | Task requires mathematical problem solving | | requires\_creative\_writing | bool \| None | None | Task needs creative content generation | | requires\_vision | bool \| None | None | Task processes images or visual content | | requires\_audio | bool \| None | None | Task processes audio content | | requires\_long\_context | bool \| None | None | Task needs large context window | | prioritize\_speed | bool | False | Optimize for fast inference | | prioritize\_cost | bool | False | Optimize for cost-effectiveness | | prioritize\_quality | bool | False | Optimize for output quality | | max\_cost\_tier | int \| None | None | Maximum acceptable cost (1-10, where 10=expensive) | | min\_context\_window | int \| None | None | Minimum required context window in tokens | | preferred\_provider | str \| None | None | Preferred provider (e.g., "openai", "anthropic") | | require\_open\_source | bool | False | Require open-source model | | require\_production\_ready | bool | False | Require production-ready model | ## Model Recommendation Output The `ModelRecommendation` object provides comprehensive information: ```python theme={null} from upsonic import Agent, Task agent = Agent() recommendation = agent.recommend_model_for_task("Analyze financial data and create investment recommendations") # Access recommendation properties print(f"Model: {recommendation.model_name}") # e.g., "openai/gpt-4o" print(f"Reason: {recommendation.reason}") # Explanation for selection print(f"Confidence: {recommendation.confidence_score}") # 0.0 to 1.0 print(f"Alternatives: {recommendation.alternative_models}") # List of alternatives print(f"Cost Tier: {recommendation.estimated_cost_tier}") # 1-10 scale print(f"Speed Tier: {recommendation.estimated_speed_tier}") # 1-10 scale print(f"Method: {recommendation.selection_method}") # "rule_based" or "llm" # Use the recommendation task = Task("Analyze financial data and create investment recommendations") result = agent.do(task, model=recommendation.model_name) print(result) ``` ## Complete Example: Multi-Task Workflow Here's a comprehensive example showing model selection for different task types: ```python theme={null} from upsonic import Agent, Task # Create agent with default model selection settings agent = Agent( model="openai/gpt-4o-mini", # Default model debug=True ) # Task 1: Complex reasoning task reasoning_task = Task( "Analyze this complex business scenario and provide strategic recommendations..." ) reasoning_rec = agent.recommend_model_for_task( reasoning_task, criteria={ "requires_reasoning": True, "prioritize_quality": True } ) print(f"For reasoning: {reasoning_rec.model_name}") result1 = agent.do(reasoning_task, model=reasoning_rec.model_name) print(f"Result: {result1}") # Task 2: Cost-sensitive chatbot chatbot_task = Task("Generate a friendly greeting for our banking app users") chatbot_rec = agent.recommend_model_for_task( chatbot_task, criteria={ "prioritize_cost": True, "prioritize_speed": True, "max_cost_tier": 3 } ) print(f"For chatbot: {chatbot_rec.model_name}") result2 = agent.do(chatbot_task, model=chatbot_rec.model_name) print(f"Result: {result2}") # Task 3: Code generation code_task = Task("Write a high-performance sorting algorithm in Python") code_rec = agent.recommend_model_for_task( code_task, criteria={"requires_code_generation": True}, use_llm=True # Use LLM for better understanding ) print(f"For coding: {code_rec.model_name}") result3 = agent.do(code_task, model=code_rec.model_name) print(f"Result: {result3}") # Task 4: Long document analysis document_task = Task("Analyze and summarize this 300-page financial report") document_rec = agent.recommend_model_for_task( document_task, criteria={ "requires_long_context": True, "min_context_window": 200000, "requires_reasoning": True } ) print(f"For documents: {document_rec.model_name}") result4 = agent.do(document_task, model=document_rec.model_name) print(f"Result: {result4}") ``` ## Agent-Level Configuration Configure default selection behavior at agent initialization: ```python theme={null} from upsonic import Agent, Task # Agent with default selection criteria agent = Agent( model="anthropic/claude-sonnet-4-5", model_selection_criteria={ "prioritize_cost": True, "max_cost_tier": 5, "require_production_ready": True }, use_llm_for_selection=False # Use rule-based by default ) # Now recommendations use these defaults task_description = "Generate a summary of quarterly sales data" recommendation = agent.recommend_model_for_task(task_description) print(f"Recommended (with cost constraints): {recommendation.model_name}") # Execute with recommended model task = Task(task_description) result = agent.do(task, model=recommendation.model_name) print(result) ``` ## Best Practices 1. **Start with Rule-Based**: Use rule-based selection for most tasks - it's fast and effective 2. **Use LLM for Ambiguity**: Enable LLM-based selection for complex or ambiguous requirements 3. **Set Cost Limits**: Always specify `max_cost_tier` for production applications 4. **Check Alternatives**: Review alternative models for flexibility and fallback options 5. **Monitor Confidence**: Low confidence scores (`< 0.7`) suggest reviewing criteria or task description 6. **Context Windows**: For long documents, always check `min_context_window` requirements 7. **Production Safety**: Use `require_production_ready=True` for business-critical applications 8. **Provider Preferences**: Specify `preferred_provider` if you have existing infrastructure 9. **Test Recommendations**: Validate model performance with your specific use cases 10. **Cache Recommendations**: Store recommendations for similar tasks to avoid repeated selection ## Supported Models The framework includes comprehensive metadata for: * **OpenAI**: GPT-4o, GPT-4o-mini, O1-Pro, O1-mini * **Anthropic**: Claude 4 Opus, Claude 3.7 Sonnet, Claude 3.5 Haiku * **Google**: Gemini 2.5 Pro, Gemini 2.5 Flash * **Meta**: Llama 3.3 70B * **DeepSeek**: DeepSeek-Reasoner, DeepSeek-Chat * **Qwen**: Qwen 3 235B * **Mistral**: Mistral Large, Mistral Small * **Cohere**: Command R+ * **Grok**: Grok 4 Each model includes benchmark scores (MMLU, HumanEval, MATH, etc.), capabilities, cost/speed tiers, and use case recommendations. ## Common Use Cases ### Banking & Finance ```python theme={null} from upsonic import Agent, Task agent = Agent(model="openai/gpt-4o-mini") recommendation = agent.recommend_model_for_task( "Perform risk assessment and regulatory compliance analysis", criteria={ "requires_reasoning": True, "requires_math": True, "prioritize_quality": True, "require_production_ready": True } ) print(f"Recommended model for banking: {recommendation.model_name}") print(f"Reason: {recommendation.reason}") # Use the recommended model task = Task("Analyze the risk profile of a mortgage portfolio") result = agent.do(task, model=recommendation.model_name) print(result) ``` ### Customer Support ```python theme={null} from upsonic import Agent, Task agent = Agent(model="openai/gpt-4o-mini") recommendation = agent.recommend_model_for_task( "Handle customer inquiries in real-time chat", criteria={ "prioritize_speed": True, "prioritize_cost": True, "max_cost_tier": 3 } ) print(f"Recommended model for support: {recommendation.model_name}") print(f"Reason: {recommendation.reason}") # Use the recommended model task = Task("Respond to a customer asking about account balance") result = agent.do(task, model=recommendation.model_name) print(result) ``` ### Research & Development ```python theme={null} from upsonic import Agent, Task agent = Agent(model="openai/gpt-4o-mini") recommendation = agent.recommend_model_for_task( "Solve complex mathematical proofs", criteria={ "requires_reasoning": True, "requires_math": True, "prioritize_quality": True }, use_llm=True ) print(f"Recommended model for R&D: {recommendation.model_name}") print(f"Reason: {recommendation.reason}") # Use the recommended model task = Task("Prove that the sum of angles in a triangle equals 180 degrees") result = agent.do(task, model=recommendation.model_name) print(result) ``` The automatic model selection system empowers your AI agent framework to dynamically optimize model usage based on task requirements, delivering the best balance of performance, cost, and speed for your specific banking and fintech applications. # Company Knowledge Source: https://docs.upsonic.ai/concepts/agents/advanced/company-knowledge Branding and organizational context for your agents You can embed your organization's identity and objectives directly into the `Agent`. this ensures that the agent acts as a representative of your company, aligning with your brand voice and business goals. ## adding Company Context The `Agent` class accepts several parameters to define the company context: * `company_name`: The name of your organization. * `company_description`: A brief description of what your company does. * `company_objective`: The high-level goals or mission. * `company_url`: The main website URL. ```python theme={null} from upsonic import Agent, Task agent = Agent( model="anthropic/claude-sonnet-4-5", name="SupportBot", # Define Company Context company_name="TechFlow Solutions", company_description="A leading provider of cloud optimization tools.", company_objective="To help businesses reduce cloud costs by 30%.", company_url="https://techflow.example.com" ) # The agent now knows who it works for task = Task("Draft a welcome email to a new client.") result = agent.print_do(task) print(result) # Output will likely mention TechFlow Solutions and align with the cost-reduction mission. ``` ## How It Works This information is injected into the agent's system prompt. It provides a persistent background context ("grounding") that influences: 1. **Tone & Voice**: Professional and aligned with the company description. 2. **Goal Alignment**: Responses are steered towards the `company_objective`. 3. **Self-Identification**: The agent knows "who" it is representing. ## Best Practices * **Be Specific**: A clear `company_objective` helps the agent prioritize tasks. * **URL Context**: Providing `company_url` gives the agent a reference point if it needs to generate links or refer to the website (especially if using browsing tools). # Context Compression Source: https://docs.upsonic.ai/concepts/agents/advanced/context-compression Automatic context window management for long-running agent conversations The `Agent` class includes built-in context management that automatically handles context window overflow during long conversations. When enabled, the middleware monitors token usage and applies reduction strategies before the context exceeds the model's limit. ## How It Works Context management applies three strategies in order when the context window is exceeded: 1. **Prune old tool calls** — Removes old tool call/return pairs, keeping only the most recent ones. 2. **LLM summarization** — Summarizes older messages into condensed, structured messages via the LLM while keeping recent messages verbatim. 3. **Context full response** — If the context is still full after all strategies, returns a fixed message indicating the context limit has been reached. ## Usage ```python theme={null} from upsonic import Agent, Task agent = Agent( model="openai/gpt-4o-mini", context_management=True, # Enabled by default context_management_keep_recent=5, # Number of recent messages to always preserve context_management_model="anthropic/claude-sonnet-4-5" # Model for context managing ) # Task with potentially long context long_text = "..." * 100000 task = Task(f"Summarize this text: {long_text}") result = agent.do(task) print(result) ``` ## Parameters | Parameter | Type | Default | Description | | -------------------------------- | ------ | ------- | ---------------------------------------------------------------------------------------------- | | `context_management` | `bool` | `True` | Enable or disable automatic context management. | | `context_management_keep_recent` | `int` | `5` | Number of recent messages (and tool call events) to preserve during pruning and summarization. | Context management uses a 90% safety margin of the model's maximum context window. Token estimation relies on actual `usage` data from model responses when available, falling back to a character-based heuristic otherwise. # Reflection Source: https://docs.upsonic.ai/concepts/agents/advanced/reflection Enable self-critique and improvement for agent responses Reflection allows the agent to critique and improve its own responses before returning them. This "Self-Correction" pattern improves output quality by checking for errors, clarity, and completeness. ## Enabling Reflection To enable reflection, set `reflection=True` during agent initialization. ```python theme={null} from upsonic import Agent, Task # Create an agent with reflection enabled agent = Agent( model="anthropic/claude-sonnet-4-5", reflection=True ) task = Task("Write a python function to Fibonacci sequence with detailed docstrings.") # The agent will: # 1. Generate an initial response # 2. Critique the response (finding bugs or missing docs) # 3. Regenerate an improved response result = agent.print_do(task) print(result) ``` ## Configuring Reflection You can customize the reflection process using `ReflectionConfig`. ```python theme={null} from upsonic import Agent, Task from upsonic.reflection import ReflectionConfig # Custom reflection configuration config = ReflectionConfig( max_iterations=2, # Maximum improvement attempts acceptance_threshold=0.9 # Minimum score to accept response ) agent = Agent( model="anthropic/claude-sonnet-4-5", reflection=True, reflection_config=config, debug=True # useful to see the reflection steps ) task = Task("Optimize this database query...") result = agent.do(task) print(result) ``` ## When to Use Reflection? * **Coding Tasks**: To catch bugs and improve code quality. * **Complex Reasoning**: To verify logic and assumptions. * **Creative Writing**: To refine style and tone. Reflection increases the time and token usage for each task as it involves additional model calls for critique and revision. # Reliability & Retries Source: https://docs.upsonic.ai/concepts/agents/advanced/reliability-and-retries Configure error handling and retry logic for robust agents Agents operating in production need to handle failures gracefully. The `Agent` class provides built-in mechanisms for retrying failed operations and controlling error propagation. ## Retry Configuration You can control how many times an agent attempts to execute a task before failing. * `retry`: The number of *additional* attempts after the first failure. * `mode`: How to handle the final failure (`"raise"` or `"return_false"`). ### Basic Retry Logic ```python theme={null} from upsonic import Agent, Task agent = Agent( model="anthropic/claude-sonnet-4-5", retry=3, # Will try up to 4 times total (1 initial + 3 retries) mode="raise" # Raise the exception if all retries fail ) task = Task("Perform a potentially flaky API operation") try: result = agent.do(task) print(result) except Exception as e: print(f"Task failed after retries: {e}") ``` ### Safe Mode (Return False) If you prefer the agent to return `False` instead of crashing your application on failure: ```python theme={null} agent = Agent( model="anthropic/claude-sonnet-4-5", retry=2, mode="return_false" # Return False instead of raising Exception ) result = agent.do("Some complex task") if result is False: print("Agent failed to complete the task.") else: print(f"Success: {result}") ``` ## Best Practices * **Network Instability**: Set `retry >= 2` for agents using web search or external APIs. * **Production Systems**: Use `mode="raise"` inside a `try/catch` block to log specific errors while keeping the application running. # Workspace Configuration Source: https://docs.upsonic.ai/concepts/agents/advanced/workspace Configure agents with workspace folders containing agent configuration files The Workspace feature allows you to configure your agent using an `Agents.md` file stored in a designated folder. When a workspace is set, the agent reads the configuration file and includes it in the system prompt, and can generate a dynamic greeting message at the start of each session. ## Overview When you set a `workspace` path on an Agent: 1. **Configuration Loading**: The agent reads the `Agents.md` file from the workspace folder and includes it in the system prompt 2. **Session Greeting**: You can call `execute_workspace_greeting()` to generate a personalized greeting based on the configuration ## Example ```python theme={null} from upsonic import Agent, Task # Create an agent with workspace agent = Agent( "anthropic/claude-sonnet-4-5", workspace="/path/to/my_agent_folder", session_id="user_session_001" ) # Execute the workspace greeting (optional, for new sessions) greeting = agent.execute_workspace_greeting() print(greeting) # Run tasks - the Agents.md content is included in the system prompt task = Task("What can you help me with?") result = agent.do(task) print(result) ``` ## The AGENTS.md File Create an `AGENTS.md` file in your workspace folder to define your agent's behavior. We provide a ready-to-use template with memory management, safety rules, group chat guidelines, and more. Get the full AGENTS.md template you can copy and customize for your workspace. The content of this file is automatically injected into the agent's system prompt wrapped in `` tags. ## Integration with Interfaces When using Upsonic [interfaces](/concepts/interfaces/Overview) (Telegram, Slack, WhatsApp), the workspace greeting is automatically called when a user resets their session with the `/reset` command. The greeting response is sent to the user, providing a fresh start with a personalized introduction. # Attributes Source: https://docs.upsonic.ai/concepts/agents/attributes Configuration options for the Agent system ## Attributes The Agent system is configured through the `Agent` class, which provides the following attributes: | Attribute | Type | Default | Description | | ---------------------------- | ------------------------------------------- | ----------------- | ------------------------------------------------------------------- | | `model` | str \| Model | `"openai/gpt-4o"` | Model identifier or Model instance | | `model_name` | str | (from `model`) | Original model identifier string (set from `model` parameter) | | `name` | str \| None | `None` | Agent name for identification | | `memory` | Memory \| None | `None` | Memory instance for conversation history | | `db` | DatabaseBase \| None | `None` | Database instance (overrides memory if provided) | | `session_id` | str \| None | `None` | Session identifier for conversation tracking | | `user_id` | str \| None | `None` | User identifier for multi-user scenarios | | `debug` | bool | `False` | Enable debug logging | | `debug_level` | int | `1` | Debug level (1 = standard, 2 = detailed). Only used when debug=True | | `company_url` | str \| None | `None` | Company URL for context | | `company_objective` | str \| None | `None` | Company objective for context | | `company_description` | str \| None | `None` | Company description for context | | `company_name` | str \| None | `None` | Company name for context | | `system_prompt` | str \| None | `None` | Custom system prompt | | `reflection` | bool | `False` | Enable reflection capabilities | | `compression_strategy` | Literal\["none", "simple", "llmlingua"] | `"none"` | Context compression method: 'none', 'simple', 'llmlingua' | | `compression_settings` | Dict\[str, Any] \| None | `None` | Settings for compression strategy | | `reliability_layer` | Any \| None | `None` | Reliability layer for robustness | | `agent_id_` | str \| None | `None` | Unique identifier for the agent instance | | `canvas` | Canvas \| None | `None` | Canvas instance for visual interactions | | `retry` | int | `1` | Number of retry attempts | | `mode` | RetryMode | `"raise"` | Retry mode behavior: 'raise' or 'return\_false' | | `role` | str \| None | `None` | Agent role | | `goal` | str \| None | `None` | Agent goal | | `instructions` | str \| None | `None` | Specific instructions | | `education` | str \| None | `None` | Agent education background | | `work_experience` | str \| None | `None` | Agent work experience | | `feed_tool_call_results` | bool \| None | `None` | Include tool results in memory | | `show_tool_calls` | bool | `True` | Display tool calls | | `tool_call_limit` | int | `5` | Maximum tool calls per execution | | `enable_thinking_tool` | bool | `False` | Enable orchestrated thinking | | `enable_reasoning_tool` | bool | `False` | Enable reasoning capabilities | | `tools` | List\[Any] \| None | `None` | Agent-level tools (can also be added via `add_tools()`) | | `user_policy` | Policy \| List\[Policy] \| None | `None` | User input safety policy | | `agent_policy` | Policy \| List\[Policy] \| None | `None` | Agent output safety policy | | `tool_policy_pre` | Policy \| List\[Policy] \| None | `None` | Tool safety policy for pre-execution validation | | `tool_policy_post` | Policy \| List\[Policy] \| None | `None` | Tool safety policy for post-execution validation | | `user_policy_feedback` | bool | `False` | Enable feedback loop for user policy violations | | `agent_policy_feedback` | bool | `False` | Enable feedback loop for agent policy violations | | `user_policy_feedback_loop` | int | `1` | Maximum retry count for user policy feedback | | `agent_policy_feedback_loop` | int | `1` | Maximum retry count for agent policy feedback | | `settings` | ModelSettings \| None | `None` | Model-specific settings | | `profile` | ModelProfile \| None | `None` | Model profile configuration | | `reflection_config` | ReflectionConfig \| None | `None` | Configuration for reflection | | `model_selection_criteria` | Dict\[str, Any] \| None | `None` | Default criteria for recommend\_model\_for\_task() | | `use_llm_for_selection` | bool | `False` | Use LLM in recommend\_model\_for\_task() | | `reasoning_effort` | Literal\["low", "medium", "high"] \| None | `None` | Reasoning effort: 'low', 'medium', 'high' (OpenAI) | | `reasoning_summary` | Literal\["concise", "detailed"] \| None | `None` | Reasoning summary: 'concise', 'detailed' (OpenAI) | | `thinking_enabled` | bool \| None | `None` | Enable thinking (Anthropic/Google) | | `thinking_budget` | int \| None | `None` | Token budget for thinking | | `thinking_include_thoughts` | bool \| None | `None` | Include thoughts in output (Google) | | `reasoning_format` | Literal\["hidden", "raw", "parsed"] \| None | `None` | Reasoning format: 'hidden', 'raw', 'parsed' (Groq) | | `culture_manager` | CultureManager \| None | `None` | Culture manager instance for cultural knowledge (experimental) | | `add_culture_to_context` | bool | `False` | Add cultural knowledge to context (experimental) | | `update_cultural_knowledge` | bool | `False` | Update cultural knowledge based on interactions (experimental) | | `enable_agentic_culture` | bool | `False` | Enable agentic culture capabilities (experimental) | | `metadata` | Dict\[str, Any] \| None | `None` | Agent metadata (passed to prompt) | ## Properties The Agent class provides the following read-only properties: | Property | Type | Description | | ------------ | ----------- | ------------------------------------------------------------------------ | | `agent_id` | str | Unique agent identifier (auto-generated if not provided via `agent_id_`) | | `session_id` | str \| None | Session identifier (from override, memory, or db) | | `user_id` | str \| None | User identifier (from override, memory, or db) | ## Configuration Example ```python theme={null} from upsonic import Agent, Task from upsonic.storage.providers.sqlite import SqliteStorage from upsonic.storage import Memory # Create storage and memory storage = SqliteStorage( db_file="agent_memory.db", agent_sessions_table_name="sessions" ) memory = Memory( storage=storage, session_id="session_001", user_id="user_001", full_session_memory=True, summary_memory=True, model="openai/gpt-4o-mini" ) # Create agent with configuration agent = Agent( model="anthropic/claude-sonnet-4-6", name="Assistant", memory=memory, debug=True, role="AI Assistant", goal="Help users with their questions", show_tool_calls=True, tool_call_limit=5 ) # Execute a task task = Task("Hello! What can you help me with?") result = agent.do(task) print(result) ``` # Clanker Source: https://docs.upsonic.ai/concepts/agents/clanker Yeah, we actually did this. You know what a Clanker is. If you don't, go open TikTok for 5 minutes and come back. We saw the meme. We liked it. We shipped it. That's the whole story. `Clanker` is `Agent`. Same class. Same everything. Just a better name tbh. ## Use It ```python theme={null} from upsonic import Clanker, Task clanker = Clanker("openai/gpt-4o", name="My First Clanker") task = Task("Tell me a joke about robots.") result = clanker.do(task) ``` Congrats, you just built a Clanker. ## It Does Everything Agent Does Because it **is** Agent. Memory, tools, safety, streaming — all of it. Just vibes. ```python theme={null} from upsonic import Clanker, Task from upsonic.storage.memory import Memory from upsonic.storage.in_memory import InMemoryStorage memory = Memory(storage=InMemoryStorage()) clanker = Clanker( "anthropic/claude-sonnet-4-5", name="Enterprise Clanker", memory=memory, company_name="Acme Corp", company_objective="World domination through superior AI agents", ) task = Task("Draft a strategic plan for Q3.") result = clanker.print_do(task) ``` `Agent` for the boardroom. `Clanker` for the real ones. ## Source Code ```python theme={null} Clanker = Agent ``` One line. They cooked, we shipped. # Basic Agent Example Source: https://docs.upsonic.ai/concepts/agents/creating-an-agent Learn how to build Agents with Upsonic To build effective agents, start simple -- just a model, tools, and instructions. Once that works, layer in more functionality as needed. It's also best to begin with well-defined tasks like report generation, data extraction, classification, summarization, knowledge search, and document processing. These early wins help you identify what works, validate user needs, and set the stage for advanced systems. Here's the simplest possible report generation agent: ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool @tool def search_web(query: str) -> str: """Search the web for information about a topic.""" # Simulated web search - replace with actual implementation return f"Search results for '{query}': Found relevant information about the topic." agent = Agent( model="anthropic/claude-sonnet-4-5", instructions="Write a report on the topic. Output only the report.", tools=[search_web] # Tools can be added during initialization ) task = Task(description="Trending startups and products.") agent.print_do(task) ``` ## Setting a System Prompt You can customize your agent's behavior by providing a `system_prompt` or `instructions` parameter. The `system_prompt` gives you full control over the system message sent to the model, while `instructions` provides high-level guidance that gets incorporated into the agent's default prompt. ### Using instructions (Recommended for most cases) The `instructions` parameter is the simplest way to guide your agent's behavior: ```python theme={null} from upsonic import Agent agent = Agent( model="anthropic/claude-sonnet-4-5", instructions="You are a helpful assistant that specializes in Python programming. Be concise and provide code examples when relevant." ) ``` ### Using system\_prompt (Full control) For complete control over the system message, use `system_prompt`: ```python theme={null} from upsonic import Agent agent = Agent( model="anthropic/claude-sonnet-4-5", system_prompt="""You are an expert financial analyst. Your responses should: - Be data-driven and analytical - Include relevant metrics when available - Maintain a professional tone - Cite sources when making claims""" ) ``` ### Combining with Agent Identity You can also define your agent's identity using `role`, `goal`, and other attributes: ```python theme={null} from upsonic import Agent agent = Agent( model="anthropic/claude-sonnet-4-5", name="DataBot", role="Data Analyst", goal="Help users understand and visualize their data", instructions="Always ask clarifying questions before analyzing data. Provide visualizations when possible.", education="PhD in Statistics", work_experience="10 years of experience in data science and analytics" ) ``` ## Run your Agent When running your agent, use the `Agent.print_do()` method to print the response in the terminal. This is only for development purposes and not recommended for production use. In production, use the `Agent.do()` or `Agent.do_async()` methods. For example: ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool import asyncio @tool def search_web(query: str) -> str: """Search the web for information about a topic.""" # Simulated web search - replace with actual implementation return f"Search results for '{query}': Found relevant information about the topic." async def main(): agent = Agent( model="anthropic/claude-sonnet-4-5", instructions="Write a report on the topic. Output only the report.", tools=[search_web] # Tools can be added during initialization ) # You can also add tools after initialization # agent.add_tools([another_tool]) # do() and do_async() methods accept both Task objects and strings task = Task(description="Trending startups and products.") #result = agent.do(task) # Or: result = agent.do("Trending startups and products.") # Print the response #print(result) ################ STREAM RESPONSE ################# async for text_chunk in agent.astream(task): print(text_chunk, end='', flush=True) print() # New line after streaming if __name__ == "__main__": asyncio.run(main()) ``` Next, continue building your agent by adding functionality as needed. Common questions: * **How do I run my agent?** -> See the [running agents](/concepts/agents/running-agents) documentation. * **How do I manage sessions?** -> See the [memory](/concepts/memory/overview) documentation. * **How do I manage input and capture output?** -> See the [running agents](/concepts/agents/running-agents) documentation. * **How do I add tools?** -> See the [tools](/concepts/tools/overview) documentation. * **How do I give the agent context?** -> See the [agent attributes](/concepts/agents/attributes) documentation. * **How do I add knowledge?** -> See the [knowledge base](/concepts/knowledge-base) documentation. * **How do I handle images, audio, video, and files?** -> See the [OCR](/concepts/ocr/overview) documentation. * **How do I add guardrails?** -> See the [safety engine](/concepts/safety-engine/overview) documentation. * **How do I cache model responses during development?** -> See the [task attributes](/concepts/tasks/attributes) documentation for cache configuration. ## Developer Resources * View the [Agent reference](/reference/agent/agent) * View the [Agent overview](/concepts/agents/overview) # Debugging Agents Source: https://docs.upsonic.ai/concepts/agents/debugging-agents Debug and troubleshoot agent execution Debug agents by enabling debug mode to see detailed execution information including tool calls, context processing, and model interactions. ## Enable Debug Mode The simplest way to debug is enabling the `debug` flag when running a task. ```python theme={null} from upsonic import Agent, Task # Create agent and task agent = Agent("anthropic/claude-sonnet-4-5") task = Task("Calculate 25 * 4 and explain the steps") # Execute with debug mode result = agent.do(task, debug=True) print(result) ``` When debug mode is enabled, you'll see detailed logs including: * Pipeline step execution * Tool call information * Context management * Model request/response details * Cache hits/misses * Safety policy checks ## Debug Agent Configuration You can also enable debug mode at the agent level for persistent debugging across all tasks. ```python theme={null} from upsonic import Agent, Task from upsonic.tools import tool # Create a custom tool @tool def multiply(a: int, b: int) -> int: """Multiply two numbers.""" return a * b # Create agent with debug enabled agent = Agent( model="anthropic/claude-sonnet-4-5", debug=True, show_tool_calls=True ) # Execute task - debug info shown automatically task = Task( description="Use the multiply tool to calculate 15 * 8", tools=[multiply] ) result = agent.do(task) print(f"Result: {result}") ``` With agent-level debug mode, every execution provides detailed insights into the agent's decision-making process and tool usage. # Image Generation Source: https://docs.upsonic.ai/concepts/agents/image-generation-agent Generating and managing images with Agent class `Agent` can generate images using the `ImageGenerationTool` and save them using image utility functions. ## Basic Image Generation ```python theme={null} from upsonic import Agent, Task from upsonic.tools.builtin_tools import ImageGenerationTool from upsonic.utils.image import save_image_to_folder # Create agent with image generation capability agent = Agent( model="openai-responses/gpt-4o", ) # Create task with ImageGenerationTool task = Task( description="Generate a beautiful landscape image of a sunset over mountains.", tools=[ImageGenerationTool()] ) # Execute task - result will be image bytes result = agent.print_do(task) # Save the generated image (folder created automatically) saved_path = save_image_to_folder( image_data=result, folder_path="my_images", filename="sunset.png", is_base64=False # Agent returns bytes directly ) print(f"Image saved to: {saved_path}") ``` ## Opening Generated Images ```python theme={null} from upsonic.utils.image import open_image_file, open_images_from_folder # Open a single image open_image_file("my_images/sunset.png") # Open all images in a folder (limit to 3) opened_files = open_images_from_folder("my_images", limit=3) ``` ## Listing Images in Folder ```python theme={null} from upsonic.utils.image import list_images_in_folder # List all images in folder (sorted by newest first) images = list_images_in_folder("my_images") for img_path in images: print(f"Found: {img_path}") ``` ## Complete Workflow ```python theme={null} from upsonic import Agent, Task from upsonic.tools.builtin_tools import ImageGenerationTool from upsonic.utils.image import save_image_to_folder, open_image_file # Setup agent = Agent("openai-responses/gpt-4o") # Generate image task = Task( description="Generate an image of a futuristic city at night.", tools=[ImageGenerationTool()] ) result = agent.print_do(task) # Save and open (folder created automatically) if isinstance(result, bytes): saved_path = save_image_to_folder( image_data=result, folder_path="generated_images", filename="city.png", is_base64=False ) open_image_file(saved_path) ``` # Agent Metrics Source: https://docs.upsonic.ai/concepts/agents/metrics Track tokens, cost, requests, tool calls, and timing across every model call this agent participates in. ## Overview Every agent exposes a single read-only **`agent.usage`** property. It returns an `AggregatedUsage` view derived from the [centralized usage registry](/concepts/usage-registry) on each access, scoped to this agent's `agent_usage_id`. Sub-pipeline model calls — memory summarization, reliability validator/editor, culture, policy, and sub-agents invoked as tools — automatically inherit the agent's scope and roll into `agent.usage` without any manual propagation. When printing is enabled (`print_do` / `print_do_async`), an **Agent Metrics** panel is displayed after each task so you can see the updated totals. ## Accessing Agent Metrics Read **`agent.usage`** on any `Agent` instance. It always returns an `AggregatedUsage` — zero-valued before the first run, populated thereafter. ### Token Metrics | Property | Type | Description | | -------------------- | ----- | ---------------------------------------------- | | `input_tokens` | `int` | Total prompt/input tokens across all runs | | `output_tokens` | `int` | Total completion/output tokens across all runs | | `total_tokens` | `int` | Sum of `input_tokens + output_tokens` | | `cache_read_tokens` | `int` | Tokens read from prompt cache | | `cache_write_tokens` | `int` | Tokens written to prompt cache | | `reasoning_tokens` | `int` | Reasoning (chain-of-thought) tokens | ### Request & Tool Metrics | Property | Type | Description | | ------------ | ----- | ------------------------------------- | | `requests` | `int` | Total number of LLM API requests made | | `tool_calls` | `int` | Total number of tool calls executed | ### Timing Metrics | Property | Type | Description | | ------------------------ | --------------- | --------------------------------------------------------------- | | `duration` | `float` | Sum of per-call durations across contributing entries (seconds) | | `model_execution_time` | `float` | Total time spent inside LLM API calls (seconds) | | `tool_execution_time` | `float` | Total time spent executing tools (seconds) | | `upsonic_execution_time` | `float` | Framework overhead = `duration − model − tool` (seconds) | | `time_to_first_token` | `float \| None` | Earliest TTFT across contributing entries | ### Cost Metrics | Property | Type | Description | | -------- | --------------- | ---------------------------------------------------------------------------------------------------------- | | `cost` | `float \| None` | Sum of `cost_usd` across contributing entries. `None` if no entry was priced; `0.0` means priced and free. | ### Aggregation Metadata | Property | Type | Description | | ------------- | ----------- | ---------------------------------------------------------------- | | `entry_count` | `int` | Number of underlying `UsageEntry` rows contributing to this view | | `models` | `list[str]` | Distinct model identifiers that contributed (first-seen order) | ## Example ```python theme={null} from upsonic import Agent, Task agent = Agent("anthropic/claude-sonnet-4-5", print=True) agent.print_do(Task("What is 2 + 2? Reply with one number.")) agent.print_do(Task("What is 3 + 3? Reply with one number.")) u = agent.usage print(f"Requests: {u.requests}") print(f"Input tokens: {u.input_tokens}") print(f"Output tokens: {u.output_tokens}") print(f"Tool calls: {u.tool_calls}") if u.cost is not None: print(f"Cost: ${u.cost:.4f}") print(f"Model time: {u.model_execution_time:.2f}s") print(f"Tool time: {u.tool_execution_time:.2f}s") print(f"Framework time: {u.upsonic_execution_time:.2f}s") print(f"Models used: {u.models}") ``` ## Printed Panel When you use `print_do` or `print_do_async`, the **Agent Metrics** panel displays after each task: ``` ╭──────────────────── Agent Metrics ────────────────────╮ │ Agent: MyAgent │ │ │ │ Total Requests: 4 │ │ Total Input Tokens: 1,552 │ │ Total Output Tokens: 915 │ │ Total Tool Calls: 2 │ │ Total Estimated Cost: $0.0008 │ │ Total Duration: 21.55 seconds │ │ Model Execution Time: 18.17 seconds │ │ Tool Execution Time: 1.00 seconds │ │ Framework Overhead: 2.38 seconds │ ╰───────────────────────────────────────────────────────╯ ``` ## Scope & Propagation * **Across tasks** — Every call to `do` / `print_do` / `do_async` / `print_do_async` records entries against the agent's scope. Reading `agent.usage` re-aggregates them, so the figures always reflect the latest state. * **Sub-pipeline rollup** — Memory summarization, reliability validator/editor, culture, policy, and sub-agent calls inherit the parent's scope via context variables and roll into `agent.usage` automatically. * **Retry idempotency** — The registry is keyed by `entry_id`. Retried requests replace their prior entry instead of double-counting. * **Independent agents** — Each `Agent` instance has its own `agent_usage_id`. Two different agents never share usage. * **JSON snapshot** — Call `agent.usage.to_dict()` for a flat dict suitable for logs and dashboards. ## Legacy Migration Legacy surfaces have been removed in favour of `agent.usage`: | Legacy | Replacement | | ------------------------------------------------------- | -------------------------------------- | | `agent.cost` (dict) | `agent.usage.to_dict()` | | `AgentUsage.incr()` / accumulator fields | (registry-derived; no mutation needed) | | `agent._finalize_agent_usage`, retry baseline machinery | (registry is idempotent) | ## Related Documentation * [Usage Registry](/concepts/usage-registry) — Architecture, scope tags, persistence * [Task Metrics](/concepts/tasks/metrics) — Per-task scoped view * [Chat Metrics](/concepts/chat/metrics) — Per-session scoped view * [Team Metrics](/concepts/team/metrics) — Per-team scoped view # Agents Source: https://docs.upsonic.ai/concepts/agents/overview Let's analyze how Upsonic Agents works Concepts Agent Generate agents that belongs to your company. The `Agent` class is the core agent implementation in Upsonic, providing a powerful and flexible interface for creating AI agents with advanced capabilities including memory management, safety policies, reliability layers, and sophisticated tool integration. ## Overview The `Agent` can be created with minimal configuration or with extensive customization to suit your specific needs. The agent provides a robust foundation for AI-powered applications with built-in support for various advanced features. ## Key Features * **Memory Management**: Built-in support for session memory, user profiles, and conversation history * **Safety Policies**: Configurable user and agent policies for content filtering and validation * **Reliability Layer**: Advanced hallucination prevention and content validation * **Tool Integration**: Sophisticated tool processing with behavioral wrappers * **Thinking & Reasoning**: Optional advanced reasoning capabilities for complex tasks * **Multi-Model Support**: Works with OpenAI, Anthropic, Google, and others! * **Streaming**: Real-time response streaming for better user experience * **Caching**: Built-in caching system for improved performance * **Canvas Integration**: Support for persistent text editing and collaboration ## Example ### Basic Example ```python theme={null} from upsonic import Agent, Task # Create an agent agent = Agent("anthropic/claude-sonnet-4-5") # Execute with Task object task = Task("What is 2 + 2?") agent.print_do(task) # agent.do(task) # Or execute directly with a string (auto-converted to Task) agent.print_do("What is 2 + 2?") # agent.do("What is 2 + 2?") ``` When creating an agent without specifying a model, it defaults to `"openai/gpt-4o"`. Make sure you have the appropriate API key set in your environment. ### Deep Agent Example ```python theme={null} import asyncio from upsonic.agent.deepagent import DeepAgent from upsonic import Task async def main(): # Create a deep agent agent = DeepAgent(model="anthropic/claude-sonnet-4-5") # Create a complex task task = Task( description="Research Python web frameworks and create a comparison report. Save findings to /research/frameworks.txt and create /reports/comparison.txt" ) # Execute - agent will automatically create todos and manage the workflow await agent.print_do_async(task) # await agent.do_async(task) # Check files created files = await agent.filesystem_backend.glob("/**/*.txt") print(f"Files created: {files}") asyncio.run(main()) ``` ## Navigation * [Creating an Agent](/concepts/agents/creating-an-agent) - Learn how to create agents with different configurations * [Agent Attributes](/concepts/agents/attributes) - Comprehensive guide to all agent configuration options * [Adding a Memory](/concepts/agents/advanced/adding-a-memory) - Set up memory management for your agents * [Adding Thinking](/concepts/agents/advanced/adding-thinking) - Enable thinking capabilities for your agents * [Adding Reasoning](/concepts/agents/advanced/adding-reasoning) - Enable advanced reasoning for complex tasks # Agent printing Source: https://docs.upsonic.ai/concepts/agents/printing Learn how to control your Agent's printing By default, `do()` runs silently while `print_do()` shows output. You can change this behavior using the `print` parameter or environment variable. ## Quick Start ```python theme={null} from upsonic import Agent, Task agent = Agent("anthropic/claude-sonnet-4-5") task = Task("Say hello") # Silent execution agent.do(task) # With printed output agent.print_do(task) ``` ## Always Print or Never Print Set the `print` parameter when creating your agent: ```python theme={null} # Always print, even with do() agent = Agent("anthropic/claude-sonnet-4-5", print=True) agent.do(task) # Shows output # Never print, even with print_do() agent = Agent("anthropic/claude-sonnet-4-5", print=False) agent.print_do(task) # Silent ``` ## Global Control with Environment Variable Use `UPSONIC_AGENT_PRINT` to control all agents in your application: ```bash theme={null} # Enable printing for all agents export UPSONIC_AGENT_PRINT=true # Disable printing for all agents export UPSONIC_AGENT_PRINT=false ``` Environment variable has the highest priority and overrides both the `print` parameter and method choice. ## Priority Order When multiple settings conflict, this order applies: 1. **Environment variable** — Always wins 2. **Agent parameter** — `Agent(print=True/False)` 3. **Method choice** — `print_do()` prints, `do()` doesn't # Running Agents Source: https://docs.upsonic.ai/concepts/agents/running-agents Execute agents with different methods Agents can be executed using different methods depending on your needs - synchronous, asynchronous, or streaming. ## Synchronous Execution The simplest way to run an agent is using the `do()` method, which executes synchronously and returns the result. ```python theme={null} from upsonic import Agent, Task # Create agent agent = Agent("anthropic/claude-sonnet-4-5") # Execute with Task object task = Task("What is the capital of France?") result = agent.print_do(task) print(result) # Output: Paris # Or execute directly with a string result = agent.print_do("What is the capital of France?") print(result) # Output: Paris ``` ## List Input (Multiple Tasks) `do()`, `do_async()`, `print_do()`, and `print_do_async()` accept a **list of strings** or a **list of `Task` objects**. They run each item in sequence and return a list of string results. A single-element list returns a single string (scalar); an empty list returns an empty list. Mixed lists of `str` and `Task` are supported. ### List of strings ```python theme={null} from upsonic import Agent agent = Agent("anthropic/claude-sonnet-4-5") results = agent.do(["What is 2+2?", "What is 3+3?"]) # results is a list of strings, one per input for r in results: print(r) ``` ### List of Task objects ```python theme={null} from upsonic import Agent, Task agent = Agent("anthropic/claude-sonnet-4-5") tasks = [ Task("What is the capital of France?"), Task("What is the capital of Germany?"), ] results = agent.do(tasks) # results is a list of strings, one per task for r in results: print(r) ``` ## Asynchronous Execution For concurrent operations or async applications, use `do_async()` which returns a coroutine. ```python theme={null} from upsonic import Agent, Task import asyncio async def main(): # Create agent agent = Agent("anthropic/claude-sonnet-4-5") # Execute asynchronously (accepts Task or string) result = await agent.do_async("Explain quantum computing in simple terms") print(result) # Run async function asyncio.run(main()) ``` ## Streaming Text Output For real-time output, use `stream()` to get responses as they're generated. ```python theme={null} import asyncio from upsonic import Agent, Task async def main(): # Create agent and task agent = Agent("anthropic/claude-sonnet-4-5") task = Task("Write a short poem about coding") # Stream the output async for text_chunk in agent.astream(task): print(text_chunk, end='', flush=True) print() # New line after streaming if __name__ == "__main__": asyncio.run(main()) ``` ## Event Streaming For full visibility into agent execution, use `astream()` (or `stream()` for synchronous code) with `events=True` to receive detailed events about every step of the pipeline. ```python theme={null} import asyncio from upsonic import Agent, Task from upsonic.run.events.events import ( PipelineStartEvent, PipelineEndEvent, TextDeltaEvent, ToolCallEvent, ToolResultEvent, ) from upsonic.tools import tool @tool def calculate(x: int, y: int) -> int: """Add two numbers.""" return x + y async def main(): agent = Agent("anthropic/claude-sonnet-4-5") task = Task("Calculate 5 + 3", tools=[calculate]) async for event in agent.astream(task, events=True): if isinstance(event, PipelineStartEvent): print(f"🚀 Starting pipeline with {event.total_steps} steps") elif isinstance(event, ToolCallEvent): print(f"\n🔧 Calling: {event.tool_name}({event.tool_args})") elif isinstance(event, ToolResultEvent): status = "❌" if event.is_error else "✅" print(f"\n{status} Result: {event.result_preview}") elif isinstance(event, TextDeltaEvent): print("\nText Delta Event: ", event.content, end='', flush=True) elif isinstance(event, PipelineEndEvent): print(f"\n✅ Completed in {event.total_duration:.2f}s") asyncio.run(main()) ``` ### Event Categories #### Pipeline Events | Event | Description | Key Attributes | | -------------------- | ----------------------------- | ---------------------------------------------------------------------------- | | `PipelineStartEvent` | Emitted when execution begins | `total_steps`, `is_streaming`, `task_description` | | `PipelineEndEvent` | Emitted when execution ends | `total_steps`, `executed_steps`, `total_duration`, `status`, `error_message` | #### Step Events | Event | Description | Key Attributes | | ---------------- | -------------------------- | ---------------------------------------------------------------- | | `StepStartEvent` | Emitted when a step begins | `step_name`, `step_index`, `step_description`, `total_steps` | | `StepEndEvent` | Emitted when a step ends | `step_name`, `step_index`, `status`, `execution_time`, `message` | #### Tool Events | Event | Description | Key Attributes | | ------------------------ | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | `ToolCallEvent` | Emitted when a tool is called | `tool_name`, `tool_call_id`, `tool_args`, `tool_index` | | `ToolResultEvent` | Emitted when a tool returns | `tool_name`, `tool_call_id`, `result`, `result_preview`, `execution_time`, `is_error`, `error_message` | | `ExternalToolPauseEvent` | Emitted when execution pauses for external tool | `tool_name`, `tool_call_id`, `tool_args` | #### LLM Stream Events | Event | Description | Key Attributes | | -------------------- | ---------------------------------------- | ------------------------------------------------------- | | `TextDeltaEvent` | Text chunk during streaming | `content`, `accumulated_content`, `part_index` | | `TextCompleteEvent` | Text streaming complete | `content`, `part_index` | | `ThinkingDeltaEvent` | Reasoning content (for supported models) | `content`, `part_index` | | `ToolCallDeltaEvent` | Tool call arguments streaming | `tool_name`, `tool_call_id`, `args_delta`, `part_index` | | `FinalOutputEvent` | Final output ready | `output`, `output_type` | #### Initialization & Model Events | Event | Description | Key Attributes | | ------------------------ | --------------------------------------- | ------------------------------------------------------------------------------- | | `AgentInitializedEvent` | Agent initialized for execution | `agent_id`, `is_streaming` | | `StorageConnectionEvent` | Storage connection established | `storage_type`, `is_connected`, `has_memory`, `session_id` | | `LLMPreparedEvent` | LLM manager prepared | `default_model`, `requested_model`, `model_changed` | | `ModelSelectedEvent` | Model selected for execution | `model_name`, `provider`, `is_override` | | `ToolsConfiguredEvent` | Tools configured for the task | `tool_count`, `tool_names`, `has_mcp_handlers` | | `MessagesBuiltEvent` | Request messages built | `message_count`, `has_system_prompt`, `has_memory_messages`, `is_continuation` | | `ModelRequestStartEvent` | Model request starting | `model_name`, `is_streaming`, `has_tools`, `tool_call_count`, `tool_call_limit` | | `ModelResponseEvent` | Model response received (non-streaming) | `model_name`, `has_text`, `has_tool_calls`, `tool_call_count`, `finish_reason` | #### Context & Input Build Events These fire once per run as the agent assembles the request sent to the model. Useful for inspecting what the model actually receives (history size, prompt length, attached media). | Event | Description | Key Attributes | | ------------------------ | -------------------------------------------- | ----------------------------------------------------------- | | `MemoryPreparedEvent` | Memory manager preparation finished | `memory_enabled`, `history_count` | | `ChatHistoryLoadedEvent` | Chat history loaded; run boundary marked | `history_count` | | `SystemPromptBuiltEvent` | System prompt assembled | `prompt_length`, `has_culture`, `has_skills` | | `ContextBuiltEvent` | Task context assembled (RAG + prior outputs) | `context_length`, `has_knowledge_base`, `has_prior_outputs` | | `UserInputBuiltEvent` | User input assembled (text + media) | `input_type`, `has_images`, `has_documents`, `input_length` | #### Cache Events | Event | Description | Key Attributes | | ------------------ | ----------------------------------- | --------------------------------------------------------------------------- | | `CacheCheckEvent` | Cache checked for existing response | `cache_enabled`, `cache_method`, `cache_hit`, `similarity`, `input_preview` | | `CacheHitEvent` | Cache hit occurred | `cache_method`, `similarity`, `cached_response_preview` | | `CacheMissEvent` | Cache miss occurred | `cache_method`, `reason` | | `CacheStoredEvent` | Response stored in cache | `cache_method`, `duration_minutes` | #### Policy Events | Event | Description | Key Attributes | | --------------------- | --------------------------- | ---------------------------------------------------------------------------------- | | `PolicyCheckEvent` | Policy validation performed | `policy_type`, `action`, `policies_checked`, `content_modified`, `blocked_reason` | | `PolicyFeedbackEvent` | Policy feedback for retry | `policy_type`, `feedback_message`, `retry_count`, `max_retries`, `violated_policy` | #### Memory, Reflection & Reliability Events | Event | Description | Key Attributes | | ------------------------ | ----------------------------- | ----------------------------------------------------------------------------------- | | `MemoryUpdateEvent` | Memory updated | `messages_added`, `memory_type` | | `ReflectionEvent` | Reflection processing applied | `reflection_applied`, `improvement_made`, `original_preview`, `improved_preview` | | `ReliabilityEvent` | Reliability layer processing | `reliability_applied`, `modifications_made` | | `ExecutionCompleteEvent` | Execution complete | `output_type`, `has_output`, `output_preview`, `total_tool_calls`, `total_duration` | #### Run Lifecycle Events | Event | Description | Key Attributes | | ------------------- | ---------------------------------- | ------------------------------------- | | `RunStartedEvent` | Run started | `agent_id`, `task_description` | | `RunCompletedEvent` | Run completed successfully | `agent_id`, `output_preview` | | `RunPausedEvent` | Run paused (for HITL requirements) | `reason`, `requirements`, `step_name` | | `RunCancelledEvent` | Run cancelled | `message`, `step_name` | ### Common Attributes All events inherit from `AgentEvent` and share these base attributes: | Attribute | Type | Description | | ------------ | --------------- | -------------------------------------------------------------- | | `event_id` | `str` | Unique identifier (8 chars) | | `run_id` | `Optional[str]` | The agent run ID this event belongs to (matches Agent.run\_id) | | `timestamp` | `datetime` | When the event occurred | | `event_type` | `str` | Class name of the event (property, not a field) | | `event_kind` | `str` | Event category identifier | ### Synchronous Event Streaming For synchronous code, use `stream()` with `events=True`: ```python theme={null} from upsonic import Agent, Task from upsonic.run.events.events import TextDeltaEvent, PipelineStartEvent, PipelineEndEvent agent = Agent("anthropic/claude-sonnet-4-5") task = Task("Explain AI briefly") # Stream events synchronously for event in agent.stream(task, events=True): if isinstance(event, PipelineStartEvent): print(f"Starting pipeline with {event.total_steps} steps") elif isinstance(event, TextDeltaEvent): print(event.content, end='', flush=True) elif isinstance(event, PipelineEndEvent): print(f"\nCompleted in {event.total_duration:.2f}s") # After streaming completes, access the final output # Option 1: From the task (most direct) final_output = task.response print(f"\nFinal (from task.response): {final_output}") # Option 2: From the agent's run output (includes additional metadata) run_output = agent.get_run_output() if run_output: print(f"Final (from agent.get_run_output().output): {run_output.output}") # You can also access other metadata: # - run_output.usage (token usage) # - run_output.messages (all messages) # - run_output.tools (tool executions) # - run_output.execution_stats (execution statistics) ``` **Note:** The `stream()` method returns an iterator that yields either: * `str` chunks when `events=False` (default) - for text streaming * `AgentStreamEvent` objects when `events=True` - for event streaming For async streaming, use `astream()` with the same `events` parameter. ## Tool Management Tools can be added to agents during initialization or dynamically using `add_tools()`. Use `get_tool_defs()` to retrieve all registered tool definitions. ```python theme={null} from upsonic import Agent from upsonic.tools import tool @tool def calculate(x: int, y: int) -> int: """Add two numbers.""" return x + y @tool def another_tool() -> str: """Another tool.""" return "Another tool" # Add tools during initialization agent = Agent("anthropic/claude-sonnet-4-5", tools=[calculate]) # Or add tools after initialization agent.add_tools([another_tool]) # Get all registered tool definitions tool_defs = agent.get_tool_defs() print(tool_defs) ``` # Filesystem Tools Source: https://docs.upsonic.ai/concepts/autonomous-agent/advanced/filesystem-tools File operations available in AutonomousAgent The `AutonomousFilesystemToolKit` provides comprehensive file operations, all sandboxed to the workspace directory. ## Available Tools | Tool | Description | | ------------------ | ---------------------------------------------------- | | `read_file` | Read file contents with optional line offset/limit | | `write_file` | Create or overwrite files | | `edit_file` | Replace text in files (requires reading first) | | `list_files` | List directory contents (recursive or non-recursive) | | `search_files` | Search for files by name pattern | | `grep_files` | Search file contents using regex | | `file_info` | Get file metadata (size, dates, permissions) | | `create_directory` | Create directories recursively | | `move_file` | Move or rename files | | `copy_file` | Copy files or directories | | `delete_file` | Delete files or directories | ## Example: Code Analysis ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # Search and analyze code task = Task("Find all Python files that contain 'TODO' comments and list them with line numbers") agent.print_do(task) ``` ## Example: Bulk File Operations ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # Create project structure task = Task(""" Create a basic Python package structure: - src/mypackage/__init__.py - src/mypackage/core.py with a sample function - tests/__init__.py - tests/test_core.py with a basic test """) agent.print_do(task) ``` ## Read-Before-Edit Safety The filesystem toolkit enforces reading a file before editing it. This prevents accidental modifications to files the agent hasn't seen: ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # The agent will automatically read first, then edit task = Task("Add type hints to all functions in utils.py") agent.print_do(task) ``` ## Direct Toolkit Access Access the toolkit directly for programmatic use: ```python theme={null} from upsonic import AutonomousAgent agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # Read a file content = agent.filesystem_toolkit.read_file("README.md") print(content) # List files in a directory files = agent.filesystem_toolkit.list_files("src", recursive=True) print(files) # Search for files by pattern python_files = agent.filesystem_toolkit.search_files("*.py") print(python_files) # Check what files were read print(agent.filesystem_toolkit.get_read_files()) # Reset tracking if needed agent.filesystem_toolkit.reset_read_tracking() ``` # Memory Integration Source: https://docs.upsonic.ai/concepts/autonomous-agent/advanced/memory-integration Session persistence and memory in AutonomousAgent AutonomousAgent comes with automatic memory setup for session persistence, with sensible defaults enabled out of the box. ## Default Configuration By default, `AutonomousAgent` uses: * **InMemoryStorage**: Automatic storage backend (no configuration needed) * **Full Session Memory**: Enabled by default to preserve conversation history ```python theme={null} from upsonic import AutonomousAgent, Task # InMemoryStorage + full_session_memory are enabled automatically agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # First interaction task = Task("Read the main.py file") agent.print_do(task) # Second interaction - agent remembers context (full_session_memory is True by default) task = Task("Now add error handling to that file") agent.print_do(task) ``` ## Additional Memory Features Enable additional memory features beyond the default: ```python theme={null} from upsonic import AutonomousAgent agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", # full_session_memory=True is already the default summary_memory=True, # Generate session summaries user_analysis_memory=True # Track user preferences ) ``` ## Persistent Storage Use database-backed storage for persistence across sessions: ```python theme={null} from upsonic import AutonomousAgent, Task from upsonic.storage import SqliteStorage, Memory # Create persistent storage storage = SqliteStorage(db_file="sessions.db") memory = Memory( storage=storage, session_id="project_session_001", user_id="developer_001", full_session_memory=True ) agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", memory=memory ) # Conversations persist across restarts task = Task("Continue where we left off") agent.print_do(task) ``` ## Session and User IDs Track sessions and users: ```python theme={null} from upsonic import AutonomousAgent agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", session_id="coding_session_123", user_id="alice" # full_session_memory=True is the default ) # Access IDs print(f"Session: {agent.session_id}") print(f"User: {agent.user_id}") ``` # Shell Tools Source: https://docs.upsonic.ai/concepts/autonomous-agent/advanced/shell-tools Terminal command execution in AutonomousAgent The `AutonomousShellToolKit` enables secure terminal command execution within the workspace. ## Available Tools | Tool | Description | | ---------------------- | -------------------------------- | | `run_command` | Execute shell commands | | `run_python` | Execute Python code snippets | | `check_command_exists` | Verify if a command is available | ## Configuration Options | Option | Default | Description | | ------------------ | ----------------- | ------------------------------------------- | | `shell_timeout` | 120 | Default command timeout in seconds | | `shell_max_output` | 10000 | Maximum output characters before truncation | | `blocked_commands` | Security defaults | Commands that are blocked | ## Example: Running Commands ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", shell_timeout=60 ) # Run development tasks task = Task("Run the test suite and report any failures") agent.print_do(task) ``` ## Example: Python Execution ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # Execute Python code task = Task("Write and run a Python script that calculates the Fibonacci sequence up to 100") agent.print_do(task) ``` ## Command Blocking By default, dangerous commands are blocked. You can customize the blocklist: ```python theme={null} from upsonic import AutonomousAgent agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", blocked_commands=["rm -rf", "sudo", "chmod 777"] ) ``` ## Environment Variables Pass custom environment variables to commands: ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # The shell toolkit supports environment variables # Commands run in the workspace directory task = Task("Set DEBUG=true and run the application") agent.print_do(task) ``` ## Direct Toolkit Access Access the shell toolkit directly: ```python theme={null} from upsonic import AutonomousAgent agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # Direct execution result = agent.shell_toolkit.run_command("python3 --version") print(result) # Check command availability exists = agent.shell_toolkit.check_command_exists("docker") print(f"Docker available: {exists}") # Run Python code output = agent.shell_toolkit.run_python("print([x**2 for x in range(5)])") print(output) ``` # Workspace Security Source: https://docs.upsonic.ai/concepts/autonomous-agent/advanced/workspace-security Sandboxing and security features in AutonomousAgent AutonomousAgent implements strict security measures to prevent unintended access outside the workspace. ## Workspace Sandboxing All file and shell operations are restricted to the workspace directory: ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/home/user/my-project" ) # These paths work (within workspace) task = Task("Read src/main.py") # /home/user/my-project/src/main.py agent.print_do(task) task = Task("Read ./config.json") # /home/user/my-project/config.json agent.print_do(task) # Path traversal is blocked task = Task("Read ../other-project/secret.txt") # Blocked - outside workspace agent.print_do(task) task = Task("Read /etc/passwd") # Blocked - absolute path outside workspace agent.print_do(task) ``` ## Default Blocked Commands The shell toolkit blocks dangerous commands by default: * `rm -rf /` and `rm -rf /*` (destructive patterns) * `:(){:|:&};:` (fork bomb) * `mkfs` (filesystem formatting) * `dd if=/dev/zero` (disk overwrite) You can add additional blocked commands like `sudo` via the `blocked_commands` parameter. ## Custom Security Configuration ```python theme={null} from upsonic import AutonomousAgent # Disable shell entirely for maximum security agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", enable_shell=False # Only filesystem access ) # Or customize blocked commands agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", blocked_commands=["rm", "sudo", "chmod", "curl", "wget"] ) ``` ## Tracking File Access Monitor which files the agent has read: ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) task = Task("Read config.py and utils.py, then update utils.py") agent.print_do(task) # Check accessed files print("Files read:", agent.filesystem_toolkit.get_read_files()) # Reset tracking if needed agent.filesystem_toolkit.reset_read_tracking() # Or use the agent-level method: agent.reset_filesystem_tracking() ``` # AGENTS.md Source: https://docs.upsonic.ai/concepts/autonomous-agent/agents-md Configure AutonomousAgent behavior using an AGENTS.md file in the workspace The AGENTS.md feature allows you to configure your AutonomousAgent using a markdown file stored in the workspace directory. When a workspace is set, the agent reads the `AGENTS.md` file and includes it in the system prompt, providing persistent configuration and behavioral guidelines. ## Overview When you set a `workspace` path on an AutonomousAgent: 1. **Configuration Loading**: The agent reads the `AGENTS.md` file from the workspace folder and includes it in the system prompt 2. **Session Greeting**: You can call `execute_workspace_greeting()` to generate a personalized greeting based on the configuration ## Example ```python theme={null} from upsonic import AutonomousAgent, Task # Create an autonomous agent with workspace agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", session_id="user_session_001" ) # Execute the workspace greeting (optional, for new sessions) greeting = agent.execute_workspace_greeting() print(greeting) # Run tasks - the AGENTS.md content is included in the system prompt task = Task("What can you help me with?") agent.print_do(task) ``` ## The AGENTS.md File Create an `AGENTS.md` file in your workspace folder to define your agent's behavior. We provide a ready-to-use template with memory management, safety rules, group chat guidelines, and more. Get the full AGENTS.md template you can copy and customize for your workspace. The content of this file is automatically injected into the agent's system prompt wrapped in `` tags. ## How It Works When the AutonomousAgent initializes with a workspace: 1. It checks if an `AGENTS.md` file exists in the workspace directory 2. If found, the file content is read and appended to the system prompt 3. The agent uses these instructions alongside its built-in filesystem and shell tool guidelines 4. The greeting method can introduce the agent based on its configuration ## Integration with Interfaces When using Upsonic [interfaces](/concepts/interfaces/Overview) (Telegram, Slack, WhatsApp), the workspace greeting is automatically called when a user resets their session with the `/reset` command. The greeting response is sent to the user, providing a fresh start with a personalized introduction. # Attributes Source: https://docs.upsonic.ai/concepts/autonomous-agent/attributes Configuration options for the AutonomousAgent ## Attributes `AutonomousAgent` inherits all attributes from `Agent` and adds the following autonomous-specific options: ### Autonomous Agent Specific Attributes | Attribute | Type | Default | Description | | ------------------------ | ------------------ | ------------------- | ------------------------------------------------------------------------- | | `workspace` | str \| None | Current directory | Workspace directory path. All file/shell operations are sandboxed here | | `storage` | Storage \| None | `InMemoryStorage()` | Custom storage backend. If None, InMemoryStorage is created automatically | | `enable_filesystem` | bool | `True` | Enable filesystem tools (read, write, edit, list, search, etc.) | | `enable_shell` | bool | `True` | Enable shell command execution tools | | `shell_timeout` | int | `120` | Default timeout for shell commands in seconds | | `shell_max_output` | int | `10000` | Maximum output length before truncation | | `blocked_commands` | List\[str] \| None | Security defaults | List of command patterns to block for security | | `full_session_memory` | bool | `True` | Enable chat history persistence (enabled by default) | | `summary_memory` | bool | `False` | Enable session summary generation | | `user_analysis_memory` | bool | `False` | Enable user profile extraction | | `user_profile_schema` | BaseModel \| None | `None` | Pydantic model for user profile structure | | `dynamic_user_profile` | bool | `False` | Generate profile schema dynamically | | `num_last_messages` | int \| None | `None` | Limit on message turns to keep in history | | `feed_tool_call_results` | bool \| None | `None` | Include tool call results in history | ### Inherited Agent Attributes All standard `Agent` attributes are also available: | Attribute | Type | Default | Description | | -------------------------------- | ---------------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------- | | `model` | str \| Model | `"openai/gpt-4o"` | Model identifier or Model instance | | `name` | str \| None | `None` | Agent name for identification | | `memory` | Memory \| None | Auto-created | Memory instance (auto-created with storage if not provided) | | `db` | DatabaseBase \| None | `None` | Database instance (overrides memory if provided) | | `session_id` | str \| None | Auto-generated | Session identifier for conversation tracking | | `user_id` | str \| None | Auto-generated | User identifier for multi-user scenarios | | `debug` | bool | `False` | Enable debug logging | | `debug_level` | int | `1` | Debug level (1 = standard, 2 = detailed) | | `print` | bool \| None | `None` (defaults to `True`) | Enable printing of output. If None, reads from UPSONIC\_AGENT\_PRINT env var, else defaults to True | | `role` | str \| None | `None` | Agent role | | `goal` | str \| None | `None` | Agent goal | | `instructions` | str \| None | `None` | Specific instructions | | `system_prompt` | str \| None | Auto-generated | Custom system prompt. If None, a built-in prompt with tool usage guidelines is generated | | `tools` | List\[Any] \| None | `None` | Additional tools (merged with default filesystem/shell tools) | | `tool_call_limit` | int | `100` | Maximum tool calls per execution | | `show_tool_calls` | bool | `True` | Display tool calls in output | | `context_management` | bool | `False` | Enable context management | | `context_management_keep_recent` | int | `5` | Recent messages to keep when managing context | | `user_policy` | Policy \| List\[Policy] \| None | `None` | User input safety policy | | `agent_policy` | Policy \| List\[Policy] \| None | `None` | Agent output safety policy | | `tool_policy_pre` | Policy \| List\[Policy] \| None | `None` | Tool safety policy for pre-execution | | `tool_policy_post` | Policy \| List\[Policy] \| None | `None` | Tool safety policy for post-execution | | `retry` | int | `1` | Number of retry attempts | | `mode` | Literal\["raise", "return\_false"] | `"raise"` | Retry mode behavior | ## Properties | Property | Type | Description | | ---------------------- | ----------------------------------- | ------------------------------------------ | | `autonomous_workspace` | Path | Resolved workspace path | | `autonomous_storage` | Storage \| None | Storage backend created by AutonomousAgent | | `autonomous_memory` | Memory \| None | Memory instance created by AutonomousAgent | | `filesystem_toolkit` | AutonomousFilesystemToolKit \| None | Filesystem toolkit (if enabled) | | `shell_toolkit` | AutonomousShellToolKit \| None | Shell toolkit (if enabled) | ## Methods | Method | Description | | ----------------------------- | ------------------------------------- | | `reset_filesystem_tracking()` | Clear the record of read/edited files | ## Configuration Example ```python theme={null} from upsonic import AutonomousAgent, Task # Full configuration example agent = AutonomousAgent( # Model model="anthropic/claude-sonnet-4-5", # Workspace (all operations sandboxed here) workspace="/path/to/project", # Agent identity name="DevAssistant", role="Senior Developer", goal="Help developers write better code", instructions="Follow best practices and include error handling.", # Toolkit configuration enable_filesystem=True, enable_shell=True, shell_timeout=60, # Memory configuration full_session_memory=True, summary_memory=True, # Debug debug=True ) # Execute a task task = Task("Create a new Python module for data validation") result = agent.print_do(task) print(result) ``` # Creating an Autonomous Agent Source: https://docs.upsonic.ai/concepts/autonomous-agent/creating-an-autonomous-agent Learn how to build Autonomous Agents with Upsonic `AutonomousAgent` is perfect for tasks that require filesystem or shell access. It comes pre-configured with: * **InMemoryStorage** as the default storage backend * **Full session memory enabled** for conversation history persistence * **Filesystem and shell tools** ready to use This means you can focus on your task without any configuration. ## Basic Creation The simplest way to create an autonomous agent: ```python theme={null} from upsonic import AutonomousAgent, Task # Create with just a model and workspace agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # The agent has filesystem and shell tools ready to use task = Task("List all Python files and count the total lines of code") agent.print_do(task) ``` ## Workspace Configuration The workspace is where all file and shell operations take place. It's sandboxed for security: ```python theme={null} from upsonic import AutonomousAgent, Task # Workspace defaults to current directory if not specified agent = AutonomousAgent(model="anthropic/claude-sonnet-4-5") # Or specify a workspace explicitly agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/home/user/projects/my-app" ) # All paths are relative to the workspace task = Task("Read src/main.py") # Reads /home/user/projects/my-app/src/main.py agent.print_do(task) ``` ## Adding Agent Identity Give your agent a role and personality: ```python theme={null} from upsonic import AutonomousAgent, Task agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", name="CodeReviewer", role="Senior Software Engineer", goal="Review code for bugs and suggest improvements", instructions="Be thorough but constructive. Focus on security and performance." ) task = Task("Review the authentication module for security issues") agent.print_do(task) ``` ## Custom Storage Use custom storage instead of the default InMemoryStorage: ```python theme={null} from upsonic import AutonomousAgent from upsonic.storage import SqliteStorage, Memory # Create custom storage storage = SqliteStorage(db_file="agent_sessions.db") memory = Memory( storage=storage, session_id="session_001", full_session_memory=True ) agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", memory=memory ) ``` ## Selective Toolkits Enable only the tools you need: ```python theme={null} from upsonic import AutonomousAgent # Filesystem only (no shell access) agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", enable_filesystem=True, enable_shell=False ) # Shell only (no filesystem access) agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", enable_filesystem=False, enable_shell=True ) ``` ## Adding Custom Tools Add your own tools alongside the default ones: ```python theme={null} from upsonic import AutonomousAgent, Task from upsonic.tools import tool @tool def deploy_to_staging() -> str: """Deploy the current code to staging environment.""" return "Deployed successfully to staging!" agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project", tools=[deploy_to_staging] # Added alongside filesystem and shell tools ) task = Task("Run tests and if they pass, deploy to staging") agent.print_do(task) ``` ## Next Steps * [Running an Autonomous Agent](/concepts/autonomous-agent/running-an-autonomous-agent) - Learn execution methods * [Filesystem Tools](/concepts/autonomous-agent/advanced/filesystem-tools) - Detailed filesystem operations * [Shell Tools](/concepts/autonomous-agent/advanced/shell-tools) - Shell command execution # Basic Autonomous Agent Example Source: https://docs.upsonic.ai/concepts/autonomous-agent/examples/basic-autonomous-agent-example A quick example to get started with AutonomousAgent Build a working autonomous agent in just a few lines of code. The `AutonomousAgent` comes pre-configured with filesystem and shell tools, automatic storage, and workspace sandboxing. ## Basic Example ```python theme={null} from upsonic import AutonomousAgent, Task # Create an autonomous agent with workspace agent = AutonomousAgent( model="anthropic/claude-sonnet-4-5", workspace="/path/to/project" ) # The agent can read, write, and execute in the workspace task = Task("Read the main.py file and explain what it does") agent.print_do(task) ``` All file and shell operations are restricted to the workspace directory. Attempting to access files outside the workspace will be blocked for security. ## What's Included by Default When you create an `AutonomousAgent`, you get: * **InMemoryStorage** as the default storage backend * **Full session memory** enabled for conversation history persistence * **Filesystem toolkit** for file operations (read, write, edit, search, etc.) * **Shell toolkit** for terminal command execution * **Workspace sandboxing** for security # Autonomous Agent Source: https://docs.upsonic.ai/concepts/autonomous-agent/overview Pre-configured agent with filesystem and shell capabilities