Skip to main content

๐Ÿฆ† Extreme minimalist self-adapting AI agent - one file, self-healing, runtime dependencies

Project description

๐Ÿฆ† DevDuck

PyPI

Self-modifying AI agent that hot-reloads its own codeโ€”builds itself as it runs.

One Python file that adapts to your environment, fixes itself, and expands capabilities at runtime.

Learn more: https://duck.nyc

๐ŸŽฌ See It In Action

Feature What You'll See Demo
๐Ÿ”ฅ Hot-Reload Agent detects code changes and restarts instantly Watch
๐ŸŒ Web UI Clean web interface with real-time streaming Watch
๐Ÿ› ๏ธ Dynamic Tools Save .py file in ./tools/ โ†’ use instantly Watch
๐ŸŒŠ TCP Streaming Connect via netcat, apps, or other agents Watch
๐Ÿ”Œ IPC & Tray macOS menu bar + Unix socket IPC Demo
๐Ÿ’ฌ Ambient Overlay Floating AI input with glassmorphism UI Watch

Quick Start

# Install & run
pipx install devduck && devduck

# One-shot query
devduck "create a REST API with FastAPI"

# Python API
python -c "import devduck; devduck('analyze this code')"

Requirements: Python 3.10-3.13, AWS credentials (or Ollama/Anthropic/GitHub/MLX)


Core Capabilities

Feature What It Does How to Use
๐Ÿ”ฅ Hot-Reload Auto-restarts on code changes Edit __init__.py โ†’ saves โ†’ auto-restart
๐Ÿ› ๏ธ Runtime Tools Add/remove tools without restart manage_tools(action="add", ...)
๐Ÿ“ฆ Dynamic Loading Install packages and load tools on-the-fly install_tools(action="install_and_load", package="...")
๐Ÿง  Auto-RAG Remembers conversations via Knowledge Base Set DEVDUCK_KNOWLEDGE_BASE_ID
๐ŸŒŠ Multi-Protocol TCP, WebSocket, MCP, IPC servers Auto-starts on ports 9999, 8080, 8000
๐Ÿ”Œ MCP Client Connect to external MCP servers Set MCP_SERVERS env var
๐Ÿ’พ State Time-Travel Save/restore agent state state_manager(action="export")
๐Ÿ“ Self-Improvement Updates own system prompt system_prompt(action="add_context", ...)
โ˜๏ธ AWS Deploy One-command serverless agentcore_config(auto_launch=True)

Developer Setup

git clone git@github.com:cagataycali/devduck.git
cd devduck
python3.13 -m venv .venv
source .venv/bin/activate
.venv/bin/pip3.13 install -e .
devduck

Architecture

graph TB
    A[User Input] -->|CLI/TCP/WS/MCP/IPC| B[DevDuck Core]
    B -->|Auto RAG| C[Knowledge Base]
    C -.->|Context Retrieval| B
    B -->|Tool Calls| D[38+ Built-in Tools]
    D --> E[shell/editor/calculator]
    D --> F[GitHub/AgentCore]
    D --> G[TCP/WebSocket/MCP/IPC]
    D --> H[tray/ambient/cursor/clipboard]
    B -->|Hot-reload| I[./tools/*.py + __init__.py]
    I -.->|Load Instantly| D
    B -->|Runtime| K[manage_tools/install_tools]
    K -.->|Expand| D
    B -->|Response| J[User Output]
    J -.->|Store Memory| C
    
    style B fill:#e1f5ff
    style C fill:#d4edda
    style I fill:#fff3cd
    style K fill:#ffe6cc

Self-adapting loop: Query โ†’ RAG โ†’ Tools โ†’ Response โ†’ Memory โ†’ Hot-reload/Runtime-load โ†’ Repeat


Model Setup

DevDuck auto-detects providers based on credentials:

Priority: Bedrock โ†’ Anthropic โ†’ OpenAI โ†’ GitHub โ†’ Gemini โ†’ Cohere โ†’ Writer โ†’ Mistral โ†’ LiteLLM โ†’ LlamaAPI โ†’ MLX โ†’ Ollama

Provider API Key Auto-Detected
Bedrock AWS credentials โœ… If boto3 auth succeeds
Anthropic ANTHROPIC_API_KEY โœ… If key present
OpenAI OPENAI_API_KEY โœ… If key present
GitHub GITHUB_TOKEN or PAT_TOKEN โœ… If key present
Gemini GOOGLE_API_KEY or GEMINI_API_KEY โœ… If key present
Cohere COHERE_API_KEY โœ… If key present
Writer WRITER_API_KEY โœ… If key present
Mistral MISTRAL_API_KEY โœ… If key present
LiteLLM LITELLM_API_KEY โœ… If key present
LlamaAPI LLAMAAPI_API_KEY โœ… If key present
MLX No key needed โœ… On Apple Silicon (M1/M2/M3)
Ollama No key needed โœ… Fallback if nothing else found

Just set your API key - DevDuck handles the rest:

export ANTHROPIC_API_KEY=sk-ant-...
devduck  # Auto-uses Anthropic

export OPENAI_API_KEY=sk-...
devduck  # Auto-uses OpenAI

export GOOGLE_API_KEY=...
devduck  # Auto-uses Gemini

Manual override:

export MODEL_PROVIDER=bedrock
export STRANDS_MODEL_ID=us.anthropic.claude-sonnet-4-20250514-v1:0
devduck

Tool Management

Runtime Tool Management

Add, remove, or reload tools while agent is running:

# List all loaded tools
manage_tools(action="list")

# Add tools from a package at runtime
manage_tools(action="add", package="strands_fun_tools", tool_names="cursor,clipboard,bluetooth")

# Remove tools you don't need
manage_tools(action="remove", tool_names="cursor,clipboard")

# Reload specific tools after editing
manage_tools(action="reload", tool_names="shell,editor")

# Reload all tools (restarts agent)
manage_tools(action="reload")

# Load custom tool from file
manage_tools(action="add", tool_path="./my_custom_tool.py")

Dynamic Package Installation

Install Python packages and load their tools at runtime:

# Discover available tools before loading
install_tools(action="list_available", package="strands-fun-tools", module="strands_fun_tools")

# Install package and load all tools
install_tools(action="install_and_load", package="strands-agents-tools", module="strands_tools")

# Install and load specific tools only
install_tools(
    action="install_and_load",
    package="strands-fun-tools", 
    module="strands_fun_tools",
    tool_names=["clipboard", "cursor", "bluetooth"]
)

# Load tools from already installed package
install_tools(action="load", module="strands_tools", tool_names=["shell", "calculator"])

# List currently loaded tools
install_tools(action="list_loaded")

Static Tool Configuration

Format: package1:tool1,tool2;package2:tool3,tool4

# Minimal (shell + editor only)
export DEVDUCK_TOOLS="strands_tools:shell,editor"

# Dev essentials
export DEVDUCK_TOOLS="strands_tools:shell,editor,file_read,file_write,calculator"

# Full stack + GitHub
export DEVDUCK_TOOLS="devduck.tools:tcp,websocket,mcp_server,use_github;strands_tools:shell,editor,file_read"

devduck

Hot-Reload Tools from Directory

Create ./tools/weather.py:

from strands import tool
import requests

@tool
def weather(city: str) -> str:
    """Get weather for a city."""
    r = requests.get(f"https://wttr.in/{city}?format=%C+%t")
    return r.text

Enable directory auto-loading:

export DEVDUCK_LOAD_TOOLS_FROM_DIR=true
devduck
# Save weather.py โ†’ use instantly (no restart needed)

Default: Directory loading is OFF. Use manage_tools() or install_tools() for explicit control.


MCP Integration

As MCP Server (Expose DevDuck)

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "devduck": {
      "command": "uvx",
      "args": ["devduck", "--mcp"]
    }
  }
}

Or start HTTP MCP server:

mcp_server(action="start", port=8000, stateless=True)
# Connect at: http://localhost:8000/mcp

Modes: --mcp (stdio for Claude Desktop) | http (background server) | stateless=True (multi-node)

As MCP Client (Load External Servers)

Expand capabilities by loading tools from external MCP servers:

export MCP_SERVERS='{
  "mcpServers": {
    "strands-docs": {"command": "uvx", "args": ["strands-agents-mcp-server"]},
    "remote": {"url": "https://api.example.com/mcp", "headers": {"Auth": "Bearer token"}},
    "custom": {"command": "python", "args": ["my_server.py"]}
  }
}'
devduck

Supported transports: stdio (command/args/env) | HTTP (url/headers) | SSE (url with /sse path)

Tool prefixing: Each server's tools get prefixed (e.g., strands-docs_search_docs)


Advanced Features

State Management (Time-Travel)

Save and restore agent state for reproducibility:

# Export current state
state_manager(action="export", metadata={"note": "before refactor"})

# List saved states
state_manager(action="list")

# Load and display state
state_manager(action="load", state_file="~/.devduck/states/devduck_20250118_150000.pkl")

# Resume from state (ephemeral - doesn't mutate parent)
state_manager(
    action="resume", 
    state_file="~/.devduck/states/devduck_20250118_150000.pkl",
    query="continue the analysis from where we left off"
)

# Modify state metadata
state_manager(
    action="modify",
    state_file="path/to/state.pkl",
    metadata={"tags": ["important", "refactor"]}
)

# Delete state
state_manager(action="delete", state_file="path/to/state.pkl")

States saved to: ~/.devduck/states/

System Prompt Management

Self-improvement - agent updates its own system prompt:

# View current system prompt
system_prompt(action="view")

# Add new context (appends to prompt)
system_prompt(action="add_context", context="New learning: Always use FastAPI for APIs")

# Update entire prompt
system_prompt(action="update", prompt="You are a specialized DevOps agent...")

# Sync to GitHub (persist across deployments)
system_prompt(
    action="update",
    prompt="Updated system prompt with new learnings...",
    repository="cagataycali/devduck"
)

# Reset to default
system_prompt(action="reset")

Pattern: Learn โ†’ Add context โ†’ Sync to GitHub โ†’ Persist forever

Knowledge Base (Auto-RAG)

Automatic memory across sessions:

export DEVDUCK_KNOWLEDGE_BASE_ID=your_kb_id
devduck

How it works:

  1. Before each query: Retrieves relevant context from KB
  2. After each response: Stores conversation for future reference
  3. No manual tool calls needed - fully automatic

Manual storage:

store_in_kb(
    content="Important information to remember...",
    title="Project Context",
    knowledge_base_id="optional-kb-id"
)

Sub-Agent Creation

Delegate tasks to specialized agents via GitHub Actions:

# Create sub-agent with specific model and tools
create_subagent(
    repository="owner/repo",
    workflow_id="agent.yml",
    task="Analyze this dataset and provide insights",
    model="us.anthropic.claude-sonnet-4-20250514-v1:0",
    provider="bedrock",
    max_tokens=60000,
    tools="file_read,python_repl,calculator,http_request"
)

# Custom system prompt for specialized behavior
create_subagent(
    repository="owner/repo",
    workflow_id="agent.yml",
    task="Review code and suggest improvements",
    tools="file_read,editor,shell",
    system_prompt="You are a senior code reviewer focused on best practices"
)

# Check sub-agent status
create_subagent(action="status", repository="owner/repo", workflow_id="agent.yml", run_id="12345")

# List recent runs
create_subagent(action="list", repository="owner/repo", workflow_id="agent.yml")

๐Ÿ“‹ All Built-in Tools (38 total)

DevDuck Core (17 tools)

  • system_prompt - Update agent's system prompt (GitHub sync support)
  • store_in_kb - Store content in Bedrock Knowledge Base
  • state_manager - Save/restore agent state (time-travel)
  • tcp - TCP server with real-time streaming
  • websocket - WebSocket server with concurrent messaging
  • ipc - Unix socket IPC server for local processes
  • mcp_server - Expose as MCP server (HTTP/stdio)
  • install_tools - Install packages and load tools at runtime
  • create_subagent - Spawn sub-agents via GitHub Actions
  • use_github - GitHub GraphQL API operations
  • tray - System tray app control (macOS)
  • ambient - Ambient AI input overlay (macOS)
  • agentcore_config - Configure & launch on Bedrock AgentCore
  • agentcore_invoke - Invoke deployed AgentCore agents
  • agentcore_logs - View CloudWatch logs from agents
  • agentcore_agents - List/manage agent runtimes
  • manage_tools - Runtime tool add/remove/reload
  • view_logs - View/search/clear DevDuck logs

Strands Tools (13 tools)

  • shell - Interactive shell with PTY support
  • editor - File editing (view/create/replace/insert/undo)
  • file_read - Multi-file reading with search modes
  • file_write - Write content to files
  • file_read - Read files with document mode for PDFs/CSVs
  • calculator - SymPy-powered math (solve/derive/integrate)
  • image_reader - Read images for Converse API
  • use_agent - Nested agent with different model
  • load_tool - Load custom tools from Python files
  • environment - Environment variable management
  • mcp_client - Connect to external MCP servers autonomously
  • retrieve - Bedrock Knowledge Base retrieval
  • speak - Text-to-speech (macOS say or AWS Polly)
  • slack - Slack messaging and event handling

Strands Fun Tools (6 tools - macOS)

  • listen - Background speech transcription (Whisper)
  • cursor - Mouse & keyboard control
  • clipboard - Clipboard monitoring & control
  • screen_reader - OCR & UI element detection
  • bluetooth - BLE scanning and GATT operations
  • yolo_vision - Object detection with YOLO

Community Tools (./tools/)

  • fetch_github_tool - Fetch and load tools from GitHub repos
  • gist - Comprehensive GitHub Gist management (create/update/fork/star/comment)
  • scraper - HTML/XML parsing with BeautifulSoup4
  • add_comment - Add comments to GitHub issues/PRs
  • list_issues - List GitHub repository issues
  • list_pull_requests - List GitHub repository PRs

Plus: Hot-reload tools from ./tools/ directory when DEVDUCK_LOAD_TOOLS_FROM_DIR=true


Hot-Reload Example

# ./tools/weather.py
from strands import tool
import requests

@tool
def weather(city: str) -> str:
    """Get weather for a city."""
    r = requests.get(f"https://wttr.in/{city}?format=%C+%t")
    return r.text

Save โ†’ use instantly:

๐Ÿฆ† weather(city="Tokyo")
# Clear sky +15ยฐC

No restart. No configuration. Just works.


Access Methods

Protocol Endpoint Test Command Use Case
CLI Terminal devduck "query" Interactive/one-shot
Python Import import devduck; devduck("query") Script integration
TCP localhost:9999 nc localhost 9999 Network clients
WebSocket localhost:8080 wscat -c ws://localhost:8080 Browser/async apps
MCP localhost:8000/mcp Add to Claude Desktop MCP clients
IPC /tmp/devduck_main.sock nc -U /tmp/devduck_main.sock Local processes

Custom ports:

export DEVDUCK_TCP_PORT=9000 DEVDUCK_WS_PORT=8001 DEVDUCK_MCP_PORT=8002
devduck

Disable servers:

export DEVDUCK_ENABLE_TCP=false DEVDUCK_ENABLE_MCP=false
devduck

Configuration

Variable Default Description
Model
MODEL_PROVIDER Auto Manual override: bedrock, anthropic, openai, github, gemini, cohere, writer, mistral, litellm, llamaapi, mlx, ollama
STRANDS_MODEL_ID Auto Model name (e.g., claude-sonnet-4, gpt-4o, qwen3:1.7b)
Provider API Keys
ANTHROPIC_API_KEY - Anthropic API key (auto-detected)
OPENAI_API_KEY - OpenAI API key (auto-detected)
GOOGLE_API_KEY / GEMINI_API_KEY - Google Gemini API key (auto-detected)
GITHUB_TOKEN / PAT_TOKEN - GitHub token for GitHub Models (auto-detected)
COHERE_API_KEY - Cohere API key (auto-detected)
WRITER_API_KEY - Writer API key (auto-detected)
MISTRAL_API_KEY - Mistral API key (auto-detected)
LITELLM_API_KEY - LiteLLM API key (auto-detected)
LLAMAAPI_API_KEY - LlamaAPI key (auto-detected)
Tools
DEVDUCK_TOOLS 38 tools Format: package1:tool1,tool2;package2:tool3
DEVDUCK_LOAD_TOOLS_FROM_DIR false Auto-load from ./tools/ directory
Memory
DEVDUCK_KNOWLEDGE_BASE_ID - Bedrock KB ID for auto-RAG
SYSTEM_PROMPT - Additional system prompt content
MCP
MCP_SERVERS - JSON config for external MCP servers
Servers
DEVDUCK_TCP_PORT 9999 TCP server port
DEVDUCK_WS_PORT 8080 WebSocket server port
DEVDUCK_MCP_PORT 8000 MCP server port
DEVDUCK_IPC_SOCKET /tmp/devduck_main.sock IPC socket path
DEVDUCK_ENABLE_TCP true Enable TCP server
DEVDUCK_ENABLE_WS true Enable WebSocket server
DEVDUCK_ENABLE_MCP true Enable MCP server
DEVDUCK_ENABLE_IPC true Enable IPC server
Context
DEVDUCK_LOG_LINE_COUNT 50 Recent log lines in context
DEVDUCK_LAST_MESSAGE_COUNT 200 Recent messages in context

Troubleshooting

Ollama model not found:

# DevDuck auto-pulls models, but if it fails:
ollama pull qwen3:1.7b

Port already in use:

# Change ports
export DEVDUCK_TCP_PORT=9000
export DEVDUCK_WS_PORT=8001
devduck

Hot-reload not working:

# Ensure tools directory exists
mkdir -p ./tools

# Check file watcher logs
devduck
๐Ÿฆ† view_logs(action="search", pattern="watcher")

Memory/performance issues:

# Use lighter model
export STRANDS_MODEL_ID="qwen3:0.5b"

# Reduce context
export DEVDUCK_LOG_LINE_COUNT=20
export DEVDUCK_LAST_MESSAGE_COUNT=50

Ambient overlay not starting:

# Make sure tkinter is installed
python3 -c "import tkinter"

# Install tkinter if missing
brew install python-tk@3.13  # macOS
sudo apt-get install python3-tk  # Ubuntu/Debian
sudo dnf install python3-tkinter  # Fedora

Tray app not starting (macOS):

# Install rumps
pip install rumps

# Or reinstall devduck
pip install -e .

View logs: devduck โ†’ ๐Ÿฆ† view_logs()


GitHub Actions

Run DevDuck in CI/CD pipelines:

name: AI Code Assistant
on: 
  issues:
    types: [opened, edited]
  pull_request:
    types: [opened, edited, synchronize]

jobs:
  devduck:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write
      pull-requests: write
    steps:
      - uses: cagataycali/devduck@main
        with:
          task: "Analyze and help with this issue or PR"
          provider: "github"
          model: "gpt-4o"
          tools: "shell,file_read,file_write,use_github,calculator"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Sub-agent workflows:

devduck("Create a sub-agent to analyze test coverage")

Resources


Citation

@software{devduck2025,
  author = {Cagatay Cali},
  title = {DevDuck: Self-Modifying AI Agent with Hot-Reload and Multi-Protocol Servers},
  year = {2025},
  url = {https://github.com/cagataycali/devduck}
}

Apache 2.0 | Built with Strands Agents | @cagataycali

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

devduck-0.1.1766644714.tar.gz (210.9 kB view details)

Uploaded Source

Built Distribution

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

devduck-0.1.1766644714-py3-none-any.whl (120.6 kB view details)

Uploaded Python 3

File details

Details for the file devduck-0.1.1766644714.tar.gz.

File metadata

  • Download URL: devduck-0.1.1766644714.tar.gz
  • Upload date:
  • Size: 210.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for devduck-0.1.1766644714.tar.gz
Algorithm Hash digest
SHA256 ffec702eac1017fd644bc96bcf101ab56b171a2d597a03b2974de0f915b591c6
MD5 982361ec8b1664b6439b1bc5e16602c0
BLAKE2b-256 5458785755ab41e237a9e42feffa1307f825f562145799e220bb75621ccde539

See more details on using hashes here.

File details

Details for the file devduck-0.1.1766644714-py3-none-any.whl.

File metadata

File hashes

Hashes for devduck-0.1.1766644714-py3-none-any.whl
Algorithm Hash digest
SHA256 0e777b81e39878b8e8d0393aeb3ab00d281d175ca46c75dfe3af69c169c89772
MD5 a67e756b6f0d843499b85b85baa8a2ab
BLAKE2b-256 aa31109a986b96f852946b8e2bd2d369eafc4a8693d22c7eb1942328c710512a

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