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.118.tar.gz (24.2 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.118-py3-none-any.whl (27.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: cycls-0.0.2.118.tar.gz
  • Upload date:
  • Size: 24.2 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.118.tar.gz
Algorithm Hash digest
SHA256 aa905b0b82a886779bc382d5e90a92f9206181912c74a1cb9d9ad62106a92921
MD5 062a0bae55adccbbea335ecaa826c0ff
BLAKE2b-256 f3e99e85c2b74c27c93c8a5f3200ac3d954fadc9a557ed65cad48d07bb40b68f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: cycls-0.0.2.118-py3-none-any.whl
  • Upload date:
  • Size: 27.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.118-py3-none-any.whl
Algorithm Hash digest
SHA256 8922d55b9d203c69f6dc50e152e2c42521e56c865e4ed7016340636df287956a
MD5 7e09bbd7bbd42653d7f545cf82ea84ad
BLAKE2b-256 9eb6418758fbe5c60f7471fa2fc520a9e5a62094d8d00afebd1393282a01aed9

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