SkillAgentSearch skills...

Rojak

Python library for building durable and scalable multi-agent orchestrations.

Install / Use

/learn @StreetLamb/Rojak
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<p align="center"> <a href="https://github.com/StreetLamb/rojak/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/StreetLamb/rojak.svg?color=blue"></a> <a href="https://github.com/StreetLamb/rojak/releases"><img alt="GitHub release" src="https://img.shields.io/github/release/StreetLamb/rojak.svg"></a> <a href="https://github.com/StreetLamb/rojak/actions/workflows/test.yml"><img alt="Test" src="https://github.com/StreetLamb/rojak/actions/workflows/test.yml/badge.svg"></a> </p> <h3 align="center"> <p> Rojak - A library for building highly durable and scalable multi-agent orchestrations.</p> </h3>

See it in action:

https://github.com/user-attachments/assets/d61b8893-3c33-4002-bca9-740f403f51f1

Features

  • 🛡️ Durable and Fault-Tolerant - Agents always completes, even when the server crashes or managing long-running tasks that span weeks, months, or even years.
  • 🗂️ State Management - Messages, contexts and other states are automatically managed and preserved, even during failures. No complex database transactions required.
  • 🤝 MCP Support - Supports calling tools via Model Context Protocol (MCP) servers.
  • 🧑‍💻 Human-In-The-Loop - Integrates human intervention for approving, rejecting, or modifying tool invocations and decisions, ensuring control over critical workflows.
  • 📈 Scalable - Manage unlimited agents, and handle multiple chat sessions in parallel.
  • Scheduling - Schedule to run your agents at specific times, days, date or intervals.
  • 👁️ Visiblity - Track your agents’ past and current actions in real time through a user-friendly browser-based UI.
  • 🌐 Universal Deployment - Deploy and run locally or on any cloud platform.

Table of Contents

Install

Install the core Rojak library:

pip install rojak

Install dependencies for the specific model providers you need:

# For OpenAI models or models supporting OpenAI format e.g. DeepSeek, Ollama.
pip install rojak[openai]

# For Anthropic and Anthropic Bedrock models.
pip install rojak[anthropic]

# To install both
pip install rojak[openai,anthropic]

Rojak also supports retrievers to retrieve context from vector stores. Install the dependencies if required:

# For Qdrant
pip install rojak[qdrant-client]

Usage

Start the Temporal development server.

temporal server start-dev
# main.py
import asyncio
import uuid
from temporalio.client import Client
from rojak import Rojak
from rojak.agents import OpenAIAgentActivities, OpenAIAgentOptions, OpenAIAgent
from rojak.workflows import TaskParams

def transfer_to_agent_b():
    """Handoff to Agent B"""
    return agent_b

agent_a = OpenAIAgent(
    name="Agent A",
    instructions="You are a helpful agent.",
    functions=["transfer_to_agent_b"]
)

agent_b = OpenAIAgent(
    name="Agent B",
    instructions="Only speak in Haikus."
)


async def main():
    # Connect to the Temporal service
    temporal_client = await Client.connect("localhost:7233")

    # Initialize the Rojak client
    rojak = Rojak(temporal_client, task_queue="tasks")

    # Configure agent activities
    openai_activities = OpenAIAgentActivities(
        OpenAIAgentOptions(
            api_key="YOUR_API_KEY_HERE",  # Replace with your OpenAI API key or specify OPENAI_API_KEY in .env 
            all_functions=[transfer_to_agent_b]
        )
    )

    # Create a worker for handling agent activities
    worker = await rojak.create_worker([openai_activities])

    async with worker:
        # Run the workflow with agent A and a handoff to agent B
        response = await rojak.run(
            id=str(uuid.uuid4()),
            type="stateless",
            task=TaskParams(
                agent=agent_a,
                messages=[{"role": "user", "content": "I want to talk to agent B."}]
            ),
        )
        print(response.result.messages[-1].content)

if __name__ == "__main__":
    asyncio.run(main())
Agent B is here,  
Ready to chat and assist,  
What do you wish for?

View this completed workflow at http://localhost:8233.

Overview

Rojak simplifies the orchestration of reliable multi-agent systems by leveraging Temporal as its backbone. Designed to address the real-world challenges of agentic systems, such as network outages, unreliable endpoints, failures, and long-running processes, Rojak ensures reliability and scalability.

Much like OpenAI’s Swarm, Rojak employs two key concepts:

  • Agents: These function like individual team members, each responsible for specific tasks and equipped with the necessary tools to accomplish them.
  • Handoffs: These facilitate seamless transitions, allowing one Agent to pass responsibility or context to another effortlessly.

Examples

Basic examples can be found in the /examples directory:

  • weather: A straightforward example demonstrating tool calling and the use of context_variables.
  • mcp_weather An example demonstrating connecting to MCP servers and executing tools through them.
  • pizza A comprehensive example showcasing the use of multiple agents with human-in-the-loop interventions to help users seamlessly order food.

Understanding Rojak’s Architecture

Rojak Diagram

Rojak is built on Temporal workflows and activities, and orchestrates agents via the Orchestrator Workflow.

  • The Orchestrator Workflow is responsible for receiving the user’s query, managing the overall execution process, and orchestrating tasks such as retrieving responses from LLM models, executing tools or functions, and handling any necessary Activities.

Activities are method functions grouped by class, with each class representing actions for a specific provider. Base classes like AgentActivities and RetrieverActivities serve as templates, while concrete classes, such as OpenAIAgentActivities for OpenAI and QdrantRetrieverActivities for Qdrant Vector DB, implement provider-specific methods. This design ensures flexibility and seamless integration with various providers.

After completing its tasks, the Orchestrator Workflow generates a result containing the agent’s response and the next agent (if any) to hand off to. This result is passed back to the Orchestrator Workflow, which then continues the process by executing the specified agent in the result.

Every step in the workflows is tracked and recorded in the Temporal Service, which, in the event of failures, allows the workflow to resume from the previous step. This ensures that workflows are durable, reliable, and recoverable.

While the Temporal Service oversees the workflow, Workers are responsible for running the code. Workers poll the Temporal Service for tasks and execute them. If there are no running workers, the workflow will not progress. You can deploy not just one worker, but hundreds or even thousands, if necessary, to scale your system’s performance.

Running Rojak

Ensure that a Temporal Service is running locally. You can find instructions for setting it up here.

$ temporal server start-dev

Once the Temporal Service is running, connect the Temporal client to the Temporal Service and use it to instantiate a Rojak client.

from temporalio.client import Client
from rojak import Rojak

temporal_client = await Client.connect("localhost:7233")
rojak = Rojak(temporal_client, task_queue="tasks")

Workers

Workers are responsible for executing the tasks defined in workflows and activities. They poll the Temporal Service for tasks and run the corresponding activity or workflow logic.

To create and start a worker, you first need to define the activities it will handle. For example, if you’re using an OpenAI agent, you must provide the corresponding OpenAIAgentActivities configured with appropriate options through OpenAIAgentOptions.

Here’s how to create and start a worker:

from rojak.agents import OpenAIAgentActivities, OpenAIAgentOptions

# Initialize Rojak client
rojak = Rojak(temporal_client, task_queue="tasks")

# Initialize an OpenAI agent
agent = OpenAIAgent(name="Agent")

# Define the activities for the OpenAI agent
openai_activities = OpenAIAgentActivities(
    OpenAIAgentOptions(api_key="...")
)

# Create a worker to handle tasks for the defined activi

Related Skills

View on GitHub
GitHub Stars82
CategoryCustomer
Updated1mo ago
Forks9

Languages

Python

Security Score

100/100

Audited on Feb 8, 2026

No findings