Dual API: Sync & Async

AA Kit now provides both synchronous and asynchronous APIs, making it incredibly easy to get started while still providing full async capabilities when you need them.

New in v2.0

No more asyncio.run() boilerplate! Just use the synchronous methods for simple use cases.

  • Synchronous methods work out of the box
  • Async methods available with 'a' prefix when needed
  • Same functionality, different calling styles
  • Zero breaking changes - existing code still works

Method Comparison

FeatureSynchronous APIAsynchronous API
Simple chatagent.chat()await agent.achat()
Streamingfor chunk in agent.stream_chat()async for chunk in agent.astream_chat()
Add toolagent.add_tool()await agent.aadd_tool()
Remove toolagent.remove_tool()await agent.aremove_tool()
Clear memoryagent.clear_memory()await agent.aclear_memory()

Examples

Simple Synchronous Usage

Perfect for scripts, notebooks, and simple applications

from aakit import Agent

# Create an agent
agent = Agent(
    name="assistant",
    instruction="You are a helpful assistant",
    model="gpt-4"
)

# Chat synchronously - no async/await needed!
response = agent.chat("Hello! How are you?")
print(response)

# Stream responses synchronously
for chunk in agent.stream_chat("Tell me a story"):
    print(chunk, end='', flush=True)

Asynchronous Usage

When you need concurrent operations or are in an async context

import asyncio
from aakit import Agent

async def main():
    agent = Agent(
        name="assistant",
        instruction="You are a helpful assistant",
        model="gpt-4"
    )
    
    # Use async methods with 'a' prefix
    response = await agent.achat("Hello! How are you?")
    print(response)
    
    # Async streaming
    async for chunk in agent.astream_chat("Tell me a story"):
        print(chunk, end='', flush=True)

asyncio.run(main())

Tool Management

Add and remove tools without async complexity

# Synchronous tool management
def calculate(expression: str) -> str:
    return f"Result: {eval(expression)}"

agent = Agent("calc", "Math assistant", "gpt-4")

# Add tool synchronously
agent.add_tool(calculate)

# Use it
response = agent.chat("What is 25 * 4?")

# Remove tool synchronously
agent.remove_tool("calculate")

Memory Operations

Manage agent memory simply

# Agent with memory
agent = Agent(
    name="memory_agent",
    instruction="You remember our conversations",
    model="gpt-4",
    memory="memory://"
)

# Chat with memory
response = agent.chat("My name is Alice")
response = agent.chat("What's my name?")  # Will remember!

# Clear memory synchronously
agent.clear_memory()

Mixed Usage Pattern

Use sync and async in the same application

from aakit import Agent
import asyncio

agent = Agent("assistant", "You are helpful", "gpt-4")

# Synchronous for simple operations
quick_response = agent.chat("Hello!")

# Async for concurrent operations
async def handle_multiple_requests():
    tasks = [
        agent.achat("Question 1"),
        agent.achat("Question 2"),
        agent.achat("Question 3")
    ]
    responses = await asyncio.gather(*tasks)
    return responses

# Run async when needed
responses = asyncio.run(handle_multiple_requests())

When to Use Which API?

Use Synchronous API When:

  • Writing simple scripts or notebooks
  • Building CLI tools or utilities
  • Prototyping and experimentation
  • Sequential operations are sufficient
  • You want minimal code complexity

Use Asynchronous API When:

  • Building web applications (FastAPI, etc.)
  • Handling multiple agents concurrently
  • Integrating with async frameworks
  • Optimizing for high throughput
  • Managing long-running operations

Migration Guide

Existing Code Still Works!

The async API hasn't changed. If you have existing async code, it will continue to work exactly as before. The new sync API is purely additive.

# Old code still works
async def main():
    response = await agent.chat("Hello")  # Still works!
    
# But now you can also do
response = agent.chat("Hello")  # New sync API!