How to Build a QwenPaw Agent Workspace with Custom Skills, Model Providers, Console Access, and Streaming API Testing

Disclosure: Some links in this article are affiliate links. AI Maestro may earn a commission if you make a purchase, at no…

By AI Maestro June 13, 2026 5 min read
How to Build a QwenPaw Agent Workspace with Custom Skills, Model Providers, Console Access, and Streaming API Testing

For makers and developers, the QwenPaw ecosystem offers a robust framework to construct agentic workflows without getting bogged down in boilerplate code. This guide walks through the process of deploying a QwenPaw workspace directly within a Google Colab environment. We cover the full lifecycle: from installing dependencies and configuring secure authentication to integrating multiple LLM providers and exposing a functional console. By the end, you will have a live, API-driven agent capable of interacting with custom skills and streaming outputs, ready for both local experimentation and production-ready prototyping.

Initialising the Environment and Security

The foundation of this setup involves importing the necessary Python libraries and establishing a strict directory structure. We define specific paths for working files, secrets, logs, and agent workspaces to ensure data isolation. Crucially, we enforce authentication by generating a secure, random password stored in a local file, ensuring that access to the QwenPaw Console remains protected.

We also define helper utilities to manage the application lifecycle. These include functions to execute shell commands, monitor port availability, and gracefully terminate any existing processes before launching a new instance. This prevents conflicts and ensures a clean state every time the environment resets.

import os
import sys
import json
import time
import uuid
import shlex
import signal
import shutil
import socket
import secrets
import pathlib
import subprocess
from datetime import datetime
RESET_QWENPAW = False
PORT = int(os.environ.get("QWENPAW_COLAB_PORT", "8088"))
ROOT = pathlib.Path("/content/qwenpaw_colab")
WORKING_DIR = ROOT / "working"
SECRET_DIR = ROOT / "secrets"
LOG_DIR = ROOT / "logs"
WORKSPACE_DIR = WORKING_DIR / "workspaces" / "default"
PID_FILE = ROOT / "qwenpaw_app.pid"
APP_LOG = LOG_DIR / "qwenpaw_app.log"
if RESET_QWENPAW and ROOT.exists():
   shutil.rmtree(ROOT)
for p in [ROOT, WORKING_DIR, SECRET_DIR, LOG_DIR, WORKSPACE_DIR]:
   p.mkdir(parents=True, exist_ok=True)
os.environ["QWENPAW_WORKING_DIR"] = str(WORKING_DIR)
os.environ["QWENPAW_SECRET_DIR"] = str(SECRET_DIR)
os.environ["QWENPAW_AUTH_ENABLED"] = "true"
os.environ["QWENPAW_AUTH_USERNAME"] = os.environ.get("QWENPAW_AUTH_USERNAME", "admin")
os.environ["QWENPAW_LOG_LEVEL"] = os.environ.get("QWENPAW_LOG_LEVEL", "info")
os.environ["QWENPAW_SKILL_SCAN_MODE"] = os.environ.get("QWENPAW_SKILL_SCAN_MODE", "warn")
os.environ["QWENPAW_TOOL_GUARD_ENABLED"] = os.environ.get("QWENPAW_TOOL_GUARD_ENABLED", "true")
password_file = SECRET_DIR / ".colab_ui_password"
if not password_file.exists():
   password_file.write_text("qpw-" + secrets.token_urlsafe(18), encoding="utf-8")
os.environ["QWENPAW_AUTH_PASSWORD"] = password_file.read_text(encoding="utf-8").strip()
def run(cmd, check=False, env=None, cwd=None, stream=False):
   if isinstance(cmd, str):
       display_cmd = cmd
       shell = True
   else:
       display_cmd = " ".join(shlex.quote(str(x)) for x in cmd)
       shell = False
   print(f"\n$ {display_cmd}")
   if stream:
       proc = subprocess.Popen(cmd, shell=shell, env=env, cwd=cwd, text=True)
       rc = proc.wait()
       if check and rc != 0:
           raise RuntimeError(f"Command failed with exit code {rc}: {display_cmd}")
       return rc, ""
   out = subprocess.run(
       cmd,
       shell=shell,
       env=env,
       cwd=cwd,
       text=True,
       stdout=subprocess.PIPE,
       stderr=subprocess.STDOUT,
   )
   print(out.stdout[-4000:])
   if check and out.returncode != 0:
       raise RuntimeError(f"Command failed with exit code {out.returncode}: {display_cmd}")
   return out.returncode, out.stdout
def port_open(host="127.0.0.1", port=8088, timeout=0.5):
   try:
       with socket.create_connection((host, port), timeout=timeout):
           return True
   except OSError:
       return False
def wait_for_port(port, seconds=90):
   start = time.time()
   while time.time() - start < seconds:
       if port_open("127.0.0.1", port):
           return True
       time.sleep(1)
   return False
def stop_previous_app():
   if PID_FILE.exists():
       try:
           pid = int(PID_FILE.read_text().strip())
           os.kill(pid, signal.SIGTERM)
           time.sleep(2)
           try:
               os.kill(pid, 0)
               os.kill(pid, signal.SIGKILL)
           except OSError:
               pass
       except Exception:
           pass
       PID_FILE.unlink(missing_ok=True)
def qwenpaw_cmd(*args):
   exe = shutil.which("qwenpaw")
   if exe:
       return [exe, *args]
   return [sys.executable, "-m", "qwenpaw", *args]
def colab_secret_or_env(name):
   value = os.environ.get(name, "")
   try:
       from google.colab import userdata
       secret_value = userdata.get(name)
       if secret_value:
           value = secret_value
   except Exception:
       pass
   return value or ""
print("Python:", sys.version)
assert sys.version_info >= (3, 10), "QwenPaw needs Python 3.10+."
pip_spec = os.environ.get("QWENPAW_PIP_SPEC", "qwenpaw")
run([sys.executable, "-m", "pip", "install", "-q", "-U", "pip", "setuptools", "wheel"], check=False)
run([sys.executable, "-m", "pip", "install", "-q", "-U", pip_spec, "requests"], check=True)
try:
   import requests
except Exception:
   run([sys.executable, "-m", "pip", "install", "-q", "-U", "requests"], check=True)
   import requests

Configuring Model Providers and Agents

Once the environment is primed, we configure the agent logic. We set up a flexible configuration that supports a range of major model providers, including OpenAI, OpenRouter, DashScope, DeepSeek, and Google Gemini. The code scans for API keys stored as Colab secrets, automatically selecting the first available provider to ensure the system remains functional regardless of the underlying infrastructure.

We then define a default agent profile named “Colab Research Assistant”. This agent is configured to be file-aware, capable of executing custom skills, and guarded by security protocols. The setup includes parameters for maximum iteration counts, retry logic, and streaming output, ensuring the agent behaves predictably during complex tasks.

if not (WORKING_DIR / "config.json").exists():
run(qwenpaw_cmd("init", "--defaults"), check=False)
else:
print("QwenPaw working directory already initialized:", WORKING_DIR)
provider_candidates = [
{
"env": "OPENAI_API_KEY",
"provider_id": "openai",
"name": "OpenAI",
"base_url": "https://api.openai.com/v1",
"model": os.environ.get("QWENPAW_MODEL", "gpt-4o-mini"),
"chat_model": "OpenAIChatModel",
"prefix": "sk-",
},
{
"env": "OPENROUTER_API_KEY",
"provider_id": "openrouter",
"name": "OpenRouter",
"base_url": "https://openrouter.ai/api/v1",
"model": os.environ.get("QWENPAW_MODEL", "openai/gpt-4o-mini"),
"chat_model": "OpenAIChatModel",
"prefix": "sk-or-",
},
{
"env": "DASHSCOPE_API_KEY",
"provider_id": "dashscope",
"name": "DashScope",
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"model": os.environ.get("QWENPAW_MODEL", "qwen-plus"),
"chat_model": "OpenAIChatModel",
"prefix": "sk-",
},
{
"env": "DEEPSEEK_API_KEY",
"provider_id": "deepseek",
"name": "DeepSeek",
"base_url": "https://api.deepseek.com",
"model": os.environ.get("QWENPAW_MODEL", "deepseek-chat"),
"chat_model": "OpenAIChatModel",
"prefix": "sk-",
},
{
"env": "GEMINI_API_KEY",
"provider_id": "gemini",
"name": "Google Gemini",
"base_url": "https://generativelanguage.googleapis

Stay ahead of AI. Get the most important stories delivered to your inbox — no spam, no noise.

Name
Scroll to Top