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.115.tar.gz (22.4 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.115-py3-none-any.whl (25.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: cycls-0.0.2.115.tar.gz
  • Upload date:
  • Size: 22.4 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.115.tar.gz
Algorithm Hash digest
SHA256 ba674bcbf52f2dc05f8d3889fa3d8f882834f4067a8717240f09f7f213762643
MD5 d740541ba97104648d97b92508217e4b
BLAKE2b-256 ae0022ec4a886313593dac56d3526dce3e6c3848603a1b4fe2b8f8764b363e91

See more details on using hashes here.

File details

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

File metadata

  • Download URL: cycls-0.0.2.115-py3-none-any.whl
  • Upload date:
  • Size: 25.3 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.115-py3-none-any.whl
Algorithm Hash digest
SHA256 39e41c3d491f555be76fb0aeb0a1a2a72309e753f57104c9346883b99a020e13
MD5 e2197f479e35aac897e43e687ca60597
BLAKE2b-256 64816344cdf08677ce7e8b9df5f262b0c4589d28476ac5840e688c0380d0c27d

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