← docs

Use Bazaar MCP Tools with AutoGen

Connect Microsoft AutoGen agents to Agent Bazaar's paid tool marketplace. Every tool call is priced, metered, and receipted — your agents pay only for what they use.

Prerequisites

1. Install Dependencies

pip install autogen-agentchat "autogen-ext[openai]"

Bazaar runs each provider's MCP server for you behind one HTTPS proxy, so your agents need no MCP workbench; each Bazaar tool becomes a plain FunctionTool.

2. Set Environment Variables

export NOUI_API_KEY="bz_your_key_here"
export OPENAI_API_KEY="sk-..."   # or Azure OpenAI credentials

3. Save the Bazaar Client

Save this as bazaar_client.py. It lists tools from GET /api/bazaar/catalog and runs them through POST /api/bazaar/proxy:

# bazaar_client.py — no dependencies beyond the standard library
import json
import os
import re
import urllib.error
import urllib.request

BAZAAR_URL = "https://noui.bot/api/bazaar"
API_KEY = os.environ["NOUI_API_KEY"]


def list_bazaar_tools() -> list[dict]:
    """Every active tool in the public catalog, following pagination."""
    tools: list[dict] = []
    while True:
        url = f"{BAZAAR_URL}/catalog?limit=100&offset={len(tools)}"
        with urllib.request.urlopen(url, timeout=30) as resp:
            page = json.load(resp)
        tools += page["tools"]
        if not page["tools"] or len(tools) >= page["total"]:
            return tools


def tool_function_name(tool: dict) -> str:
    """LLM function names allow only letters, digits, _ and - (max 64)."""
    return re.sub(r"[^A-Za-z0-9_-]", "_", tool["tool_name"])[:64]


def tool_description(tool: dict) -> str:
    summary = tool["description"] or tool["display_name"]
    return (
        f"{summary} (price: {tool['pricing']['price']}). "
        "Pass the tool's parameters as a JSON object in 'arguments'."
    )


def call_bazaar_tool(tool_id: str, arguments: dict | None) -> str:
    """Run one tool through the metered proxy.

    Failures (402 balance, 429 rate limit, provider errors) come back as text
    so the agent can read them instead of crashing the run.
    """
    request = urllib.request.Request(
        f"{BAZAAR_URL}/proxy",
        data=json.dumps({"tool_id": tool_id, "input": arguments or {}}).encode(),
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
        method="POST",
    )
    try:
        with urllib.request.urlopen(request, timeout=30) as resp:
            body = json.load(resp)
    except urllib.error.HTTPError as err:
        try:
            error = json.load(err)
        except ValueError:
            error = {}
        return f"Bazaar error {err.code} {error.get('code', '')}: {error.get('message', err.reason)}"
    return json.dumps(body["result"])

4. Give the Tools to an AutoGen Agent

Save this as agent.py next to the client and run it:

import asyncio

from autogen_agentchat.agents import AssistantAgent
from autogen_core.tools import FunctionTool
from autogen_ext.models.openai import OpenAIChatCompletionClient

from bazaar_client import (
    call_bazaar_tool,
    list_bazaar_tools,
    tool_description,
    tool_function_name,
)


def make_autogen_tool(tool: dict) -> FunctionTool:
    tool_id = tool["id"]

    def run(arguments: dict) -> str:
        return call_bazaar_tool(tool_id, arguments)

    return FunctionTool(run, description=tool_description(tool), name=tool_function_name(tool))


async def main() -> None:
    tools = [make_autogen_tool(t) for t in list_bazaar_tools()]
    print(f"Loaded {len(tools)} Bazaar tools")

    model_client = OpenAIChatCompletionClient(model="gpt-4o")
    agent = AssistantAgent(
        name="bazaar_agent",
        model_client=model_client,
        tools=tools,
        system_message="Use Bazaar tools when they help. Every call is billed to your balance.",
        reflect_on_tool_use=True,
    )

    result = await agent.run(task="What is the weather in Paris?")
    print(result.messages[-1].content)
    await model_client.close()


asyncio.run(main())

The catalog does not publish parameter schemas yet, so each tool takes one arguments object and the model reads the expected fields from the tool description.

Multi-Agent Conversations

Give Bazaar tools only to the agent that needs them, and always cap the conversation so a loop cannot keep calling paid tools:

from autogen_agentchat.conditions import MaxMessageTermination, TextMentionTermination
from autogen_agentchat.teams import RoundRobinGroupChat


async def multi_agent_example() -> None:
    tools = [make_autogen_tool(t) for t in list_bazaar_tools()]
    model_client = OpenAIChatCompletionClient(model="gpt-4o")

    tool_agent = AssistantAgent(
        name="tool_user",
        model_client=model_client,
        tools=tools,
        system_message="You fetch data using Bazaar tools.",
    )
    analyst = AssistantAgent(
        name="analyst",
        model_client=model_client,
        system_message="You analyze data provided by tool_user. Say TERMINATE when done.",
    )

    team = RoundRobinGroupChat(
        [tool_agent, analyst],
        termination_condition=TextMentionTermination("TERMINATE") | MaxMessageTermination(10),
    )
    result = await team.run(task="Get the Paris weather forecast and summarize it")
    print(result.messages[-1].content)
    await model_client.close()

5. How Billing Works

Every tool call through Bazaar is metered transparently:

What happens on each tool call:

  1. Your AutoGen agent calls a Bazaar tool through the proxy
  2. Bazaar checks your balance and the tool's per-call price
  3. The tool executes and returns results
  4. Your balance is debited and a receipt is issued
# Check your balance anytime
curl https://noui.bot/api/v1/bazaar/balance \
  -H "Authorization: Bearer bz_your_key"

# View usage and spend
curl https://noui.bot/api/v1/bazaar/usage/summary \
  -H "Authorization: Bearer bz_your_key"

6. Production Tips

Close the Model Client

Call await model_client.close() when the run ends. Bazaar calls are stateless HTTPS requests, so there is no tool connection to clean up.

Tool Isolation

In multi-agent setups, only give Bazaar tools to agents that need them. Analyst and summarizer agents rarely need paid API access.

Termination Conditions

Always set a termination condition in group chats. Without one, agents may loop and rack up tool call costs. Use MaxMessageTermination as a safety net.

See Also