# Build Your Own Coding Agent in 30 Minutes with Snowflake’s New code_toolset_all

> Source: <https://pub.towardsai.net/build-your-own-coding-agent-in-30-minutes-with-snowflakes-new-code-toolset-all-e05241d0c572?source=rss----98111c9905da---4>
> Published: 2026-08-29 10:03:00+00:00

**TL;DR:** Snowflake’s Cortex Agents now support code_toolset_all — a fully managed sandbox with bash, file I/O, SQL execution, and web search. This guide walks you through building a Python SDK client and a Streamlit chat UI that connects to it, complete with keypair auth, SSE streaming, and retry logic. All code is open-source and tested against a live Snowflake account.

On **August 26, 2026**, Snowflake announced the **General Availability** of the Cortex Agents Coding Agent. This isn’t a preview or beta — it’s production-ready, GA, and available to all accounts. The feature lets you add code_toolset_all to any Cortex Agent request, and Snowflake provisions a fully managed sandbox backed by the same runtime that powers CoCo (Snowflake's built-in coding assistant).

I wanted an AI agent that could:

With GA status, this is now production-ready for real workloads. The catch? There was no Python SDK yet. So I built one.

By the end of this article, you’ll have:

Architecture Diagram

```
You (Streamlit) → SDK → Cortex Agents API → Managed Sandbox → Response
```

The Coding Agent API uses JWT tokens signed with your RSA private key. Generate one:

```
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM \  -out ~/.ssh/snowflake_rsa_key.p8 -nocrypt
openssl rsa -in ~/.ssh/snowflake_rsa_key.p8 -pubout \  -out ~/.ssh/snowflake_rsa_key.pub
```

Register the public key in Snowflake:

```
ALTER USER MY_USER SET RSA_PUBLIC_KEY='MIIBIjANBgkq...';
```

The SDK has four core components:

```
| Module         | Responsibility                   || -------------- | -------------------------------- || `config.py`    | Environment-based configuration  || `auth.py`      | JWT token generation and refresh || `streaming.py` | SSE event parsing                || `client.py`    | HTTP transport with retry        |
```

The Cortex Agents API streams responses using **Server-Sent Events**. Here’s what the actual wire format looks like:

```
event: response.statusdata: {"message":"Provisioning sandbox","status":"sandbox_provisioning"}event: response.text.deltadata: {"text":"Hello! I'm","sequence_number":2}event: response.text.deltadata: {"text":" Cortex Code.","sequence_number":3}event: responsedata: {"content":[{"type":"text","text":"Hello! I'm Cortex Code."}],"status":"completed"}event: donedata: [DONE]
```

Most SSE parsers assume single-line data: events. The Cortex API uses **two-line pairs** (event: then data:), which means you need to track state between lines:

``` python
def iter_events(self, response):    current_event_type = Nonefor line in response.iter_lines():        if line.startswith("event: "):            current_event_type = line[7:]            continue        if line.startswith("data: "):            data_str = line[6:]            event_type = current_event_type or "unknown"            current_event_type = None            if data_str == "[DONE]":                yield StreamEvent(event_type="done")                return            data = json.loads(data_str)            yield StreamEvent(event_type=event_type, data=data)
```

**This was the #1 bug** in my initial implementation — parsing each line independently produced empty responses.

I wanted the SDK to feel natural for Python developers:

``` python
from cortex_coding_agent import ClientConfig, CodingAgentBuilderagent = (    CodingAgentBuilder()    .with_model("claude-sonnet-4-5")    .with_system_instructions("You are a data engineering assistant.")    .with_workspace("USER$.PUBLIC.DEFAULT$")    .with_permission_policy("always_allow")    .build(ClientConfig()))with agent:    response = agent.ask("Show me the top 5 tables by row count")    print(response.text)
```

The builder validates configuration at build time and constructs the proper API payload:

```
{  "messages": [{"role": "user", "content": [{"type": "text", "text": "..."}]}],  "tools": [{"tool_spec": {"type": "code_toolset_all", "name": "code_toolset_all"}}],  "models": {"orchestration": "claude-sonnet-4-5"},  "tool_resources": {    "code_toolset_all": {      "permission_policy": {"type": "always_allow"},      "workspace_mounts": [{"name": "USER$.PUBLIC.DEFAULT$", "mount_path": "/workspace"}]    }  }}
```

Here’s a subtlety that cost me debugging time: **the API manages conversation state server-side**. You don’t send message history — you send only the latest message, and the API maintains continuity via thread_id.

My first implementation accumulated all messages client-side and sent the full history. This caused the API to return empty responses on the 2nd and 3rd turns. The fix:

``` php
def _build_request(self, user_message: str) -> AgentRequest:    message = Message(role=MessageRole.USER, content=[...])    # Send ONLY the current message — API manages history    return AgentRequest(        messages=[message],        thread_id=self._thread_id,  # Server tracks state        ...    )
```

The entire chat interface is remarkably simple once the SDK handles the complexity:

``` python
import streamlit as stfrom cortex_coding_agent import ClientConfig, CodingAgentBuilder@st.cache_resourcedef get_agent():    return (        CodingAgentBuilder()        .with_model("claude-sonnet-4-5")        .with_permission_policy("always_allow")        .build(ClientConfig())    )if prompt := st.chat_input("Ask the coding agent..."):    with st.spinner("Thinking..."):        reply = get_agent().ask(prompt).text    st.markdown(reply)
```

Launch with:

```
export SNOWFLAKE_ACCOUNT=myaccount.region.cloudexport SNOWFLAKE_USER=MY_USERexport SNOWFLAKE_PRIVATE_KEY_PATH=~/.ssh/snowflake_rsa_key.p8streamlit run examples/streamlit_app.py
```

Once running, the agent handles prompts like:

```
| Prompt                                  | What Happens                           || --------------------------------------- | -------------------------------------- || “Show me all databases”                 | Executes `SHOW DATABASES` via SQL tool || “Write a Python script to parse JSON”   | Generates code in the sandbox          || “Read the CSV at `/workspace/data.csv`” | Uses file read tool                    || “Search for pandas documentation”       | Uses web search tool                   || “Create a stored procedure for ETL”     | Combines SQL + code generation         |
```

The sandbox includes **numpy, pandas, scipy, matplotlib, and plotly** pre-installed. Need more? Add artifact repositories for PyPI access.

**1. SSE parsing is harder than it looks.** The two-line event/data format is standard SSE, but most tutorials show single-line examples. Always pair event: with the next data: line.

**2. Don’t accumulate message history.** The Cortex API is stateful — it tracks conversations server-side. Sending history causes silent failures.

**3. Use explicit Python paths on macOS.** If you have Anaconda installed, /usr/bin/python3 -m venv .venv avoids path conflicts that cause mysterious PermissionError failures.

**4. Pin ****cryptography<44** for Python 3.9 compatibility on macOS. Newer versions have Rust bindings that don't work with the system OpenSSL.

**5. The sandbox provisions on first call (~10s)** then subsequent calls in the same thread are near-instant. Design your UX around this cold-start pattern.

Before deploying to your team:

The complete SDK (38 tests, Streamlit app, deployment SQL) is available as a single zip:

**Repository structure:**

```
cortex-coding-agent/├── src/cortex_coding_agent/   # SDK (10 modules)├── tests/unit/                # 38 passing tests├── examples/streamlit_app.py  # Chat UI├── deploy/snowflake/          # Agent DDL + RBAC└── docs/                      # Install guide + extension docs
```

The Cortex Agents Coding Agent (code_toolset_all) fundamentally changes how you build AI-powered applications on Snowflake. Instead of managing agent loops, sandboxes, and tool infrastructure yourself, you make a single API call and Snowflake handles the rest.

In this article, we built a complete Python SDK from scratch — keypair authentication, SSE streaming, a fluent builder, and a Streamlit chat UI — all validated against a live Snowflake account with 38 passing tests.

The key takeaway: **the barrier to building a production coding agent is now one REST endpoint and a few hours of work.** No servers, no containers, no orchestration framework. Just your application, a keypair, and a POST request.

Since code_toolset_all automatically inherits new tools as Snowflake adds them, your SDK stays current without code changes. That's the real power of a managed runtime — you focus on the application, not the infrastructure.

Found this useful? A 👏 helps others find it too.

Honored to be a finalist for the **2026 Snowflake Community Awards — Open Source Impact (APJ)**! If this project helped you, I’d love your vote:

🎥 [1-min video: How to vote](https://app.snowflake.com/static/workspaces/workspaces-wave1.html?v=1787904396586#) 🗳️ [Vote here](https://app.snowflake.com/static/workspaces/workspaces-wave1.html?v=1787904396586#) (Page 6 → APJ → Satish Kumar | LTIMindtree, India)

Voting closes **Sep 15**. Your support means a lot! 💙

**Follow for weekly Snowflake engineering deep dives:**

*You may use, share, adapt, and build upon this work. For public redistribution or substantial adaptation, please retain attribution and include a link to the original article or repository and the author’s LinkedIn profile. Private and internal use requires no attribution. Provided “as is” for educational purposes. Please validate and test all examples before using them in production. Views are my own and do not represent any current or former employer.*

[Build Your Own Coding Agent in 30 Minutes with Snowflake’s New code_toolset_all](https://pub.towardsai.net/build-your-own-coding-agent-in-30-minutes-with-snowflakes-new-code-toolset-all-e05241d0c572) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.
