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.121.tar.gz (2.9 MB 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.121-py3-none-any.whl (3.2 MB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: cycls-0.0.2.121.tar.gz
  • Upload date:
  • Size: 2.9 MB
  • 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.121.tar.gz
Algorithm Hash digest
SHA256 b93a2858cb320aa07cdf8ac5812f50e2c8a2319ae83b8fc8cff47fe72049c890
MD5 10cab8765eecd4cf9b90534d5a0b3c41
BLAKE2b-256 4137ecaebf0c35ecb81127df3a93b7655a63d21b920204b03c71b79e6dbf639c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: cycls-0.0.2.121-py3-none-any.whl
  • Upload date:
  • Size: 3.2 MB
  • 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.121-py3-none-any.whl
Algorithm Hash digest
SHA256 06231ef92cf2958f2a3f57621367f21ace25af9aaa0c9000315fb73df26218be
MD5 995dab0c22fe3cfb8c4c2ed2e016f516
BLAKE2b-256 3ec98b15b9ec196cc5d6c80269920ee42643a7c6bb59e314aab1925c89731fbc

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