Skip to main content

SuperBryn Agent Sync

PyPI version Python 3.10+ License: MIT Zero dependencies

Sync your voice-agent configuration to SuperBryn for review, versioning, and monitoring — from any framework (Pipecat, LiveKit) or provider (Vapi, Retell, ElevenLabs, Bland, Bolna, …), or straight from your source code.

A pushed manifest never changes your live agent directly. It lands as a pending draft that you review, diff, and approve in the SuperBryn dashboard. On approval (once verification passes), SuperBryn promotes the draft to a new agent version.

Features

  • Zero runtime dependencies — the blocking client uses stdlib urllib; add aiohttp only if you want the async client.
  • Draft-first sync — every push lands as a pending draft for human review; nothing goes live without approval.
  • Client-side content hashing — same RFC 8785 (JCS) + SHA-256 hashing as the server, so you can pre-check and skip no-op pushes.
  • Manifest builder — fluent, typed builder for identity, behavior, LLM / STT / TTS / voice, tools, language, telephony, guardrails, and concurrency.
  • Framework adapters — build a manifest directly from a Pipecat pipeline or a LiveKit agent, unwrapping fallback adapters and custom wrappers; a fixed allow-list of config attributes is read, never API keys.
  • Provider translators — turn Vapi / Retell / ElevenLabs / Bland / Bolna agent JSON into a manifest, best-effort and never erroring on unknown fields.
  • Source-code extraction — codescan statically scans your agent's code (Python ast, conservative JS/TS regexes) to fill prompt, models, voice, and phone number when no API can.
  • Typed errors — auth, scope, validation, business-rule, and rate-limit failures each raise a distinct exception with details.
  • Bundled JSON Schema — the canonical manifest schema ships inside the package.

Prerequisites

  • Python 3.10+
  • An agent-scoped API key created in the SuperBryn dashboard (Developers → API Keys, scope: Single agent). Org-wide keys are rejected by the sync endpoints.

Install

pip install superbryn-agent-sync            # zero runtime dependencies
pip install "superbryn-agent-sync[async]"   # + aiohttp for the async client

The import name is superbryn:

from superbryn import Superbryn, Manifest

Quick Start

  1. Set your agent-scoped API key in the environment:

    export SUPERBRYN_API_KEY="sk_agent_..."
    
  2. Build a manifest and sync it:

    from superbryn import Superbryn, Manifest
    
    manifest = (
        Manifest.builder(source="custom")
        .set_identity(name="Support Agent", type="inbound", agent_modality="voice")
        .set_behavior(prompt=open("system_prompt.txt").read())
        .set_llm(provider="openai", model="gpt-4o", temperature=0.7, max_tokens=1024)
        .set_stt(provider="deepgram", model="nova-2", language="en-US")
        .set_tts(provider="cartesia", model="sonic-2")
        .set_voice(provider="cartesia", voice_id="a0e99841-...")
        .add_tool(
            name="lookup_order",
            description="Look up an order by ID",
            schema={"type": "object", "properties": {}},
            server={"type": "http", "url": "https://api.example.com/orders"},
        )
        .set_language(primary_language="en-US", additional_languages=[{"code": "es-US", "priority": 1}])
        .set_telephony(phone_number="+15551234567")
        .set_policy_guardrails(open("guardrails.md").read())
        .set_concurrency_calls(10)
        .build()
    )
    
    client = Superbryn()  # or Superbryn(api_key="sk_agent_...")
    result = client.sync(manifest)
    # {"agent_row_id": "...", "approval_status": "pending", "verification_status": "...",
    #  "hash": "...", "change_types": [...]}
    
  3. Open the SuperBryn dashboard, review the pending draft, and approve it to promote a new agent version.

Every manifest field is optional — send only what your integration knows. An empty manifest is valid.

Client Surface

client.sync(manifest)                  # push; lands as pending draft (or no-op)

The async client mirrors the same surface (pip install "superbryn-agent-sync[async]"):

from superbryn import AsyncSuperbryn

result = await AsyncSuperbryn(api_key="sk_agent_...").sync(manifest)

Content Hashing

The SDK implements the same RFC 8785 (JCS) + SHA-256 content hashing as the server, so a client-side hash always agrees with the server's:

from superbryn import compute_manifest_hash

local_hash = compute_manifest_hash(manifest)   # == manifest.hash

Framework Adapters

Lazy submodules — the base package depends on neither framework.

Pipecat

from superbryn import Superbryn
from superbryn.pipecat import build_manifest_from_pipeline

manifest = build_manifest_from_pipeline(
    pipeline,
    identity={"name": "Support Agent", "type": "inbound", "agent_modality": "voice"},
    behavior={"prompt": open("prompt.txt").read()},
    policy_guardrails=open("guardrails.md").read(),
)
Superbryn(api_key="sk_agent_...").sync(manifest)

Recursively walks the pipeline — including ParallelPipeline branches and ServiceSwitcher / LLMSwitcher members, and unwrapping custom wrapper classes — and fills llm / stt / tts / voice automatically. For switchers, the primary member fills the block and the next member is reported in its fallback sub-block. Extraction reads a fixed allow-list of configuration attributes (including private fields like _settings where Pipecat services store their settings); credential attributes such as API keys are never part of that list and are never read.

LiveKit

from superbryn import Superbryn
from superbryn.livekit import build_manifest_from_agent

manifest = build_manifest_from_agent(
    agent,
    identity={"name": "Support Agent", "type": "inbound", "agent_modality": "voice"},
    policy_guardrails=open("guardrails.md").read(),
)
Superbryn(api_key="sk_agent_...").sync(manifest)

Reads agent.llm / agent.stt / agent.tts — unwrapping FallbackAdapter / StreamAdapter / custom wrappers to the base plugin, with FallbackAdapter fallbacks reported in fallback sub-blocks — and uses agent.instructions as the behavior prompt. Extraction reads a fixed allow-list of configuration attributes (including private fields like _opts where LiveKit plugins store their settings); credential attributes such as API keys are never part of that list and are never read.

Provider Translators

For SaaS platforms the agent config lives in their cloud, not in your process. Fetch the agent JSON from the provider's API, then translate it to a manifest:

import requests
from superbryn import Superbryn
from superbryn.translators import vapi

raw = requests.get(
    "https://api.vapi.ai/assistant/ASSISTANT_ID",
    headers={"Authorization": "Bearer VAPI_KEY"},
).json()

manifest = vapi.manifest_from_assistant(raw)
Superbryn(api_key="sk_agent_...").sync(manifest)
Provider Translator Input
Vapi translators.vapi.manifest_from_assistant(raw) GET /assistant/:id
Retell translators.retell.manifest_from_agent(agent, llm) GET /get-agent/:id + GET /get-retell-llm/:llm_id
ElevenLabs translators.elevenlabs.manifest_from_agent(raw) GET /v1/convai/agents/:id
Bland translators.bland.manifest_from_agent(raw) GET /v1/agents/:id
Bolna translators.bolna.manifest_from_agent(raw) GET /v2/agent/:id
Hooman Labs / Shunya Labs / custom translators.generic.manifest_from_prompt(prompt, source=...) or codescan.build_manifest_from_source(...) (see below) your own prompt + known pipeline facts (no public agent-read API yet)

All translators are best-effort — unknown or missing fields degrade to a sparser manifest, never an error.

Source-Code Extraction (works for every provider)

You never know in advance what a provider's public API returns — some give back the full agent config, others little more than an id, and some (Hooman Labs, Shunya Labs, in-house stacks) have no agent-read API at all. Whatever the API does or doesn't return, the customer's own code — the place that instantiates the provider's package/SDK — is always available. superbryn.codescan statically scans that code and extracts the prompt, model, voice, language, temperature and phone number.

As the sole source (no API, or the API returned nothing useful):

from superbryn import Superbryn
from superbryn.codescan import build_manifest_from_source

manifest = build_manifest_from_source(
    "path/to/agent.py",               # prefer the specific agent file over a whole tree
    source="hooman-labs",
    identity={"name": "Support Agent", "type": "inbound"},  # anything the scan can't see
)
Superbryn(api_key="sk_agent_...").sync(manifest)

As a gap filler after ANY translator — the scan adds only the fields the provider's API didn't provide, and API-provided values always win:

from superbryn import codescan, translators

manifest = translators.vapi.manifest_from_assistant(raw)          # may be sparse
manifest = codescan.fill_manifest_gaps(manifest, "path/to/agent.py")

How it works:

  • Python files are parsed with ast: keyword arguments on any call (prompt=, instructions=, model=, voice_id=, ...) are collected, and simple variable references (prompt=SYSTEM_PROMPT) resolve to their assigned string constants.
  • JS/TS files are scanned with conservative regexes for the same keys in object-literal form (systemPrompt: "...", voiceId: '...').
  • Called class names classify hits per pipeline stage (DeepgramSTTService → stt/deepgram, CartesiaTTSService → tts/cartesia), so an STT model never lands in the llm block.
  • Prompt-key strings of 40+ characters qualify as behavior.prompt; node_modules, virtualenvs and build output are skipped, and symlinks are never followed — a scan can't escape the root you give it.
  • If several distinct qualifying prompt candidates compete, the scan raises AmbiguousScanError instead of guessing (uploading the wrong string from elsewhere in a project is worse than failing). Narrow the scan to the agent file, or pass on_ambiguity="longest" to accept longest-wins.

Extraction is best-effort and read-only, and only values bound to the known config keys are collected — credential-style keys are never in the key sets. Run it in CI next to the agent code and every deploy syncs the latest config. Use scan_source(path) to inspect the raw findings before building a manifest.

Manifest Fields

Override sections accept exactly the fields of the canonical manifest schema (unknown keys raise ValueError locally — the endpoint rejects them anyway):

Section Fields
identity name, type (inbound/outbound), agent_modality (voice/chat), description, pain_point, gender, age, dob
behavior prompt, flow
llm / stt / tts / voice provider, model / voice_id, plus per-block extras (temperature, max_tokens, language, fallback, extra)
tools list of {name, description, schema, server: {type, url}}
language primary_language, additional_languages: [{code, priority}]
telephony phone_number, ivr_config

Plus top-level strings/ints: policy_guardrails, additional_details, concurrency_calls.

The canonical JSON Schema is bundled with the package:

from superbryn import load_manifest_schema

schema = load_manifest_schema()

Typed Errors

from superbryn import (
    AuthenticationError,     # 401 — bad/revoked key
    ScopeError,              # 403 — key is not agent-scoped
    NotFoundError,           # 404 — resource not found
    ManifestValidationError, # 400 — schema failure (has .details)
    BusinessRuleError,       # 422 — semantic rule failure (has .details)
    RateLimitError,          # 429 — back off and retry
)

Troubleshooting

Enable debug logs

import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("superbryn").setLevel(logging.DEBUG)

Common errors

Error Cause Fix
ConfigurationError: no API key Missing API key Pass api_key= or set SUPERBRYN_API_KEY
AuthenticationError (401) Invalid or revoked key Verify the key in SuperBryn → Developers → API Keys
ScopeError (403) Org-wide key used Create an agent-scoped key (scope: Single agent)
NotFoundError (404) Resource not found Verify the key belongs to the intended agent
ManifestValidationError (400) Manifest fails schema validation Inspect .details for the offending fields
BusinessRuleError (422) Semantic rule failure Inspect .details and adjust the manifest
RateLimitError (429) Too many requests Back off and retry

Environment Variables

Variable Meaning
SUPERBRYN_API_KEY Agent-scoped API key (fallback for api_key=)
SUPERBRYN_BASE_URL API base URL (default https://api.superbryn.com)

Links

Support

License

This project is licensed under the MIT License — see the LICENSE file for details.


Made with ❤️ by SuperBryn

Metadata

Release files for superbryn-agent-sync 0.2.0

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

Source distribution (sdist)

Source distribution for superbryn-agent-sync 0.2.0
File Size Uploaded
superbryn_agent_sync-0.2.0.tar.gz 45.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for superbryn-agent-sync 0.2.0
File Interpreter ABI Platform
superbryn_agent_sync-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 85.8 kB

Release files / superbryn_agent_sync-0.2.0.tar.gz

Download URL superbryn_agent_sync-0.2.0.tar.gz
Size 45.4 kB
Tags Source
SHA-256 checksum
How to use checksums
6288a48225d21068cb1cd09c2dfc94fd21c195559c48b611b52b0ce77b8b3058
BLAKE2b-256 checksum
How to use checksums
bc7ad6f06976d114587a956a664aa5559bd527c94513af60bc9227344d1a2156
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / superbryn_agent_sync-0.2.0-py3-none-any.whl

Download URL superbryn_agent_sync-0.2.0-py3-none-any.whl
Size 40.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
61acf2708cac6f440e4d5c3b9a6688effa92b9c58e9440df9f59a10983e26590
BLAKE2b-256 checksum
How to use checksums
066012e0e0b2b2a43451ecae3c71c504051fc1bd135f52b0319804f152dd5a9a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.4

2 release files

0.1.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