Skip to main content

GenAI Agent Protocol

GenAI Agent Protocol is an async‑first Python framework for building WebSocket‑based AI agents that let you:

  • Connect an agent to the GenAI.works ecosystem
  • Process messages via registered handler functions
  • Upload and retrieve files with contextual metadata (agent_context)
  • Log messages with contextual metadata (agent_context)

✨ Features

🧠 Agent Binding: Decorator-based agent registration
🪝 WebSocket Communication: Bidirectional messaging with a central server
📁 File Manager: Async file upload/download & metadata fetch
🪵 Context Logger: Structured, contextual WebSocket-based logging
🔎 OpenAI Schema Conversion: Automatically converts Pydantic-type function signatures to OpenAI-compatible schemas
📞 Agent‑to‑agent calls: invoke another registered agent from within your handler

📚 Core Concepts

⚙️ Environment Variables Setup

Before you run the GenAI Agent Protocol, make sure to configure the necessary environment variables.

You can do this by creating a .env file in your project root or exporting them directly in your terminal session.

Required:

AGENT_JWT_TOKEN="<your JWT token from GenAI CLI or UI>"

Defaults (you can override if needed):

ROUTER_WS_URL=ws://localhost:8080/ws           # WebSocket router URL
BACKEND_API_BASE_URL=http://localhost:8000     # Backend API URL
IS_LOCAL_SETUP=true                            # Flag to indicate local development

If your agent logic requires additional environment variables, just add them to the .env file or terminal session the same way.

GenAISession

A central controller that registers agents and manages the event lifecycle.

from genai_session.session import GenAISession

genai_session = GenAISession()

@bind(...)

Registers a handler function with the session and make them visible to GenAI infrastructure.

from genai_session.session import GenAISession
from genai_session.utils.context import GenAIContext

genai_session = GenAISession()

@genai_session.bind(name="test_name", description="Test Description")
async def message_handler(agent_context: GenAIContext, parameter: str) -> str:
    ...

GenAIContext

Provides contextual info (agent_uuid, request_id, etc.), a logger, and access to the FileManager.

from genai_session.session import GenAISession
from genai_session.utils.context import GenAIContext

genai_session = GenAISession()

@genai_session.bind(name="test_name", description="Test Description")
async def message_handler(agent_context: GenAIContext, parameter: str) -> str:
    request_id = agent_context.request_id

Files

Handles file uploads (save) and retrievals (get_by_id, get_metadata_by_id).

from genai_session.session import GenAISession
from genai_session.utils.context import GenAIContext

genai_session = GenAISession()

@genai_session.bind(name="txt_content_reader_agent", description="Agent returns txt file content")
async def get_file_content(agent_context: GenAIContext, file_id: str) -> str:
    file = await agent_context.files.get_by_id(file_id)
    file_metadata = await agent_context.files.get_metadata_by_id(file_id)
    ...

Logger

Sends JSON logs through WebSocket with severity levels (debug, info, warning, error, critical).

from genai_session.session import GenAISession
from genai_session.utils.context import GenAIContext

genai_session = GenAISession()

@genai_session.bind()
async def reverse_name(agent_context: GenAIContext, name: str) -> str:
    """Agent reverses the name"""
    agent_context.logger.info("Inside the reverse_name function")
    agent_context.logger.debug(f"name: {name}")
    ...

Invoke Agent from Agent

You can invoke another agent from within an agent using the genai_session.send method (this method is working ONLY in IS_LOCAL_SETUP=true).
This method takes the agent_uuid and params as arguments.

from genai_session.session import GenAISession
from genai_session.utils.context import GenAIContext
from genai_session.utils.agents import AgentResponse

genai_session = GenAISession()

@genai_session.bind()
async def invoke_another_agent(agent_context: GenAIContext, name: dict) -> str:
    """Agent invokes another registered agent"""
    agent_response: AgentResponse = await genai_session.send(
        agent_uuid="agent_uuid", # you can get UUID from - await agent_context.get_agents()
        params={
            "username": name,
            "interests": ["python", "genai"],
            "age": 30,
        } # key is a parameter name, value is the value you want to pass
    )
    response = agent_response.response
    is_success = agent_response.is_success
    ...

External environment variables example

import asyncio
import os
from typing import Any, Annotated

import requests

from genai_session.session import GenAISession

session = GenAISession()

BASE_URL = os.environ.get("BASE_WEATHER_API_URL")
API_KEY = os.environ.get("WEATHER_API_KEY")

@session.bind(name="get_weather_agent", description="Get weather forecast data")
async def get_weather(
        agent_context, city_name: Annotated[str, "City name to get weather forecast for"],
        date: Annotated[str, "Date to get forecast for in yyyy-MM-dd format"]
) -> dict[str, Any]:

    agent_context.logger.info("Inside get_translation")
    params = {"q": city_name, "dt": date, "key": API_KEY}
    response = requests.get(BASE_URL, params=params)

    return {"weather_forecast": response.json()["forecast"]["forecastday"][0]["day"]}

async def main():
    await session.process_events()


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

📝 Function annotation examples

No parameters

@genai_session.bind(name="get_current_date", description="Return current date")
async def get_current_date(agent_context: GenAIContext):
    ...

Built-in types

@genai_session.bind(name="file_saver", description="Saves file")
async def file_saver(
    agent_context: GenAIContext,
    filename: str,
    file_content: str, 
    page_count: int, 
    images_names: list[str]
) -> dict:
    ...

Pydantic models

from pydantic import BaseModel, Field
from typing import List, Any


class TranslationInput(BaseModel):
    text: str = Field(..., description="Text to translate")
    language: str = Field(..., description="Code of the language to translate to (e.g. 'fr', 'es')")
    banned_words: List[str] = Field(..., description="List of words to be banned from translation")

@genai_session.bind(name="translation_agent", description="Translate the text into specified language")
async def get_translation(
    agent_context: GenAIContext,
    params: TranslationInput
) -> dict[str, Any]:
    text = params.text
    language = params.language
    banned_words = params.banned_words
    ...

typing Annotations

from typing import Any, Annotated

@genai_session.bind(name="translation_agent", description="Translate the text into specified language")
async def get_translation(
    agent_context: GenAIContext, 
    text: Annotated[str, "Text to translate"],
    language: Annotated[str, "Code of the language to translate to (e.g. 'fr', 'es')"],
    banned_words: Annotated[list[str], "List of words to be banned from translation"],
) -> dict[str, Any]:
    ...

🚀 Running the Event Loop

Start your agent's event loop:

async def main():
    await genai_session.process_events()

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

📂 Example Agents

You can find fully working agent examples in the GenAI Agentos GitHub Repository.

Metadata

Release files for genai-protocol 2.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for genai-protocol 2.0.3
File Size Uploaded
genai_protocol-2.0.3.tar.gz 18.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for genai-protocol 2.0.3
File Interpreter ABI Platform
genai_protocol-2.0.3-py3-none-any.whl Python 3 none any Details

Total release size: 40.0 kB

Release files / genai_protocol-2.0.3.tar.gz

Download URL genai_protocol-2.0.3.tar.gz
Size 18.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d4aa086aca3f3c80c958cf5d6b86ba6df9f0f462f9127e6caceab5b377cef3c6
BLAKE2b-256 checksum
How to use checksums
4ccd66736041d226822cbd33f56c51fa81b703f871da3518a31d3ef798f96709
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.1

Release files / genai_protocol-2.0.3-py3-none-any.whl

Download URL genai_protocol-2.0.3-py3-none-any.whl
Size 21.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fc715e62594b5fb0b84a4172516fb778c06450556fe555aba5ded3c353e7356f
BLAKE2b-256 checksum
How to use checksums
6f4842162b6ea03d3fdbe83794fb3e205d4bdc4365382bb4f5f4d5885e25ca4f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.1

Release history Release notifications | RSS feed

This release

2.0.3 This release

2 release files

2.0.2

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.0.9

2 release files

1.0.8

2 release files

1.0.7

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page