Skip to main content

Pluggable LLM/AI Agent library

Project description

Sweet Agent

This is not another Agent Framework. It is a library that gives you only the basic you need to build or transform your current codebase in agents.

Why we build it? Most agent frameworks around there don't integrate all the actors of a real world case usage. These actors are the developer/admin, the LLMs, the system/product and the user.

These frameworks let you start an agent which will do a task and return you a result. But what most people really wants is the ability to chat with an llm which can understand their need at some point and call the appropriate tool.

MCP came in and fixed this. But the LLM has to support it.

Sweet Agent gives you the following features:

  • Support for LLM trained without tools use.
  • Transparent tools use for different LLM
  • Native support of human in the loop
  • Easy class to agent transformation
  • Tools as method
  • Agent collaboration
  • Multiple api keys support
  • Short term memory
  • Long term memory
  • Easy prompt customization
  • Integrations: django-channels

Sweet Agent gives you those primitives—nothing more, nothing less—so you can integrate them into your architecture.


Why choose Sweet Agent?

Feature Sweet Agent Typical frameworks
Any LLM (native tools or none) Often limited
Human‑in‑the‑loop prompts at every step Optional / hard
Class‑to‑agent in one line
Tools = plain Python functions or other agents Partial
API‑key rotation built in
Plug‑and‑play I/O layers (console, Django Channels, …) Rare
Memory backends swappable Often single choice

Installation

# From PyPI
pip install sweetagent

# Or from source
pip install git+https://github.com/jefcolbi/sweetagent.git

Sweet Agent requires Python ⩾ 3.8.


Quick start

Below is the smallest useful agent: it exposes one tool (get_weather) and answers a user in the console.

from sweetagent.io.base import ConsoleStaIO
from sweetagent.llm_client import LLMClient
from sweetagent.short_term_memory.session import SessionMemory
from sweetagent.llm_agent import LLMAgent


class WeatherAgent(LLMAgent):
    """Return current weather for a city (demo)."""

    def get_weather(self, city: str = None):
        # <-- Real code would query a weather API
        return "cloudy"

    def configure_tools(self):
        # Turn the method into an LLM‑callable tool
        self.register_function_as_tool(self.get_weather)


if __name__ == "__main__":
    stdio = ConsoleStaIO("weather")
    client = LLMClient(
        provider="openai",
        model="gpt-4o",
        api_keys_rotator=["sk‑...", "sk‑backup‑..."],
        stdio=stdio,
    )

    agent = WeatherAgent(
        name="Weather Agent",
        role="Return the weather of cities",
        llm_client=client,
        short_term_memory=SessionMemory(),
        stdio=stdio,
    )

    answer = agent.run("What is the weather in Douala?")
    print(answer)

Run it:

python examples/weather_agent.py

Agent collaboration

Agents can register other agents as tools. The Assistant below delegates weather questions to the WeatherAgent above while chatting freely with the user.

from sweetagent.core import WorkMode
from examples.weather_agent import WeatherAgent  # see previous snippet

class Assistant(LLMAgent):
    """General‑purpose helper that can invoke WeatherAgent."""
    pass

# wire‑up
assistant = Assistant(
    "Assistant",
    "chat with user and help as much as you can",
    client,
    short_term_memory=SessionMemory(),
    stdio=stdio,
    work_mode=WorkMode.CHAT,
)
assistant.register_agent_as_tool(weather_agent)

assistant.run("Hi!")

See test_agent.py for a full example. citeturn1file1


Prompt Engine

Sweet Agent ships a strict response‑format contract so your UI and downstream code never guess what the LLM meant.

  • Sections are marked with +++ section +++ fences.
  • YAML blocks can carry structured data (choices, tables, …).
  • A built‑in parser turns the raw reply into a FormatResponseModel.
+++ kind +++        # message | tool_call | final_answer
+++ message +++     # free text (optional)
+++ data +++        # YAML (optional)
+++ tool_name +++   # when kind == tool_call
+++ tool_arguments +++
~~~ field ~~~       # arguments in their own fences
value

+++ end +++         # terminator (mandatory)

PromptEngine handles:

  • building the initial system prompt with examples and tool JSON
  • decoding every LLM response (see test_prompting.py). citeturn1file0

You can subclass it or plug your own templating engine—just return a markdown string.


Memory

Short‑term

Implement BaseShortTermMemory to implement a short term memory strategy.

SessionMemory keeps the last messages in RAM for the current execution.

Long‑term (pluggable)


Key rotation & retries

Provide one or many API keys. LLMClient cycles through them on RateLimitError:

client = LLMClient("openai", "gpt-4o", ["k1", "k2", "k3"], stdio=stdio)

If all keys fail you get the last captured exception.


Human‑in‑the‑loop

Because every model prompt can return kind = message, the agent pauses and calls StaIO.user_input_text()—letting a human decide before the loop continues.

Implement custom BaseStaIO subclasses to:

  • stream to a React frontend
  • post to Slack
  • collect feedback for RLHF

Django Channels integration

For real‑time websockets drop this into your consumers.py (excerpt from the demo project):

class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.accept()

        self.agent: LLMAgent = None
        self.queue: Queue = Queue(maxsize=1)
        self.stdio = ChannelWebsocketStaIO('', self, self.queue)
        self.thread: Thread = None

    def configure_agent(self, initial_message: str) -> LLMAgent:
        """Configure the main agent and run it with the initial message"""
        client = LLMClient(settings.LLM_PROVIDER, settings.LLM_MODEL, settings.OPENAI_API_KEYS,
                           stdio=self.stdio)
        weather_agent = WeatherAgent("Weather Agent", "return the weather of cities", client,
                                     short_term_memory=SessionMemory(), stdio=self.stdio)
        assistant = Assistant("Assistant", "chat with user and help him as much as you can", client,
                              short_term_memory=SessionMemory(), stdio=self.stdio, work_mode=WorkMode.CHAT)
        assistant.register_agent_as_tool(weather_agent)

        self.agent = assistant
        self.agent.run(initial_message)

    def disconnect(self, close_code):
        pass

    def receive(self, text_data):
        self.stdio.log_debug(f"{text_data = }")
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]

        if self.agent:
            self.stdio.log_debug("Putting message in the queue")
            self.queue.put(message)
        else:
            self.thread = Thread(target=self.configure_agent, args=[message])
            self.thread.setDaemon(True)
            self.thread.setName("Assistant Agent Thread")
            self.thread.start()

The full example lives in consumers.py. citeturn1file2


Environment variables

Variable Default Description
LLM_PROVIDER openai Provider identifier used by litellm
LLM_MODEL gpt-4o Model name (or anthropic/claude‑...)
OPENAI_API_KEYS Comma‑separated list of keys for rotation

Set them in .env and load with python‑decouple:

OPENAI_API_KEYS=sk‑primary,sk‑backup
LLM_PROVIDER=openai
LLM_MODEL=gpt-4o

Running the test suite

python -m unittest tests

The tests exercise:

  • prompt encoding/decoding (test_prompting.py)
  • agent collaboration and tool calls (test_agent.py)

Roadmap

  • Async I/O & streaming partial tokens
  • Built‑in Redis + SQLite memory backends

License

Sweet Agent is released under the MIT License. See LICENSE for the full text.

SweetAgent is developed under Connectivo AB.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sweetagent-0.1.8.tar.gz (432.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sweetagent-0.1.8-py3-none-any.whl (27.1 kB view details)

Uploaded Python 3

File details

Details for the file sweetagent-0.1.8.tar.gz.

File metadata

  • Download URL: sweetagent-0.1.8.tar.gz
  • Upload date:
  • Size: 432.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for sweetagent-0.1.8.tar.gz
Algorithm Hash digest
SHA256 8214f58782876960f6b19843d1be1839ef6968c9e8f69feb868064c5c723e7b4
MD5 a234a16839755077a6e373b75b41fa84
BLAKE2b-256 0b6cde529b482c4f3e80bd0d4b30faf01706dee106ded527280626502f201903

See more details on using hashes here.

File details

Details for the file sweetagent-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: sweetagent-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 27.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for sweetagent-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 b69f41e1fbb6820cc1c28675a13ba7001fb837918bb99f648f6cb067644aafb8
MD5 13208cbd7db6fd09807cd3edf182725b
BLAKE2b-256 16eb1983c1ffeed859cee5670ef31765ae68c5165177f8dca1b98c69cdf2f2c8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page