Skip to main content

Distribute Intelligence

Project description

Distribute Intelligence

Website | Docs | Tutorial

cycls Python package on PyPi Tests Cycls newsletter Cycls Twitter


Cycls

The open-source SDK for distributing AI agents.

  Agent extends App (prompts, skills)
      └── App extends Function (web UI)
          └── Function (containerization)

Distribute Intelligence

Write a function. Deploy it as an API, a web interface, or both. Add authentication, analytics, and monetization with flags.

import cycls

cycls.api_key = "YOUR_CYCLS_API_KEY"

@cycls.app(pip=["openai"])
async def app(context):
    from openai import AsyncOpenAI
    client = AsyncOpenAI()

    stream = await client.responses.create(
        model="o3-mini",
        input=context.messages,
        stream=True,
        reasoning={"effort": "medium", "summary": "auto"},
    )

    async for event in stream:
        if event.type == "response.reasoning_summary_text.delta":
            yield {"type": "thinking", "thinking": event.delta}  # Renders as thinking bubble
        elif event.type == "response.output_text.delta":
            yield event.delta

app.deploy()  # Live at https://agent.cycls.ai

Installation

pip install cycls

Requires Docker. See the full tutorial for a comprehensive guide.

What You Get

  • Streaming API - OpenAI-compatible /chat/completions endpoint
  • Web Interface - Chat UI served automatically
  • Authentication - auth=True enables JWT-based access control
  • Analytics - analytics=True tracks usage
  • Monetization - plan="cycls_pass" integrates with Cycls Pass subscriptions
  • Native UI Components - Render thinking bubbles, tables, code blocks in responses

Running

app.local()             # Development with hot-reload (localhost:8080)
app.local(watch=False)  # Development without hot-reload
app.deploy()            # Production: https://agent.cycls.ai

Get an API key at cycls.com.

Authentication & Analytics

See the tutorial for full auth and monetization examples.

@cycls.app(pip=["openai"], auth=True, analytics=True)
async def app(context):
    # context.user available when auth=True
    user = context.user  # User(id, email, name, plans)
    yield f"Hello {user.name}!"
Flag Description
auth=True Universal user pool via Cycls Pass (Clerk-based). You can also use your own Clerk auth.
analytics=True Rich usage metrics available on the Cycls dashboard.
plan="cycls_pass" Monetization via Cycls Pass subscriptions. Enables both auth and analytics.

Native UI Components

Yield structured objects for rich streaming responses. See the tutorial for all component types and examples.

@cycls.app()
async def demo(context):
    yield {"type": "thinking", "thinking": "Analyzing the request..."}
    yield "Here's what I found:\n\n"

    yield {"type": "table", "headers": ["Name", "Status"]}
    yield {"type": "table", "row": ["Server 1", "Online"]}
    yield {"type": "table", "row": ["Server 2", "Offline"]}

    yield {"type": "code", "code": "result = analyze(data)", "language": "python"}
    yield {"type": "callout", "callout": "Analysis complete!", "style": "success"}
Component Streaming
{"type": "thinking", "thinking": "..."} Yes
{"type": "code", "code": "...", "language": "..."} Yes
{"type": "table", "headers": [...]} Yes
{"type": "table", "row": [...]} Yes
{"type": "status", "status": "..."} Yes
{"type": "callout", "callout": "...", "style": "..."} Yes
{"type": "image", "src": "..."} Yes

Thinking Bubbles

The {"type": "thinking", "thinking": "..."} component renders as a collapsible thinking bubble in the UI. Each yield appends to the same bubble until a different component type is yielded:

# Multiple yields build one thinking bubble
yield {"type": "thinking", "thinking": "Let me "}
yield {"type": "thinking", "thinking": "analyze this..."}
yield {"type": "thinking", "thinking": " Done thinking."}

# Then output the response
yield "Here's what I found..."

This works seamlessly with OpenAI's reasoning models - just map reasoning summaries to the thinking component.

Context Object

@cycls.app()
async def chat(context):
    context.messages      # [{"role": "user", "content": "..."}]
    context.messages.raw  # Full data including UI component parts
    context.user          # User(id, email, name, plans) when auth=True

API Endpoints

Endpoint Format
POST chat/cycls Cycls streaming protocol
POST chat/completions OpenAI-compatible

Streaming Protocol

Cycls streams structured components over SSE:

data: {"type": "thinking", "thinking": "Let me "}
data: {"type": "thinking", "thinking": "analyze..."}
data: {"type": "text", "text": "Here's the answer"}
data: {"type": "callout", "callout": "Done!", "style": "success"}
data: [DONE]

See docs/streaming-protocol.md for frontend integration.

Declarative Infrastructure

Define your entire runtime in the decorator. See the tutorial for more details.

@cycls.app(
    pip=["openai", "pandas", "numpy"],
    apt=["ffmpeg", "libmagic1"],
    copy=["./utils.py", "./models/", "/absolute/path/to/config.json"],
    copy_public=["./assets/logo.png", "./static/"],
)
async def my_app(context):
    ...

pip - Python Packages

Install any packages from PyPI. These are installed during the container build.

pip=["openai", "pandas", "numpy", "transformers"]

apt - System Packages

Install system-level dependencies via apt-get. Need ffmpeg for audio processing? ImageMagick for images? Just declare it.

apt=["ffmpeg", "imagemagick", "libpq-dev"]

copy - Bundle Files and Directories

Include local files and directories in your container. Works with both relative and absolute paths. Copies files and entire directory trees.

copy=[
    "./utils.py",                    # Single file, relative path
    "./models/",                     # Entire directory
    "/home/user/configs/app.json",   # Absolute path
]

Then import them in your function:

@cycls.app(copy=["./utils.py"])
async def chat(context):
    from utils import helper_function  # Your bundled module
    ...

copy_public - Static Files

Files and directories served at the /public endpoint. Perfect for images, downloads, or any static assets your agent needs to reference.

copy_public=["./assets/logo.png", "./downloads/"]

Access them at https://your-app.cycls.ai/public/logo.png.


What You Get

  • One file - Code, dependencies, configuration, and infrastructure together
  • Instant deploys - Unchanged code deploys in seconds from cache
  • No drift - What you see is what runs. Always.
  • Just works - Closures, lambdas, dynamic imports - your function runs exactly as written

No YAML. No Dockerfiles. No infrastructure repo. The code is the deployment.

Learn More

License

MIT

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cycls-0.0.2.112.tar.gz (25.8 kB view details)

Uploaded Source

Built Distribution

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

cycls-0.0.2.112-py3-none-any.whl (31.1 kB view details)

Uploaded Python 3

File details

Details for the file cycls-0.0.2.112.tar.gz.

File metadata

  • Download URL: cycls-0.0.2.112.tar.gz
  • Upload date:
  • Size: 25.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for cycls-0.0.2.112.tar.gz
Algorithm Hash digest
SHA256 d4f1d6d6b1b168244203b90520526d50a069cb20e0e95543fbe080940c4c6ba7
MD5 68948e2aff9093be88fedcfb94463c56
BLAKE2b-256 0d3d654cf0109699d87bf9e0e918301069132807b6298a001ff31b82f74c2311

See more details on using hashes here.

File details

Details for the file cycls-0.0.2.112-py3-none-any.whl.

File metadata

  • Download URL: cycls-0.0.2.112-py3-none-any.whl
  • Upload date:
  • Size: 31.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.25 {"installer":{"name":"uv","version":"0.9.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for cycls-0.0.2.112-py3-none-any.whl
Algorithm Hash digest
SHA256 27265dc1fa5581321e8e85ca8690c3026eed65635a514e9a63dffedeb1b63100
MD5 3501d96f2c404674bcda4dd8ae6a994e
BLAKE2b-256 2662cb35bff35fbbd278209fb3b0019c1025b4c8f9c011fd01a78aa8c3c60023

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