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.110.tar.gz (918.5 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.110-py3-none-any.whl (925.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: cycls-0.0.2.110.tar.gz
  • Upload date:
  • Size: 918.5 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.110.tar.gz
Algorithm Hash digest
SHA256 e85095c11553186d6e3ef09a416335f8131519d6058ff00fc586c183e2921351
MD5 0f055dc483ebd352e95db6546996936c
BLAKE2b-256 14a7cd5677574f3cbdc3cc749943441fdb972b485b755a08dd64fd02df592ad3

See more details on using hashes here.

File details

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

File metadata

  • Download URL: cycls-0.0.2.110-py3-none-any.whl
  • Upload date:
  • Size: 925.5 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.110-py3-none-any.whl
Algorithm Hash digest
SHA256 8e8631fdaba95cf45988bbf688e1ddbddb1707036fb2e8c404c5d2d0b859e379
MD5 c5374189dc1370e41a99fd42837826ed
BLAKE2b-256 b580c4037d6f1ef6014d2a04b68a388e3813fb7dbce914239570781de28c2cee

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