Skip to main content

A modular sus-adk for LLM interaction via cookies, inspired by LangChain and Google-ADK.

Project description

sus-adk

A modular, extensible framework for interacting with LLM providers using cookies for authentication/session management. Inspired by LangChain and Google-ADK.

Features

  • Modular agent, provider, session, and tool abstractions
  • Integrates with any LLM provider using a single GenericProvider
  • Cookie/session-based authentication (manual or automatic via browser, with headless and browser selection)
  • Chaining and workflow support for multi-step agentic tasks
  • Tool support: register, validate, and invoke custom tools/functions
  • LLM-driven tool selection: agent can parse LLM output to invoke tools
  • Multi-step agentic loop: alternate between LLM and tool calls, inject tool results
  • OpenAI function-calling compatibility: generate OpenAI-compatible function specs from tools
  • Memory support: store and retrieve conversational/workflow state
  • Context window management: limit context passed to LLMs
  • Error recovery: handle and log tool/LLM errors
  • Vector store memory: semantic retrieval of relevant knowledge
  • Streaming: stream LLM/tool responses to the user
  • Integration hooks: connect to external systems (webhooks, APIs, databases)
  • Async support: async run/stream methods for scalable applications
  • Distributed API: FastAPI REST API for multi-agent and remote use
  • UI integration: Streamlit web UI for interactive demos
  • Cloud deployment: Docker/cloud-ready
  • Automatic browser-based cookie fetching (headless, Chrome/Firefox/Edge)
  • Extensible for plugins and custom providers
  • Fully tested and production-ready

Installation

Install via pip:

pip install agentic-framework

Or, for local development:

pip install .

Automatic Cookie Fetching via Browser (Headless & Browser Selection)

If you don't have cookies, the agent can fetch them for you using a browser. You can choose the browser and headless mode:

from agentic_framework import Agent
from agentic_framework.providers import GenericProvider

provider = GenericProvider("https://llm-provider.com/api/generate")
url = "https://llm-provider.com/login"  # Replace with your provider's login URL

# Use headless Firefox for cookie fetching
agent = Agent(provider, url_for_cookies=url, cookie_wait_time=60, browser='firefox', headless=True)

result = agent.run("Hello, world!")
print("LLM response:", result)

Supported browsers: 'chrome', 'firefox', 'edge'. Set headless=False to see the browser window.

Usage

Basic Example

from agentic_framework import Agent, Session
from agentic_framework.providers import GenericProvider

session = Session({"sessionid": "your-session-id"})
api_url = "https://llm-provider.com/api/generate"  # Replace with your provider's endpoint
provider = GenericProvider(api_url)
agent = Agent(provider, session)
result = agent.run("Hello, world!")
print(result)

Chaining

from agentic_framework import Chain

chain = Chain([
    lambda x: agent.run(f"Summarize: {x}"),
    lambda x: agent.run(f"Translate to French: {x}")
])

output = chain.run("The quick brown fox jumps over the lazy dog.")
print(output)

Session Management

from agentic_framework import Session

session = Session()
session.set_cookie('sessionid', 'abc123')
print(session.get_cookie('sessionid'))
print(session.as_dict())

Tool Support & LLM-Driven Tool Selection

Define, register, and use tools (custom Python functions) with argument schema validation. The agent can also parse LLM output to invoke tools automatically.

from agentic_framework import Agent, Session, Tool
from agentic_framework.providers import GenericProvider

def add(a, b):
    return a + b

add_tool = Tool(
    name="add",
    description="Add two numbers",
    func=add,
    arg_schema={"a": int, "b": int}
)

provider = GenericProvider("https://fake-llm.com/api/generate")
session = Session()
agent = Agent(provider, session)
agent.register_tool(add_tool)

# Direct tool call
result = agent.call_tool("add", a=2, b=3)
print(result)  # Output: 5

# LLM-driven tool selection (simulate LLM output)
class DummyProvider(GenericProvider):
    def generate(self, prompt, session, **kwargs):
        return 'TOOL: add {"a": 2, "b": 3}'

agent.provider = DummyProvider("")
result = agent.run_with_tools("What is 2 + 3?")
print(result)  # Output: 5

Tool Listing

You can list all registered tools and their descriptions:

for tool in agent.tools.values():
    print(f"{tool.name}: {tool.description}")

Multi-Step Agentic Loop (LLM/Tool Alternation)

from agentic_framework import Agent, Session, Tool
from agentic_framework.providers import GenericProvider

add_tool = Tool(
    name="add",
    description="Add two numbers",
    func=lambda a, b: a + b,
    arg_schema={"a": int, "b": int}
)

class DummyProvider(GenericProvider):
    def __init__(self, responses):
        super().__init__("")
        self.responses = responses
        self.call_count = 0
    def generate(self, prompt, session, **kwargs):
        resp = self.responses[self.call_count]
        self.call_count += 1
        return resp

responses = [
    'TOOL: add {"a": 2, "b": 3}',
    'The answer is 5.'
]

provider = DummyProvider(responses)
session = Session()
agent = Agent(provider, session)
agent.register_tool(add_tool)

result = agent.run_agentic_loop("What is 2 + 3?")
print("Final result:", result)  # Output: The answer is 5.

OpenAI Function-Calling Compatibility

You can generate OpenAI-compatible function specs from tools for use with OpenAI's function-calling API:

from agentic_framework import Tool

def add(a: int, b: int) -> int:
    return a + b

tool = Tool(
    name="add",
    description="Add two numbers",
    func=add,
    arg_schema={"a": int, "b": int}
)

spec = tool.openai_function_spec()
print(spec)

Memory, Context Window, and Error Recovery

from agentic_framework import Agent, Session, Memory
from agentic_framework.providers import GenericProvider

# Dummy provider that echoes context and can raise errors
def error_provider_generate(prompt, session, context=None, **kwargs):
    if "fail" in prompt:
        raise RuntimeError("Simulated LLM failure")
    return f"Prompt: {prompt} | Context: {context}"

class ErrorProvider(GenericProvider):
    def generate(self, prompt, session, context=None, **kwargs):
        return error_provider_generate(prompt, session, context, **kwargs)

memory = Memory()
session = Session()
provider = ErrorProvider("")
agent = Agent(provider, session, memory=memory, context_window=2)

# Add some messages to memory
agent.run("First message")
agent.run("Second message")
agent.run("Third message")

# The context window should only include the last 2 messages
print("Context window:", memory.get_messages(2))

# Simulate LLM error
result = agent.run("fail now")
print("Error recovery result:", result)
print("Memory after error:", memory.get_messages())

Vector Memory & Semantic Retrieval

from agentic_framework import Agent, Session, VectorMemory
from agentic_framework.providers import GenericProvider

class PrintContextProvider(GenericProvider):
    def generate(self, prompt, session, context=None, **kwargs):
        return f"Prompt: {prompt} | Context: {context}"

vector_memory = VectorMemory()
session = Session()
provider = PrintContextProvider("")
agent = Agent(provider, session, vector_memory=vector_memory, context_window=2)

agent.add_to_vector_memory("The Eiffel Tower is in Paris.")
agent.add_to_vector_memory("The capital of France is Paris.")
agent.add_to_vector_memory("Mount Everest is the tallest mountain.")

result = agent.run("Where is the Eiffel Tower?", use_semantic_context=True)
print("Result with semantic context:", result)

Streaming

from agentic_framework import Agent, Session
from agentic_framework.providers import GenericProvider

class StreamingProvider(GenericProvider):
    def stream_generate(self, prompt, session, context=None, **kwargs):
        for word in (prompt + " streamed!").split():
            yield word

provider = StreamingProvider("")
session = Session()
agent = Agent(provider, session)

for chunk in agent.stream_run("Hello world"):
    print(chunk)

Integration Hooks

from agentic_framework import Agent, Session
from agentic_framework.providers import GenericProvider

def fake_webhook(data):
    return f"Webhook received: {data}"

provider = GenericProvider("")
session = Session()
agent = Agent(provider, session)

agent.register_integration("webhook", fake_webhook)
result = agent.call_integration("webhook", {"event": "test", "value": 42})
print("Integration result:", result)

Async Usage

import asyncio
from agentic_framework import Agent, Session
from agentic_framework.providers import GenericProvider

class AsyncProvider(GenericProvider):
    async def async_generate(self, prompt, session, context=None, **kwargs):
        await asyncio.sleep(0.1)
        return f"Async response: {prompt} | Context: {context}"

async def main():
    provider = AsyncProvider("")
    session = Session()
    agent = Agent(provider, session)
    result = await agent.async_run("Hello async!")
    print("Async run result:", result)

if __name__ == "__main__":
    asyncio.run(main())

Distributed API (FastAPI)

Run the REST API:

uvicorn backend.api:app --reload
  • POST /run — Run agent on a prompt
  • POST /stream — Stream agent response
  • POST /tool — Call a tool
  • POST /integration — Call an integration
  • GET /memory — Get memory state

UI Integration (Streamlit)

Run the web UI:

streamlit run backend/ui_app.py

Cloud Deployment

You can deploy with Docker or any cloud service that supports FastAPI/Streamlit. Example Dockerfile:

FROM python:3.9
WORKDIR /app
COPY backend/ .
RUN pip install -r requirements.txt
CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8000"]

Testing

All tests are in backend/tests/. To run:

python -m unittest discover backend/tests

Extending

To support custom request/response handling, subclass BaseProvider and implement generate:

from agentic_framework.provider import BaseProvider
from agentic_framework.session import Session

class MyCustomProvider(BaseProvider):
    def __init__(self, api_url):
        self.api_url = api_url
    def generate(self, prompt: str, session: Session, **kwargs):
        # Custom logic here
        pass

Examples

See backend/examples/ for example scripts.

License

MIT

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

sus_adk-0.1.0.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

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

sus_adk-0.1.0-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file sus_adk-0.1.0.tar.gz.

File metadata

  • Download URL: sus_adk-0.1.0.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for sus_adk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c99453fd4807c7eff28b31ae66e32ecb5182201cd071a15e8ca3cc1f710622e7
MD5 ea8c6b12889955e758854f492161d089
BLAKE2b-256 027664421c87c473ad333d7f37e7870846f5782176a7762e2ef0d1dbebfb1c0c

See more details on using hashes here.

File details

Details for the file sus_adk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sus_adk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for sus_adk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8d2e1449b8a15e4d2cb1a7bb19ae2c963711e1e29ebb6c1528e5d700d96b3c6a
MD5 ffc57d45f7ad5d6e035ab4f3ade5d7ba
BLAKE2b-256 1cdfe0566f8f64c672c210eca8f9fe011f71c56dbd041d6de96a843e1e4bd878

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