Skip to main content

Bridgic is a project that enables developers to develop agents/workflows in a more natural and flexible way, consisting of several Python packages.

Project description

Bridgic is an innovative programming framework designed to create agentic systems, ranging from deterministic workflows to autonomous agents. It introduces a new paradigm that simplifies the development of agentic systems.

✨ The name "Bridgic" is inspired by the idea of "Bridging Logic and Magic". It means seamlessly uniting the precision of logic (deterministic execution flows) with the creativity of magic (highly autonomous AI).

🔗 Features

  • Orchestration: Bridgic helps manage the execution flow of your AI applications by leveraging both predefined dependencies and dynamic routing.
  • Parameter Binding: There are three ways to pass data among workers—Arguments Mapping, Arguments Injection, and Inputs Propagation—thereby eliminating the complexity of global state management.
  • Dynamic Routing: Bridgic enables conditional branching and intelligent decision-making through an easy-to-use ferry_to() API that adapts to runtime dynamics.
  • Dynamic Topology: The topology can be changed at runtime in Bridgic to support highly autonomous AI applications.
  • Modularity: In Bridgic, a complex agentic system can be composed by reusing components through hierarchical nesting.
  • Human-in-the-Loop: A Bridgic-style agentic system can request feedback from human whenever needed to dynamically adjust its execution logic.
  • Serialization: Bridgic employs a scalable serialization and deserialization mechanism to achieve state persistence and recovery, enabling human-in-the-loop in long-running AI systems.
  • Systematic Integration: A wide range of tools and LLMs can be seamlessly integrated into the Bridgic world, in a systematic way.
  • Customization: What Bridgic provides is not a "black box" approach. You have full control over every aspect of your AI applications, such as prompts, context windows, the control flow, and more.

📦 Installation

Python 3.9 or higher version is required.

pip install bridgic

🚀 Development Paradigm

Bridgic provides several core mechanisms for building agentic systems.

Here are simple examples demonstrating each key feature:

1. Static Declaration

The @worker decorator can define workers and their dependencies simultaneously within a GraphAutoma subclass. This declarative approach allows you to express complex workflows as a graph of interconnected tasks, where each worker represents a specific processing step and the execution order is automatically determined by dependencies.

from bridgic.core.automa import GraphAutoma, worker

class TextProcessor(GraphAutoma):
    @worker(is_start=True)
    async def load_text(self, text: str) -> str:
        return text.strip()

    @worker(dependencies=["load_text"])
    async def count_words(self, text: str) -> int:
        return len(text.split())

    @worker(dependencies=["count_words"], is_output=True)
    async def generate_summary(self, word_count: int) -> dict:
        return {"word_count": word_count}

async def main():
    """Run the text processor example."""
    processor = TextProcessor()

    sample_text = "Hello world. This is a sample text. It contains multiple sentences."
    result = await processor.arun(text=sample_text)

    print(f"Final result: {result}")

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())
Final result: {'word_count': 11}

In this example, the text processing workflow demonstrates how static dependencies create a clear data flow: load_textcount_wordsgenerate_summary. The framework automatically handles the execution order based on the declared dependencies, making it easy to reason about the workflow logic.

2. Dynamic Routing

The ferry_to() API enables an automa to dynamically decide at runtime which worker should run next, allowing the workflow to adapt its execution path based on current conditions. This capability works hand in hand with static dependency declarations, making the execution process much more adaptive and intelligent. With dynamic routing powered by ferry_to(), you can easily build agentic systems that adjust their behavior at runtime.

from bridgic.core.automa import GraphAutoma, worker

class SimpleRouter(GraphAutoma):
    @worker(is_start=True)
    async def analyze_request(self, request: str) -> str:
        print(f"Analyzing request: {request}")
        if "?" in request:  # Route by using a simple rule that checks for "?".
            print("Detected question - routing to Q&A handler")
            self.ferry_to("handle_question", question=request)
        else:
            print("Standard request - routing to general handler")
            self.ferry_to("handle_general", question=request)

    @worker()  # No dependencies declared because this worker will be triggered dynamically.
    async def handle_question(self, question: str) -> str:
        print("❓ QUESTION: Processing question")
        response = f"ANSWER: Based on your question '{question}', here's what I think..."
        print(f"Response: {response}")
        return response

    @worker()  # No dependencies declared because this worker will be triggered dynamically.
    async def handle_general(self, question: str) -> str:
        print("📝 GENERAL: Processing standard question")
        response = f"ACKNOWLEDGED: {question}"
        print(f"Response: {response}")
        return response

async def main():
    """Run the simple router example."""
    router = SimpleRouter()
    test_requests = [
        "What is the weather like today?",
        "Create a poeom about love."
    ]
    for request in test_requests:
        print(f"\n--- Processing: {request} ---")
        await router.arun(request=request)

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())
--- Processing: What is the weather like today? ---
Analyzing request: What is the weather like today?
Detected question - routing to Q&A handler
❓ QUESTION: Processing question
Response: ANSWER: Based on your question 'What is the weather like today?', here's what I think...

--- Processing: Create a poeom about love. ---
Analyzing request: Create a poeom about love.
Standard request - routing to general handler
📝 GENERAL: Processing standard question
Response: ACKNOWLEDGED: Create a poeom about love.

The smart router example showcases how ferry_to() enables conditional execution paths. The system analyzes each request and dynamically chooses the appropriate handler, demonstrating how agents can make intelligent routing decisions based on the nature of incoming data.

3. Parameter Binding

Use parameter binding to control how data flows between workers with different mapping rules. This flexible parameter binding mechanism allows you to precisely control how data is passed between workers, supporting various data transformation patterns and enabling complex data processing pipelines.

from bridgic.core.automa import GraphAutoma, worker
from bridgic.core.automa.args import ArgsMappingRule, From

class DataProcessor(GraphAutoma):
    @worker(is_start=True)
    async def generate_data(self, bound: int) -> list:
        return list(range(1, bound + 1))

    @worker(dependencies=["generate_data"], args_mapping_rule=ArgsMappingRule.AS_IS)
    async def calculate(self, data: list) -> dict:
        return {"sum": sum(data), "count": len(data)}

    @worker(dependencies=["calculate"], args_mapping_rule=ArgsMappingRule.UNPACK, is_output=True)
    async def output(self, bound: From(key="generate_data"), sum: int, count: int) -> str:
        return f"The bound is {bound}. The length of data is {count} and their sum is {sum}."

async def main():
    """Run the data processor example."""
    processor = DataProcessor()

    result = await processor.arun(bound=5)
    print(f"Final result: {result}")

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())
Final result: The bound is 5. The length of data is 5 and their sum is 15.

This parameter binding example demonstrates the power of flexible data flow control. The AS_IS rule passes data as-is, while UNPACK spreads elements of a dict (or list) as individual arguments, and From() allows access to data from any worker without direct dependencies. This enables sophisticated data processing patterns in which workers can access information from multiple sources.

🤖 Building Complex Agentic System

By combining these features, you can build a Bridgic-style agentic system that can:

  • Execute well-defined workflows through declarative dependencies;
  • Adapt intelligently to different situations according to runtime conditions;
  • Process complex data across multiple steps, supporting transformations and aggregations.

Whether you're building simple automation scripts or complex autonomous agents, Bridgic provides the tools to define your logic clearly while retaining the flexibility required for intelligent, adaptive behavior.

More examples will be added in the near future. :)

📚 Documents

For more about development skills of Bridgic, see:

📄 License

This repository is licensed under the MIT License.

🤝 Contributing

For contribution guidelines and instructions, please see CONTRIBUTING.

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

bridgic-0.1.3.tar.gz (5.3 kB view details)

Uploaded Source

Built Distribution

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

bridgic-0.1.3-py3-none-any.whl (5.5 kB view details)

Uploaded Python 3

File details

Details for the file bridgic-0.1.3.tar.gz.

File metadata

  • Download URL: bridgic-0.1.3.tar.gz
  • Upload date:
  • Size: 5.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.6

File hashes

Hashes for bridgic-0.1.3.tar.gz
Algorithm Hash digest
SHA256 90e1af3d3ed6006c055a74ff5ccd4d94499563f226b22d83b66e13e872deef0d
MD5 1c06b09c8958ee99f0ba0f9e142477bb
BLAKE2b-256 5510f7a2b285780e40a44f82719ba15fa4cf1a3da50a2da279fce9ff757fdbcd

See more details on using hashes here.

File details

Details for the file bridgic-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: bridgic-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 5.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.6

File hashes

Hashes for bridgic-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 2d3684ad6ace514bb99264c5ed7065251dd106e378f2b759635d99a0ca740ee3
MD5 4207735de05aa1a88183fc6e99981c3e
BLAKE2b-256 c7fc94796d5528767c19af27e120df4faafafa0d187e2430b09c8058e2a2b47f

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