{"id":35740972,"url":"https://github.com/dev-aliraza/stark-agents","last_synced_at":"2026-03-14T22:57:45.653Z","repository":{"id":332092849,"uuid":"1127259524","full_name":"dev-aliraza/stark-agents","owner":"dev-aliraza","description":"A powerful Python ADK for building model agnostic AI agents","archived":false,"fork":false,"pushed_at":"2026-01-28T16:47:06.000Z","size":271,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-29T07:37:37.107Z","etag":null,"topics":["adk","adk-python","agent-development-kit","agentic-ai","agentic-ai-development","agents","ai-agent"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dev-aliraza.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-03T14:15:47.000Z","updated_at":"2026-01-28T16:49:50.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dev-aliraza/stark-agents","commit_stats":null,"previous_names":["dev-aliraza/stark-agents"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/dev-aliraza/stark-agents","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dev-aliraza%2Fstark-agents","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dev-aliraza%2Fstark-agents/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dev-aliraza%2Fstark-agents/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dev-aliraza%2Fstark-agents/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dev-aliraza","download_url":"https://codeload.github.com/dev-aliraza/stark-agents/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dev-aliraza%2Fstark-agents/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30520782,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-14T19:51:21.629Z","status":"ssl_error","status_checked_at":"2026-03-14T19:51:12.959Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adk","adk-python","agent-development-kit","agentic-ai","agentic-ai-development","agents","ai-agent"],"created_at":"2026-01-06T15:12:03.281Z","updated_at":"2026-03-14T22:57:45.621Z","avatar_url":"https://github.com/dev-aliraza.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stark Agents\n\nA powerful Python ADK for building model agnostic AI agents with the support for MCP servers, function tools, hierarchical sub-agents, and advanced execution control.\n\n## Features\n\n- 🧠 **Model Agnostic**: Built on top of LiteLLM, allowing you to use 100+ LLMs (OpenAI, Anthropic, Gemini, DeepSeek, Ollama, etc.) interchangeably.\n- 🔧 **Native MCP Support**: First-class support for Model Context Protocol (MCP) servers. Connect any MCP server to extend agent capabilities instantly.\n- 📚 **Markdown-based Skills**: Define agent skills in simple Markdown files (`SKILL.md`) with natural language. No complex coding required to add new capabilities.\n- 🛠️ **Function Tools \u0026 Schema**: Write standard Python functions or classes. Stark automatically generates JSON schemas and handles execution.\n- 👥 **Hierarchical Agents**: Build complex workflows with a main agent delegating tasks to specialized sub-agents.\n- 🪝 **Lifecycle Hooks**: Granular control with `model_input_hook`, `post_llm_hook`, and `iteration_end_hook` to modify behavior at every step.\n- 📡 **Streaming Support**: Real-time streaming of content, tool calls, and state updates for responsive UI applications.\n- 🔍 **Web Search**: Built-in support for web search capabilities with citation tracking.\n- 🛡️ **Human-in-the-loop**: Comprehensive approval systems for sensitive tool calls and actions.\n\n## Comparison with other ADKs\n\n| Feature | Stark Agents | LangChain | AutoGen | CrewAI |\n| :--- | :--- | :--- | :--- | :--- |\n| **Core Philosophy** | **Lightweight, Model Agnostic, Skill-based** | Chain-based, Extensive Integrations | Conversational, Multi-agent | Role-playing, Process-oriented |\n| **Model Support** | **Truly Agnostic (via LiteLLM)** | Extensive (via integrations) | Extensive | Open Source focus |\n| **Skill Definition** | **Markdown / Natural Language** | (No Skills Support) | (No Skills Support) | (No Skills Support) |\n| **Complexity** | **Low (Pythonic, Minimal)** | High (Steep learning curve) | Medium | Medium |\n| **MCP Support** | **Native First-Class** | Via community/addons | Via extensions | Via extensions |\n| **Agent Definition** | **Single Class (Agent)** | Multiple Chains/Agents | ConversationalAgent | Agent Role Class |\n\n## Installation\n\n```bash\npip install stark-agents\n```\n\n## Quick Start\n\n### Basic Agent\n\n```python\nfrom stark import Agent, Runner\n\nagent = Agent(\n    name=\"Assistant\",\n    instructions=\"You are a helpful assistant\",\n    model=\"claude-sonnet-4-5\"\n)\n\nresult = Runner(agent).run(input=[{\"role\": \"user\", \"content\": \"Hello!\"}])\nprint(result.result[-1][\"content\"])\n```\n\n### Agent with MCP Servers\n\n```python\nimport os\nfrom stark import Agent, Runner\n\nmcp_servers = {\n    \"slack\": {\n        \"command\": \"uvx\",\n        \"args\": [\"mcp-slack\"],\n        \"env\": {\n            \"SLACK_BOT_TOKEN\": os.environ.get(\"SLACK_BOT_TOKEN\", \"\")\n        }\n    }\n}\n\nagent = Agent(\n    name=\"Slack-Agent\",\n    instructions=\"You can interact with Slack\",\n    model=\"claude-sonnet-4-5\",\n    mcp_servers=mcp_servers\n)\n\nresult = Runner(agent).run(\n    input=[{\"role\": \"user\", \"content\": \"Send a message to #general\"}]\n)\n```\n\n### Agent with Function Tools\n\n#### Using the `@stark_tool` Decorator (Recommended)\n\nThe `@stark_tool` decorator automatically generates JSON schemas from your function signatures:\n\n```python\nfrom stark import Agent, Runner, stark_tool\n\n@stark_tool\ndef search_database(query: str, limit: int = 10) -\u003e str:\n    \"\"\"Search the database for information\"\"\"\n    # Your function implementation\n    results = [\"item1\", \"item2\"]\n    return f\"Found {len(results)} results for '{query}'\"\n\n@stark_tool\ndef get_user_info(user_id: int, include_details: bool = False) -\u003e str:\n    \"\"\"Retrieve user information from the database\"\"\"\n    return f\"User {user_id} details\"\n\nagent = Agent(\n    name=\"Search-Agent\",\n    instructions=\"You can search the database and get user info\",\n    model=\"claude-sonnet-4-5\",\n    function_tools=[search_database, get_user_info]\n)\n\nresult = Runner(agent).run(\n    input=[{\"role\": \"user\", \"content\": \"Search for users named John\"}]\n)\n```\n\n#### Using Class-Based Tools\n\nYou can also organize related tools into classes:\n\n```python\nfrom stark import Agent, Runner, stark_tool\n\nclass DatabaseTools:\n    def __init__(self, db_connection):\n        self.db = db_connection\n    \n    @stark_tool\n    def search(self, query: str, limit: int = 10) -\u003e str:\n        \"\"\"Search the database\"\"\"\n        return f\"Search results for: {query}\"\n    \n    @stark_tool\n    def insert(self, table: str, data: dict) -\u003e str:\n        \"\"\"Insert data into a table\"\"\"\n        return f\"Inserted into {table}\"\n\n# Pass the class instance\ndb_tools = DatabaseTools(db_connection=\"my_db\")\n\nagent = Agent(\n    name=\"DB-Agent\",\n    instructions=\"You can interact with the database\",\n    model=\"claude-sonnet-4-5\",\n    function_tools=[db_tools]\n)\n```\n\n#### Built-in Code Tools\n\nStark includes a comprehensive `CodeTool` class for file operations:\n\n```python\nfrom stark import Agent, Runner\nfrom stark.tools import CodeTool\n\ncode_tool = CodeTool(workspace_dir=\"./my_project\")\n\nagent = Agent(\n    name=\"Code-Agent\",\n    instructions=\"You can read, write, and manage files\",\n    model=\"claude-sonnet-4-5\",\n    function_tools=[code_tool]\n)\n\nresult = Runner(agent).run(\n    input=[{\"role\": \"user\", \"content\": \"Create a new Python file called app.py\"}]\n)\n```\n\n### Skills System\n\nStark supports a unique \"Skills\" system where you can define reusable agent capabilities using markdown files.\n\n#### Directory Structure\n\nCreate a `skills` directory with subdirectories for each skill:\n\n```\nskills/\n  ├── python_expert/\n  │   └── SKILL.md\n  └── data_analyst/\n      └── SKILL.md\n```\n\n#### The SKILL.md Format\n\nEach skill is defined in a `SKILL.md` file with YAML frontmatter:\n\n```markdown\n---\nname: python_expert\ndescription: A skill that provides Python programming expertise\n---\n\nYou are an expert Python programmer. You follow PEP 8 standards.\nWhen writing code, always include type hints and docstrings.\n```\n\n#### Loading Skills\n\n```python\nfrom stark import Agent, Runner\nfrom stark.type import SkillConfig\n\n# Basic skill loading\nagent = Agent(\n    name=\"Dev-Agent\",\n    instructions=\"You are a senior developer.\",\n    model=\"claude-sonnet-4-5\",\n    skills=[\"./skills/python_expert\"]  # Path to the skill folder\n)\n\n# Advanced: Customize skill execution with SkillConfig\nskill_config = SkillConfig(\n    model=\"gpt-4o\",                    # Use a different model for skills\n    llm_provider=\"openai\",             # Specify LLM provider for skills\n    max_iterations=50,                 # Increase iteration limit for skills\n    max_output_tokens=32000,           # Set max output tokens\n    parallel_tool_calls=True,          # Enable parallel tool execution\n    thinking_level=\"high\",             # Set reasoning level for thinking models\n    enable_web_search=True             # Enable web search for skills\n)\n\nagent = Agent(\n    name=\"Dev-Agent\",\n    instructions=\"You are a senior developer.\",\n    model=\"claude-sonnet-4-5\",\n    skills=[\"./skills/python_expert\"],\n    skill_config=skill_config\n)\n```\n\n### Advanced Skills Usage with Custom Tools\n\nSkills can have their own MCP servers and function tools by creating a `tools.py` file in the skill directory:\n\n**Directory Structure:**\n```\nskills/\n  └── web_scraper/\n      ├── SKILL.md\n      └── tools.py\n```\n\n**tools.py:**\n```python\nfrom stark import stark_tool\nimport os\n\n@stark_tool\ndef parse_html(html: str) -\u003e str:\n    \"\"\"Parse HTML content and extract text\"\"\"\n    # Your implementation\n    return \"Parsed content\"\n\n# Define tools dictionary\nTOOLS = {\n    \"mcp\": {\n        \"browser\": {\n            \"command\": \"uvx\",\n            \"args\": [\"mcp-server-browser\"],\n            \"env\": {}\n        }\n    },\n    \"function\": [\n        parse_html\n    ]\n}\n```\n\nWhen this skill is invoked, it will have access to:\n- The built-in `CodeTool` (automatically included)\n- Any MCP servers defined in `TOOLS[\"mcp\"]`\n- Any function tools defined in `TOOLS[\"function\"]`\n\n### Reasoning Models\n\nStark supports reasoning (or \"thinking\") models like OpenAI's O1 series. You can control the reasoning effort:\n\n```python\nagent = Agent(\n    name=\"Thinking-Agent\",\n    instructions=\"Solve this complex logic puzzle\",\n    model=\"o1\",\n    thinking_level=\"high\"  # Options: \"none\", \"low\", \"medium\", \"high\"\n)\n```\n\n### Hierarchical Sub-Agents\n\n```python\nfrom stark import Agent, Runner\n\n# Define sub-agents\ndelivery_agent = Agent(\n    name=\"Delivery-Agent\",\n    description=\"Handles pizza delivery\",\n    instructions=\"Confirm delivery details and provide tracking\",\n    model=\"claude-sonnet-4-5\"\n)\n\npizza_agent = Agent(\n    name=\"Pizza-Agent\",\n    description=\"Handles pizza preparation\",\n    instructions=\"Prepare the pizza and call delivery agent\",\n    model=\"claude-sonnet-4-5\",\n    sub_agents=[delivery_agent]\n)\n\n# Main agent with sub-agents\nmaster_agent = Agent(\n    name=\"Master-Agent\",\n    instructions=\"Coordinate pizza orders using available agents\",\n    model=\"claude-sonnet-4-5\",\n    sub_agents=[pizza_agent]\n)\n\nresult = Runner(master_agent).run(\n    input=[{\"role\": \"user\", \"content\": \"I want to order a pepperoni pizza\"}]\n)\n\n# Access sub-agent responses\nprint(result.sub_agents_response.get(\"Pizza-Agent\"))\nprint(result.sub_agents_response.get(\"Delivery-Agent\"))\n```\n\n### Streaming Responses\n\n```python\nimport asyncio\nfrom stark import Agent, Runner, RunnerStream, Stream\n\nasync def main():\n    agent = Agent(\n        name=\"Streaming-Agent\",\n        instructions=\"You are a helpful assistant\",\n        model=\"claude-sonnet-4-5\"\n    )\n\n    async for event in Runner(agent).run_stream(\n        input=[{\"role\": \"user\", \"content\": \"Tell me a story\"}]\n    ):\n        if event.type == Stream.CONTENT_CHUNK:\n            print(RunnerStream.data_dump(event), end=\"\", flush=True)\n        \n        elif event.type == Stream.TOOL_CALLS:\n            print(f\"\\nTool calls: {RunnerStream.data_dump(event)}\")\n        \n        elif event.type == Stream.TOOL_RESPONSE:\n            print(f\"Tool response: {RunnerStream.data_dump(event)}\")\n        \n        elif event.type == Stream.ITER_START:\n            print(f\"\\n--- Iteration {RunnerStream.data_dump(event)} ---\")\n        \n        elif event.type == Stream.ITER_END:\n            print(f\"\\n--- Iteration Complete ---\")\n        \n        elif event.type == Stream.AGENT_RUN_END:\n            print(f\"\\nAgent finished: {RunnerStream.data_dump(event)}\")\n\nasyncio.run(main())\n```\n\n### Web Search\n\nEnable web search capabilities for your agents:\n\n```python\nfrom stark import Agent, Runner\nfrom stark.llm_providers import OPENAI, ANTHROPIC, GEMINI\n\n# OpenAI web search\nopenai_agent = Agent(\n    name=\"Research-Agent\",\n    instructions=\"You can search the web for information\",\n    model=\"gpt-4o\",\n    llm_provider=OPENAI,\n    enable_web_search=True\n)\n\n# Anthropic web search\nanthropic_agent = Agent(\n    name=\"Research-Agent\",\n    instructions=\"You can search the web for information\",\n    model=\"claude-sonnet-4-5\",\n    llm_provider=ANTHROPIC,\n    enable_web_search=True\n)\n\n# Gemini web search\ngemini_agent = Agent(\n    name=\"Research-Agent\",\n    instructions=\"You can search the web for information\",\n    model=\"gemini-1.5-pro\",\n    llm_provider=GEMINI,\n    enable_web_search=True\n)\n\nresult = Runner(openai_agent).run(\n    input=[{\"role\": \"user\", \"content\": \"What's the latest news about AI?\"}]\n)\n```\n\n### Tool Approvals\n\nImplement approval workflows for sensitive operations:\n\n```python\nfrom stark import Agent, Runner\n\ndef approve_file_deletion(tool_name: str, arguments: dict) -\u003e bool:\n    \"\"\"Approve file deletion operations\"\"\"\n    file_path = arguments.get(\"path\", \"\")\n    print(f\"Approve deletion of {file_path}? (y/n)\")\n    return input().lower() == 'y'\n\nasync def approve_api_call(tool_name: str, arguments: dict) -\u003e bool:\n    \"\"\"Async approval for API calls\"\"\"\n    print(f\"Approve API call to {tool_name}? (y/n)\")\n    return input().lower() == 'y'\n\nagent = Agent(\n    name=\"Controlled-Agent\",\n    instructions=\"You can perform file operations\",\n    model=\"claude-sonnet-4-5\",\n    function_tools=[file_tool],\n    approvals={\n        \"delete\": approve_file_deletion,  # Matches tool names containing \"delete\"\n        \"api_.*\": approve_api_call,       # Regex pattern for API tools\n    }\n)\n```\n\n### Input Filtering\n\nFilter or modify input before sending to the LLM:\n\n```python\nfrom stark import Agent, Runner\n\ndef filter_sensitive_data(messages: list) -\u003e list:\n    \"\"\"Remove sensitive information from messages\"\"\"\n    filtered = []\n    for msg in messages:\n        if msg.get(\"role\") == \"user\":\n            content = msg.get(\"content\", \"\")\n            # Remove credit card numbers, etc.\n            content = content.replace(\"1234-5678-9012-3456\", \"[REDACTED]\")\n            filtered.append({\"role\": msg[\"role\"], \"content\": content})\n        else:\n            filtered.append(msg)\n    return filtered\n\nagent = Agent(\n    name=\"Secure-Agent\",\n    instructions=\"You are a helpful assistant\",\n    model=\"claude-sonnet-4-5\",\n    model_input_hook=filter_sensitive_data\n)\n\nresult = Runner(agent).run(\n    input=[{\"role\": \"user\", \"content\": \"My card is 1234-5678-9012-3456\"}]\n)\n```\n\n## API Reference\n\n### Agent\n\nThe main agent class that defines the behavior and capabilities of your AI agent.\n\n```python\nAgent(\n    name: str,                                    # Agent name (required)\n    instructions: str,                            # System instructions/prompt (required)\n    model: str,                                   # LLM model to use (required)\n    description: str = \"\",                        # Agent description (required for sub-agents)\n    mcp_servers: Dict[str, Any] = [],            # MCP server configurations\n    function_tools: List[Callable] = [],         # Custom function tools or class instances\n    enable_web_search: bool = False,             # Enable web search capabilities\n    sub_agents: List[Agent] = [],                # Sub-agents for delegation\n    approvals: Dict[str, Callable] = None,       # Tool approval functions (regex patterns)\n    skills: List[str] = None,                    # List of paths to skill directories\n    skill_config: SkillConfig = None,            # Configuration for skill execution\n    model_input_hook: Callable = None,           # Function to modify input before LLM call\n    post_llm_hook: Callable = None,              # Function to modify response after LLM call\n    iteration_end_hook: Callable = None,         # Function to run at end of iteration (except the last iteration - Not useful for the agents with only 1 iteration)\n    parallel_tool_calls: bool = None,            # Enable parallel tool execution\n    thinking_level: str = None,                  # Reasoning effort: \"none\", \"low\", \"medium\", \"high\"\n    llm_provider: str = OPENAI,                  # LLM provider (OPENAI, ANTHROPIC, GEMINI)\n    max_iterations: int = 10,                    # Maximum iterations before stopping\n    max_output_tokens: int = None,               # Maximum tokens in response\n    trace_id: str = None                         # Trace ID for debugging\n)\n```\n\n### Runner\n\nExecutes agents and manages their lifecycle.\n\n#### Synchronous Execution\n\n```python\nrunner = Runner(agent)\nresult = runner.run(\n    input=[{\"role\": \"user\", \"content\": \"Hello\"}]\n)\n```\n\n#### Asynchronous Execution\n\n```python\nrunner = Runner(agent)\nresult = await runner.run_async(\n    input=[{\"role\": \"user\", \"content\": \"Hello\"}]\n)\n```\n\n#### Streaming Execution\n\n```python\nrunner = Runner(agent)\nasync for event in runner.run_stream(\n    input=[{\"role\": \"user\", \"content\": \"Hello\"}]\n):\n    # Handle events\n    pass\n```\n\n### SkillConfig\n\nConfiguration class for customizing skill execution behavior.\n\n```python\nfrom stark.type import SkillConfig\n\nskill_config = SkillConfig(\n    model: Optional[str] = None,              # Model to use for skill execution (defaults to agent's model)\n    llm_provider: Optional[str] = None,       # LLM provider for skills (defaults to agent's provider)\n    max_iterations: int = 100,                # Maximum iterations for skill execution\n    max_output_tokens: int = 64000,           # Maximum output tokens for skills\n    parallel_tool_calls: bool = True,         # Enable parallel tool calls in skills\n    thinking_level: Optional[str] = None,     # Reasoning level: \\\"none\\\", \\\"low\\\", \\\"medium\\\", \\\"high\\\"\n    enable_web_search: bool = False           # Enable web search for skills\n)\n```\n\n**Use Case**: When you want skills to use different models or have different execution parameters than the main agent.\n\n### RunContext\n\nThe response object returned by agent execution.\n\n```python\nclass RunContext:\n    messages: List[Dict[str, Any]]              # Complete conversation history\n    output: str                                 # Final output of the agent\n    iterations: int                             # Number of iterations executed\n    subagents_messages: Dict[str, List]         # Messages from all sub-agents (typically empty for Single Agent or Master Agent)\n    subagents_response: Dict[str, Any]          # Responses from all sub-agents (typically empty for Single Agent)\n    error: Optional[str]                        # Error message if execution failed\n    max_iterations_reached: bool                # Whether max iterations was hit\n    run_cost: float                             # Total cost of the run in USD\n```\n\n### Stream Events\n\nWhen using streaming, you'll receive different event types:\n\n**Runner Events:**\n- `Stream.ITER_START`: Iteration started (data: iteration number)\n- `Stream.TOOL_RESPONSE`: Tool response received (data: ToolCallResponse)\n- `Stream.ITER_END`: Iteration completed (data: IterationData)\n- `Stream.AGENT_RUN_END`: Agent execution finished (data: RunContext)\n\n**Provider Events (from LLM):**\n- `Stream.REASONING_CHUNK`: Reasoning/thinking content chunk (for models with thinking capability)\n- `Stream.CONTENT_CHUNK`: Content chunk received (data: string)\n- `Stream.TOOL_CALLS`: Tool calls made (data: list of tool calls)\n- `Stream.MODEL_STREAM_COMPLETED`: Provider streaming completed (data: ProviderResponse)\n\n### Utility Classes\n\n#### Util\n\nHelper utilities for common operations:\n\n```python\nfrom stark import Util\n\n# 1. Parse JSON from LLM responses (handles markdown code blocks)\ndata = Util.load_json('```json\\n{\"key\": \"value\"}\\n```')\n# Returns: {\"key\": \"value\"}\n\n# 2. Create partial functions with pre-filled arguments\nfrom functools import partial\n\ndef my_approval_func(tool_name: str, args: dict, user_id: int):\n    print(f\"User {user_id}: Approve {tool_name}?\")\n    return True\n\n# Pass function with pre-filled user_id\napproval_with_user = Util.pass_function_with_args(my_approval_func, user_id=123)\n# Now approval_with_user only needs tool_name and args\n```\n\n#### RunnerStream\n\nHelper methods for working with stream events:\n\n```python\nfrom stark import RunnerStream\n\n# Create stream events\nevent = RunnerStream.iteration_start(1)\nevent = RunnerStream.tool_response(tool_response)\nevent = RunnerStream.iteration_end(iteration_data)\nevent = RunnerStream.agent_run_end(run_response)\n\n# Dump event data to string\ndata_str = RunnerStream.data_dump(event)\n```\n\n## MCP Server Configuration\n\nMCP servers extend agent capabilities by providing additional tools and resources.\n\n### Stdio-based MCP Server\n\n```python\nmcp_servers = {\n    \"server-name\": {\n        \"command\": \"uvx\",              # Command to run\n        \"args\": [\"mcp-server-package\"], # Arguments\n        \"env\": {                        # Environment variables\n            \"API_KEY\": \"your-key\"\n        }\n    }\n}\n```\n\n### Multiple MCP Servers\n\n```python\nmcp_servers = {\n    \"jira\": {\n        \"command\": \"uvx\",\n        \"args\": [\"mcp-atlassian\"],\n        \"env\": {\n            \"JIRA_URL\": os.environ.get(\"JIRA_URL\"),\n            \"JIRA_USERNAME\": os.environ.get(\"JIRA_EMAIL\"),\n            \"JIRA_API_TOKEN\": os.environ.get(\"JIRA_TOKEN\")\n        }\n    },\n    \"slack\": {\n        \"command\": \"uvx\",\n        \"args\": [\"mcp-slack\"],\n        \"env\": {\n            \"SLACK_BOT_TOKEN\": os.environ.get(\"SLACK_BOT_TOKEN\")\n        }\n    }\n}\n```\n\n## Function Tools\n\n### Using the `@stark_tool` Decorator\n\nThe `@stark_tool` decorator automatically generates JSON schemas from Python type hints:\n\n```python\nfrom stark import stark_tool\nfrom typing import List\n\n@stark_tool\ndef my_tool(\n    query: str,                    # Required parameter\n    limit: int = 10,               # Optional with default\n    tags: List[str] = None,        # Optional list\n    include_metadata: bool = False # Optional boolean\n) -\u003e str:\n    \"\"\"\n    Description of what the tool does.\n    This docstring becomes the tool description.\n    \"\"\"\n    # Your implementation\n    return \"result\"\n```\n\n**Supported Types:**\n- `str` → string\n- `int` → integer\n- `float` → number\n- `bool` → boolean\n- `dict` → object\n- `List[T]` → array with items of type T\n\n### Class-Based Tools\n\nOrganize related tools into classes:\n\n```python\nfrom stark import stark_tool\n\nclass MyTools:\n    def __init__(self, config):\n        self.config = config\n    \n    @stark_tool\n    def tool_one(self, param: str) -\u003e str:\n        \"\"\"First tool description\"\"\"\n        return f\"Result: {param}\"\n    \n    @stark_tool\n    def tool_two(self, value: int) -\u003e str:\n        \"\"\"Second tool description\"\"\"\n        return f\"Value: {value}\"\n\n# Use the class instance\ntools = MyTools(config=\"my_config\")\nagent = Agent(\n    name=\"Agent\",\n    instructions=\"Instructions\",\n    model=\"claude-sonnet-4-5\",\n    function_tools=[tools]\n)\n```\n\n### Built-in CodeTool\n\nThe `CodeTool` class provides comprehensive file and shell operations:\n\n```python\nfrom stark.tools import CodeTool\n\ncode_tool = CodeTool(workspace_dir=\"./project\")\n\n# Available methods:\n# - read(path, encoding='utf-8')\n# - write(path, content, create_dirs=True)\n# - update(path, search, replace, count=-1)\n# - delete(path, recursive=False)\n# - create_directory(path, parents=True)\n# - list_directory(path=\".\", pattern=\"*\", recursive=False)\n# - move(source, destination)\n# - copy(source, destination, recursive=True)\n# - shell_exec(cmd, dir_path=None, timeout=30)\n```\n\n## Advanced Usage\n\n### LLM Providers\n\n```python\nfrom stark import Agent, Runner\nfrom stark.llm_providers import OPENAI, ANTHROPIC, GEMINI\n\n# OpenAI\nopenai_agent = Agent(\n    name=\"OpenAI-Agent\",\n    instructions=\"You are a helpful assistant\",\n    model=\"gpt-4o\",\n    llm_provider=OPENAI\n)\n\n# Anthropic\nanthropic_agent = Agent(\n    name=\"Anthropic-Agent\",\n    instructions=\"You are a helpful assistant\",\n    model=\"claude-sonnet-4-5\",\n    llm_provider=ANTHROPIC\n)\n\n# Gemini\ngemini_agent = Agent(\n    name=\"Gemini-Agent\",\n    instructions=\"You are a helpful assistant\",\n    model=\"gemini-1.5-pro\",\n    llm_provider=GEMINI\n)\n```\n\n### Parallel Tool Calls\n\nEnable parallel execution of multiple tools:\n\n```python\nagent = Agent(\n    name=\"Parallel-Agent\",\n    instructions=\"You can call multiple tools in parallel\",\n    model=\"claude-sonnet-4-5\",\n    parallel_tool_calls=True,\n    function_tools=[tool1, tool2, tool3]\n)\n```\n\n### Iteration Control\n\n```python\nagent = Agent(\n    name=\"Controlled-Agent\",\n    instructions=\"You are a helpful assistant\",\n    model=\"claude-sonnet-4-5\",\n    max_iterations=5  # Limit to 5 iterations\n)\n\nresult = Runner(agent).run(input=[{\"role\": \"user\", \"content\": \"Hello\"}])\n\nif result.max_iterations_reached:\n    print(\"Warning: Agent reached maximum iterations!\")\n```\n\n### Token Limits\n\nControl the maximum output tokens:\n\n```python\nagent = Agent(\n    name=\"Limited-Agent\",\n    instructions=\"You are a helpful assistant\",\n    model=\"claude-sonnet-4-5\",\n    max_output_tokens=1000  # Limit response to 1000 tokens\n)\n```\n\n### Tracing and Debugging\n\nUse trace IDs to track agent execution:\n\n```python\nimport uuid\n\nagent = Agent(\n    name=\"Traced-Agent\",\n    instructions=\"You are a helpful assistant\",\n    model=\"claude-sonnet-4-5\",\n    trace_id=str(uuid.uuid4())\n)\n\nresult = Runner(agent).run(input=[{\"role\": \"user\", \"content\": \"Hello\"}])\nprint(f\"Trace ID: {agent.get_trace_id()}\")\n```\n\n### Tool Naming Conventions\n\nStark automatically prefixes tool names to avoid conflicts and identify tool types:\n\n| Tool Type | Prefix | Example |\n|-----------|--------|---------|\n| Function Tools | `st___` | `st___search_database` |\n| Class-Based Tools | `ClassName___` | `DatabaseTools___search` |\n| Sub-Agents | `sub_agent__` | `sub_agent__Delivery-Agent` |\n| Skills | `skill___` | `skill___python_expert` |\n| MCP Tools | (no prefix) | `slack_send_message` |\n\nThese prefixes are handled internally and you don't need to use them when defining tools. The agent automatically recognizes and routes tool calls to the appropriate handler.\n\n### Logger\n\nStark includes a built-in logger for debugging:\n\n```python\nfrom stark import logger\n\n# Use the logger in your code\nlogger.debug(\"Debug message\")\nlogger.info(\"Info message\")\nlogger.warning(\"Warning message\")\nlogger.error(\"Error message\")\n\n# The logger includes file name and line numbers automatically\n# Output format: YYYY-MM-DD HH:MM:SS - LEVEL - message (filename.py:123)\n```\n\nThe logger is pre-configured with a StreamHandler and outputs to console with timestamps and source location.\n\n## Best Practices\n\n1. **Clear Instructions**: Provide clear, specific instructions to guide agent behavior\n2. **Tool Descriptions**: Write detailed descriptions for function tools and sub-agents\n3. **Error Handling**: Always wrap agent execution in try-except blocks\n4. **Iteration Limits**: Set appropriate `max_iterations` to prevent infinite loops\n5. **Resource Cleanup**: MCP server connections are automatically cleaned up\n6. **Streaming**: Use streaming for long-running tasks to provide real-time feedback\n7. **Sub-Agent Descriptions**: Always provide descriptions for sub-agents so the parent agent knows when to use them\n8. **Type Hints**: Use type hints with `@stark_tool` for automatic schema generation\n9. **Approvals**: Implement approval workflows for sensitive operations\n10. **Input Filtering**: Use input filters to sanitize or modify data before LLM processing\n\n## Error Handling\n\n```python\nfrom stark import Agent, Runner\n\ntry:\n    agent = Agent(\n        name=\"Error-Handling-Agent\",\n        instructions=\"You are a helpful assistant\",\n        model=\"claude-sonnet-4-5\"\n    )\n    \n    result = Runner(agent).run(\n        input=[{\"role\": \"user\", \"content\": \"Hello\"}]\n    )\n    \n    if result.max_iterations_reached:\n        print(\"Warning: Maximum iterations reached\")\n    \nexcept Exception as e:\n    print(f\"Error: {e}\")\n    # Handle error appropriately\n```\n\n## Examples\n\nCheck out the `examples/` directory for more comprehensive examples:\n\n- Basic agent usage\n- MCP server integration\n- Function tools and class-based tools\n- Hierarchical sub-agents\n- Streaming responses\n- Web search integration\n- Tool approvals and input filtering\n\n## Requirements\n\n- Python 3.10 or higher\n- Dependencies are automatically installed with the package\n\n## Contributing\n\nContributions are welcome! Please feel free to submit issues and pull requests.\n\n## License\n\nSee LICENSE file for details.\n\n## Support\n\nFor issues and questions, please open an issue on the GitHub repository.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdev-aliraza%2Fstark-agents","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdev-aliraza%2Fstark-agents","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdev-aliraza%2Fstark-agents/lists"}