Built (with love) by Devoteam Snowflake Partner — Snowflake CoCo in your Streamlit app: a right-rail Copilot, a live preview of the app it writes, tool cards you can read, and approval gates that fit governed data apps.
You own the page. CoCo owns the session. copilot_rail() sits in the product and takes jobs from your screens; app_viewer() runs the Streamlit app the agent just wrote, next to the rail. panel() streams the transcript. Approvals pause Write / Edit / Bash / SQL until someone clicks Approve once, Always allow, or Deny.
Alpha
0.1.8— API may still move. Star / watch the repo if you plan to ship on it.
Repo: github.com/lletourmy/streamlit-coco (temporary PyPI source) · Dev: streamlit-coco-dev
SDK docs: Cortex Code Agent SDK
| Without streamlit-coco | With streamlit-coco |
|---|---|
| Wire CoCo yourself across Streamlit reruns | Session + fragment polling that keeps streaming |
| Raw JSON tool dumps | Meaningful cards (Glob, Grep, Read, Write, SQL, AskUser…) |
| Hope the agent behaves | require_approval_for + HITL UI |
| Chat-only demos | Structured callbacks, a Copilot rail, and a live app preview |
Also: headless query() for scripts and CI, plus a legacy all-in-one chat() if you want built-in input.
- You want CoCo Desktop, the CLI, or an IDE extension. This is an embed in your Streamlit app — no file tree, multi-tab workspace, or full IDE.
- The Streamlit host cannot run CoCo. The agent is server-side (CLI on the host today; remote API is still on the roadmap). Typical Streamlit Community Cloud without that setup will not work.
- You are not building in Python / Streamlit. There is no TypeScript package; use the Cortex Code Agent SDK directly.
- You need Slack, a hosted CoCo SaaS, or a product MCP server. Out of scope. MCP passthrough via
mcp_serversalready works. - You would not type the SQL yourself on this role. The agent uses the Snowflake role in the connection — do not wire
ACCOUNTADMINinto a web UI.
Alpha 0.1.8 — APIs may still move. Prefer panel() + your own input; chat() is the legacy all-in-one.
uv add "streamlit-coco[sdk]"
# or: pip install "streamlit-coco[sdk]"From a clone (editable + tests):
make install- Python 3.10+ · Streamlit ≥ 1.53
- CoCo CLI on
PATH(cortex --version) - Authenticated Snowflake connection (
~/.snowflake/connections.tomlor equivalent) cortex-code-agent-sdk(pulled in by thesdk/devextras)
Full local setup: doc/deployment/local.md (CLI install, Snowflake connections.toml, running examples, troubleshooting).
API: doc/api.md.
Preferred pattern — you own the input; CoCo owns the session and output:
import streamlit as st
import streamlit_coco as st_coco
opts = st_coco.CocoOptions(
connection="analytics",
cwd=".",
allowed_tools=["Read", "Glob", "Grep"],
require_approval_for=["Edit", "Write", "Bash"],
)
env = st_coco.check_environment(connection=opts.connection)
if not st_coco.render_start_gate(opts, session_key="copilot", env=env):
st.stop()
session = st_coco.get_or_create_session(opts, key="copilot")
st_coco.panel(session=session, warm_up=True, show_status=True, run_every=0.25)
st_coco.chat_input_bar(session, placeholder="Ask CoCo…")allowed_tools— may auto-run (enforced in Python when approvals are configured)require_approval_for— pause for Approve once · Always allow · Deny
Legacy all-in-one component (built-in input):
st_coco.chat(session=session, key="coco_chat", height=560)make chat # panel + chat input + tool cards + approvals
make cwd-upload # upload files into agent cwd + chat
make approval # legacy CCv2 chat
make structured # custom structured-output panel
make headless # asyncio query() pipeline
make backlog # Product Backlog Desk (multipage business demo)
make bi-semantic # Tableau / Power BI → semantic view + RAP (screens 1–6)
make app-builder # App Builder (type library → brief → Copilot / Preview)
# make tableau-semantic is an alias for bi-semanticExploratory prompts: examples/testdata/prompts.json.
Backlog desk: examples/backlog_desk/README.md.
BI → Semantic: examples/bi_to_semantic/README.md.
App Builder: examples/app_builder/README.md.
File upload: doc/features/file-upload/file-upload.md.
output = st.container()
def render(data: dict, result: st_coco.CocoChatResult) -> None:
with output:
st.dataframe(data.get("selected_features", []))
st_coco.panel(session=session, on_structured_output=render)import asyncio
import streamlit_coco as coco
async def run():
async for event in coco.query("Profile ANALYTICS.CUSTOMERS"):
if event.type == "result":
print(event.structured_output)
asyncio.run(run())The agent is server-side. The browser only sees Streamlit widgets. panel() (or copilot_rail() around it) polls a CocoSession worker via @st.fragment; app_viewer() is a separate child streamlit run in an iframe. The session talks to the Cortex Code Agent SDK, which runs the cortex CLI against your Snowflake account. Destructive tools pause in Python (can_use_tool) until someone clicks Approve / Deny. Headless query() skips the UI and uses the same session/SDK path.
Browser ──► panel() / copilot_rail() / app_viewer() / chat_input_bar()
│ @st.fragment poll (app page does not rerun)
▼
CocoSession (thread + asyncio, transcript + pending approval)
│ can_use_tool → render_approvals()
▼
cortex-code-agent-sdk ──► cortex CLI ──► Snowflake CoCo + RBAC
Legacy chat() is the same session, with a CCv2 frontend instead of native widgets.
| Capability | Entry points |
|---|---|
| Native panel + approvals | panel(), chat_input_bar(), render_approvals() |
| Copilot rail (right-column Copilot) | copilot_rail(), transcript_display_config(), example_questions= — doc/features/copilot-rail/ |
| App viewer (child Streamlit iframe) | app_viewer(), default_fix_prompt() — doc/features/app-viewer/ |
| Tool cards & AskUser / plan UI | see doc/features/tools-display/ |
| Session & options | CocoSession, CocoOptions, get_or_create_session |
| Headless events | query() |
| Legacy CCv2 | chat() |
streamlit_coco/
├── ui.py # panel(), send_prompt(), render_approvals()
├── rail.py # copilot_rail(), transcript_display_config()
├── viewer.py # app_viewer()
├── app_preview.py # child Streamlit process helpers
├── session.py # CocoSession worker + transcript
├── permissions.py # HITL can_use_tool gates
├── query.py # headless query()
├── component.py # legacy chat() CCv2 mount
└── frontend/ # static CCv2 assets
examples/ # chat, backlog desk, BI → Semantic, App Builder, …
doc/ # PRD, roadmap, feature specs
Full diagram and runtime notes: doc/prd.md §5 · threat-model topology: doc/security/threat-model.md.
API: doc/api.md. Feature checklists: doc/features/README.md.
make install # uv sync --extra dev
make check # ruff + unit/smoke (ignores tests/e2e)
make e2e-install # Playwright + Chromium (once)
make e2e # UX e2e vs examples/e2e_ux_harness.py
make test-all # check + e2e + audit
make audit # pip-audit
make format # ruff format + fix
make build # sdist + wheel
make sync-release # copy tree → public clones (see doc/deployment/publish.md)
make help # all targetsCI runs lint, tests, and pip-audit on every PR to main. Full local gate: make test-all (doc/testing.md).
Releases: develop here (streamlit-coco-dev), sync + tag on lletourmy/streamlit-coco → PyPI (guide).
Docs: PRD · API · Roadmap · Training · Deployment · Changelog · AGENTS.md
| Role | Name | Contact |
|---|---|---|
| Asset Owner | Laurent Letourmy | laurent.letourmy@devoteam.com |
| Contributors | DevoteamSP / streamlit-coco contributors | streamlit-coco-dev |
Snow Builders level: N0 (alpha), targeting N1. Identity sheet: ID.md.
Apache-2.0
