Skip to main content

Simple, flexible AI agent framework with a small DSL and explicit state

Project description

PicoFlow — Simple, Flexible AI Agent Framework

Build agents with explicit steps and a small DSL.
LLMs, tools, loops, and branches compose naturally.


A Minimal PicoFlow Application

from picoflow import flow, llm, create_agent

LLM_URL = "llm+openai:///gpt-4.1-mini?api_key_env=OPENAI_API_KEY"

@flow
async def mem(ctx):
    return ctx.add_memory("user", ctx.input)

agent = create_agent(
    mem >> llm("Answer in one sentence: {input}", llm_adapter=LLM_URL)
)

print(agent.get_output("What is PicoFlow?", trace=True))
export OPENAI_API_KEY=sk-...
python minimal.py

Core Ideas

  • Flow = step
    A flow is just a Python function that takes and returns State.

  • DSL = pipeline
    Use >> to compose steps into readable execution graphs.

  • Agent = runner
    create_agent(flow) gives you run / arun / get_output.

  • State = context (Ctx)
    Ctx is an alias of State. It is immutable and explicit.


Quick Start (Step by Step)

1. Define Steps with @flow

from picoflow import flow, Ctx

@flow
async def normalize(ctx: Ctx) -> Ctx:
    return ctx.update(input=ctx.input.strip().lower())

2. Call LLM as a Step

from picoflow import llm

ask = llm("Answer briefly: {input}")

3. Compose with DSL

pipeline = normalize >> ask

4. Run with Agent

from picoflow import create_agent

agent = create_agent(pipeline)

state = await agent.arun("Hello WORLD")
print(state.output)

DSL in One Minute

Sequential

flow = a >> b >> c

Loop

flow = step.repeat()

or:

flow = repeat(step, until=lambda s: s.done)

Parallel + Merge

flow = fork(a, b) >> merge()

Custom merge:

flow = fork(a, b) >> merge(
    mode=MergeType.CUSTOM,
    reducer=lambda branches, main: branches[0]
)

LLM URL

from picoflow.adapters.registry import from_url

adapter = from_url(
    "llm+openai:///gpt-4.1-mini?api_key_env=OPENAI_API_KEY"
)

Then:

flow = llm("Explain: {input}", llm_adapter=adapter)

Custom Adapters

class MyAdapter(LLMAdapter):
    def __call__(self, prompt: str, stream: bool):
        ...
from picoflow.adapters.registry import register

register("myllm", lambda url: MyAdapter(...))

Use:

llm+myllm://host/model?param=value

OpenAI-Compatible DSN Notes

The OpenAI-compatible adapter uses this shape:

llm+openai://<host>/<model>?k=v&...

Examples:

llm+openai:///gpt-4.1-mini?api_key_env=OPENAI_API_KEY
llm+openai://ark.cn-beijing.volces.com/doubao-seed-1-8-251228?api_key_env=OPENAI_API_KEY
llm+openai://127.0.0.1:8000/Qwen2.5?api_key=none

Supported standard query params include:

  • api_key
  • api_key_env
  • base_url
  • base_path
  • timeout
  • verify
  • insecure
  • ca_file
  • ca_path

All other query params are passed through to the request payload automatically.

Example: Doubao thinking

llm+openai://ark.cn-beijing.volces.com/doubao-seed-1-8-251228?api_key_env=OPENAI_API_KEY&thinking={"type":"enabled"}

Example: OpenAI-compatible reasoning parameter

llm+openai:///gpt-5.1?api_key_env=OPENAI_API_KEY&reasoning_effort=medium

Simple JSON values are parsed automatically:

  • JSON objects and arrays become dict/list
  • JSON numbers become int/float
  • true / false / null become boolean / None
  • other values stay as strings

Core fields such as model, messages, and stream are still controlled by PicoFlow and are not taken from the query string.


Runtime Options

Tracing

await agent.arun("hi", trace=True)

Timeout

await agent.arun("hi", timeout=10)

Streaming

async def on_chunk(text: str):
    print(text, end="", flush=True)

await agent.arun("stream me", stream_callback=on_chunk)

Tools

from picoflow import tool

flow = tool("search", lambda q: {"result": "..."} )

Results:

state.tools["search"]

Troubleshooting: SSL certificate verify failed

Recommended (secure): set your CA bundle

export SSL_CERT_FILE=/path/to/ca.pem
# or
export PICO_CA_FILE=/path/to/ca.pem

Quick debug (insecure): disable verification temporarily

...&insecure=1

or

export PICO_SSL_VERIFY=0

Do not use this in production.

Note: Local Ollama usage (llm+ollama://localhost:11434/...) uses plain HTTP and does not require SSL configuration.


📚 Cookbook (Examples)

The cookbook/ directory contains small, focused examples for common patterns.
Each folder is runnable and demonstrates one specific feature or usage style.

cookbook/
├─ minimal-demo        # Smallest runnable PicoFlow example
├─ multiple-crew       # Multi-agent / crew-style collaboration
├─ simple-chat         # Basic chat agent
├─ simple-chat-stream  # Streaming responses from LLM
├─ simple-tool         # Tool calling and tool state
└─ trace               # Tracing and execution visualization

How to run

All examples are standalone scripts:

export OPENAI_API_KEY=sk-...
cd cookbook/simple-chat
python main.py

When to use which example

  • Start hereminimal-demo
    Understand Flow, DSL (>>), and Agent execution.

  • LLM interactionsimple-chat, simple-chat-stream
    Prompt → response, with and without streaming.

  • Tool callingsimple-tool
    How tools are defined, executed, and stored in state.tools.

  • Multi-step / multi-agentmultiple-crew
    Composition of multiple flows and roles.

  • Debugging & observabilitytrace
    How tracing hooks and structured events work.

Cookbook examples are intentionally small and close to real usage.
They are recommended as the primary learning path after reading the Minimal Example.


License

MIT

Project details


Download files

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

Source Distribution

picoflow-0.1.8.tar.gz (24.6 kB view details)

Uploaded Source

Built Distribution

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

picoflow-0.1.8-py3-none-any.whl (28.1 kB view details)

Uploaded Python 3

File details

Details for the file picoflow-0.1.8.tar.gz.

File metadata

  • Download URL: picoflow-0.1.8.tar.gz
  • Upload date:
  • Size: 24.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.10

File hashes

Hashes for picoflow-0.1.8.tar.gz
Algorithm Hash digest
SHA256 1931e9385ccf38cecad0b4f6adf7af924e0c0bbdcb93731d226f38da5d0acfdc
MD5 ad3b07128a7a35158594f98f91ba3133
BLAKE2b-256 6c57f948337c031b6ced3eda38fcfd599289d03a480fa2abf910a5780d671e86

See more details on using hashes here.

File details

Details for the file picoflow-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: picoflow-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 28.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.10

File hashes

Hashes for picoflow-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 6cd9db6d3eee093f955c94a773bf6d8480a3430edd0860de2485a9c7ccd650fe
MD5 5419f642b80e0b763a0f64847b1cdd0b
BLAKE2b-256 0a32dab6231e02b8b3e7975e399bd2413e818f770db90564052ea72536c1c9a9

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