Skip to main content

Local runtime host for long-running Deep Agents channels and schedules (experimental)

Project description

Deep Agents Talon

Deep Agents Talon is the local runtime host for long-running Deep Agents. It owns the process lifecycle for channel adapters, cron schedulers, and the agent runtime in a single event loop.

Experimental: Talon is an experimental, alpha-status runtime and is subject to change or removal at any time. It is not intended for production or enterprise use.

Security support: Talon does not yet implement production-grade security controls such as complete human-in-the-loop (HITL) approval policy, channel administrator controls, sandbox-backed execution isolation, or multi-tenant boundaries. Channel access should be treated as direct access to the operator's agent, model credentials, MCP tools, and local host resources. We do not accept security vulnerability reports for the absence of these known, unimplemented Talon hardening features while Talon remains experimental.

Talon currently includes:

  • A host process with graceful shutdown, per-conversation serialization, and /stop cancellation.
  • A generic channel protocol plus a WhatsApp adapter backed by a loopback Node bridge.
  • A persistent cron scheduler with agent-facing cron tool helpers.
  • MCP tool loading from explicit config paths or ~/.deepagents/.mcp.json.
  • Optional LangSmith tracing for each channel or cron-triggered run.

Quickstart

Run the commands in this README from libs/talon. From the repository root, prefix uv commands with --directory libs/talon.

cd libs/talon
uv sync --group test
AGENT_ASSISTANT_ID=local AGENT_MODEL=<provider>:<model-id> uv run deepagents-talon --once

If AGENT_MODEL is unset, Talon starts with the echo runtime. This is useful for checking host lifecycle and channel wiring without provider credentials.

Assistant state lives under ~/.deepagents/<assistant_id>/ by default. The host creates restrictive state directories for the materialized agent manifest, channel sessions, and cron jobs. The default local execution workspace is the current working directory; set DEEPAGENTS_TALON_WORKSPACE to use a different directory. The per-invocation graph recursion limit defaults to 500; set DEEPAGENTS_TALON_RECURSION_LIMIT to tune it.

Tool Approval Overrides

Set DEEPAGENTS_TALON_INTERRUPT_ON_TOOLS to a comma-separated list of tool names that should always require Talon's channel approval flow. This local override is additive with agent-provided HITL configuration and applies to MCP or local runtime tools.

DEEPAGENTS_TALON_INTERRUPT_ON_TOOLS=bash,execute,github_create_pr

WhatsApp

The WhatsApp channel uses a local Node bridge packaged with this library. The Python adapter talks to the bridge over loopback only.

cd deepagents_talon/channels/whatsapp_bridge
npm install
cd ../../..

DEEPAGENTS_TALON_WHATSAPP_ENABLED=true \
DEEPAGENTS_TALON_WHATSAPP_START_BRIDGE=true \
AGENT_ASSISTANT_ID=whatsapp-local \
AGENT_MODEL=<provider>:<model-id> \
uv run deepagents-talon --whatsapp

The bridge prints a QR code during pairing. By default, inbound exposure is self, so only messages from the paired account trigger the agent. Configure DEEPAGENTS_TALON_WHATSAPP_EXPOSURE=allowlist with DEEPAGENTS_TALON_WHATSAPP_ALLOWLIST_CHATS or DEEPAGENTS_TALON_WHATSAPP_MENTION_PATTERNS to allow specific chats. DEEPAGENTS_TALON_WHATSAPP_OPERATOR_ID accepts one or more comma-separated operator IDs for self exposure. Outbound WhatsApp messages include a deepagents bot header by default so self-message conversations clearly distinguish agent replies from operator messages. Set DEEPAGENTS_TALON_WHATSAPP_BOT_HEADER to customize that label. Markdown image/video references in assistant replies may attach files only when they are relative paths inside DEEPAGENTS_TALON_OUTBOUND_MEDIA_DIR, or inside DEEPAGENTS_TALON_WORKSPACE when no outbound media directory is configured. DEEPAGENTS_TALON_MAX_MEDIA_BYTES caps inbound and outbound channel media across providers and defaults to 1073741824 (1 GiB), but WhatsApp is clamped to 67108864 (64 MiB) because the bridge library materializes downloads in memory before writing them.

Inbound voice transcription is opt-in:

DEEPAGENTS_TALON_VOICE_TRANSCRIPTION_ENABLED=true

When enabled without DEEPAGENTS_TALON_VOICE_TRANSCRIPTION_MODEL, Talon uses the same local default as the original WhatsApp example: nvidia/parakeet-tdt-0.6b-v3 through Transformers, with ffmpeg converting inbound audio to 16 kHz mono WAV first. Set DEEPAGENTS_TALON_VOICE_TRANSCRIPTION_DEVICE=cuda to use a GPU. The legacy example variables SPEECH_ENABLED and SPEECH_DEVICE are also accepted. Setting DEEPAGENTS_TALON_VOICE_TRANSCRIPTION_MODEL to a non-Parakeet model keeps the existing OpenAI SDK transcription path.

open exposure allows arbitrary WhatsApp senders to trigger the agent while it runs with the operator's model credentials, channel credentials, MCP tool access, and local-host access when the local execution backend is active. Enabling it requires explicit acknowledgement:

DEEPAGENTS_TALON_WHATSAPP_EXPOSURE=open
DEEPAGENTS_TALON_WHATSAPP_OPEN_ACK=allow-arbitrary-senders

See ../../examples/talon-whatsapp/ for a runnable Docker Compose topology and .env reference.

Telegram

The Telegram channel uses the Bot API with long polling. Provide a bot token from BotFather and a model so Talon runs the real Deep Agents runtime instead of the echo runtime:

DEEPAGENTS_TALON_TELEGRAM_ENABLED=true \
DEEPAGENTS_TALON_TELEGRAM_BOT_TOKEN=... \
DEEPAGENTS_TALON_TELEGRAM_EXPOSURE=allowlist \
DEEPAGENTS_TALON_TELEGRAM_ALLOWLIST_USERS=123456789 \
DEEPAGENTS_TALON_TELEGRAM_ALLOWLIST_CHATS=-1001234567890 \
AGENT_ASSISTANT_ID=telegram-local \
AGENT_MODEL=<provider>:<model-id> \
uv run deepagents-talon --telegram

From the repository root, run the same host with:

DEEPAGENTS_TALON_TELEGRAM_ENABLED=true \
DEEPAGENTS_TALON_TELEGRAM_BOT_TOKEN=... \
DEEPAGENTS_TALON_TELEGRAM_EXPOSURE=allowlist \
DEEPAGENTS_TALON_TELEGRAM_ALLOWLIST_USERS=123456789 \
DEEPAGENTS_TALON_TELEGRAM_ALLOWLIST_CHATS=-1001234567890 \
AGENT_ASSISTANT_ID=telegram-local \
AGENT_MODEL=<provider>:<model-id> \
uv run --directory libs/talon deepagents-talon --telegram

In allowlist mode, DEEPAGENTS_TALON_TELEGRAM_ALLOWLIST_USERS allows private bot DMs from specific Telegram user IDs, while DEEPAGENTS_TALON_TELEGRAM_ALLOWLIST_CHATS allows channel posts from specific channel chat IDs. DEEPAGENTS_TALON_TELEGRAM_OPERATOR_ID accepts one or more comma-separated operator IDs for self exposure. DEEPAGENTS_TALON_MAX_MEDIA_BYTES caps inbound and outbound channel media across providers and defaults to 1073741824 (1 GiB); Telegram's smaller Bot API upload limits still apply. If AGENT_MODEL and DEEPAGENTS_TALON_MODEL are both unset, Talon uses the echo runtime and replies with the inbound text unchanged.

Tracing

LangSmith tracing is opt-in. Set both values before starting the host:

LANGSMITH_TRACING=true
LANGSMITH_API_KEY=...
LANGSMITH_PROJECT=deepagents-talon

When enabled, Talon wraps each agent run in a LangSmith tracing context with assistant id, conversation id, trigger metadata, and source message metadata.

MCP Tools

Talon loads MCP servers from one config file. It checks DEEPAGENTS_TALON_MCP_CONFIG, then MCP_CONFIG, then ~/.deepagents/.mcp.json. For user-level MCP servers, edit ~/.deepagents/.mcp.json:

{
  "mcpServers": {
    "linear": {
      "type": "http",
      "url": "https://mcp.example/mcp"
    }
  }
}

Run deepagents-talon mcp config to print the resolved config paths, and deepagents-talon mcp login <server> for OAuth-backed servers.

Fleet zip exports can be materialized into a Talon-local agent directory before starting the host:

deepagents-talon import-fleet <fleet-export.zip> [--assistant-id <id>] [--target-dir <dir>]

From the repository root:

uv run --directory libs/talon deepagents-talon import-fleet ./fleet-export.zip \
  --assistant-id local

By default, import-fleet writes into the selected assistant manifest directory: ~/.deepagents/<assistant_id>/, with subagent prompts in ~/.deepagents/<assistant_id>/agents/. The selected assistant id comes from DEEPAGENTS_TALON_ASSISTANT_ID or AGENT_ASSISTANT_ID; when neither is set, the importer uses the Fleet export filename stem. For example, crowbar.zip imports into ~/.deepagents/crowbar/. Pass --assistant-id <id> to select a different assistant for the import, or --target-dir <dir> to write all imported files under an explicit directory.

The importer writes Fleet prompts, skills, and subagent prompts. Fleet tools.json is read only as import input and is not copied into the Talon agent directory. Fleet config.json is ignored. Talon does not support the old Fleet direct-run startup path or its environment variables; import the zip first, then run Talon against the materialized local assistant.

When Fleet MCP tools are present, the importer writes .mcp.json in the target agent directory. This is the runtime MCP config loaded by Talon and contains the sanitized OAuth server entries from the Fleet export. The importer also writes .mcp.json.setup as a human-readable setup handoff for the operator:

{
  "mcpServers": {
    "fleet-tools": {
      "type": "http",
      "url": "https://tools.example.com/mcp",
      "auth": "oauth",
      "allowedTools": ["github_get_file", "github_create_pull_request"]
    }
  }
}

For non-OAuth servers or local edits, keep credentials in environment variables or another local secret source rather than in committed files:

{
  "mcpServers": {
    "internal-tools": {
      "command": "internal-mcp-server",
      "args": ["--token-env", "INTERNAL_MCP_TOKEN"]
    }
  }
}

If the Fleet export contains interrupt-enabled tools, the import summary prints the recommended DEEPAGENTS_TALON_INTERRUPT_ON_TOOLS value. Set that value when starting Talon so those tools continue to require channel approval:

DEEPAGENTS_TALON_INTERRUPT_ON_TOOLS=github_create_pull_request,github_update_file \
AGENT_ASSISTANT_ID=local \
AGENT_MODEL=<provider>:<model-id> \
deepagents-talon --telegram

Cron Observability

Cron jobs are persisted in cron/jobs.json under the assistant state directory. Scheduler lifecycle events are emitted through the standard Python logger as talon_event JSON records:

  • cron.tick
  • cron.dispatch
  • cron.success
  • cron.failure
  • cron.delivery
  • cron.delivery_suppressed
  • cron.delivery_failure

These logs complement the persisted last_status and last_error fields.

Security and Data Lifecycle

Talon is single-operator by design. It does not provide multi-tenant isolation, sandbox-backed execution isolation, production-grade HITL policy enforcement, or channel administrator boundaries. Any tool approval prompt surfaced through a channel is an experimental convenience feature, not a complete security boundary. Channel exposure should be treated as direct access to the operator's agent, model credentials, MCP tools, and local host resources.

Do not file security vulnerability reports for the absence of these known, unimplemented hardening features in Talon while it remains experimental. Reports about missing enterprise controls, channel admin gates, sandbox integrations, or production HITL policy are considered feature requests for a future production-ready runtime.

Attacker-influenceable inputs include channel message text, voice transcripts, channel media metadata, downloaded media files when a channel adapter persists them for processing, web or search result content, MCP tool results, and imported manifest instructions. Treat all of those inputs as untrusted content entering the agent context.

Outbound data leaves Talon through these integrations:

  • Model providers receive conversation text, cron prompts, voice transcripts, selected tool outputs, and system or manifest instructions.
  • LangSmith receives trace metadata and serialized run inputs/outputs when LANGSMITH_TRACING=true.
  • MCP servers receive tool arguments chosen by the model and may receive conversation-derived values.
  • Tavily or other search tools receive query strings chosen by the model and may include conversation-derived values.
  • Channel providers receive assistant replies and outbound media paths supplied to the channel adapter.

Sensitive local state is stored under ~/.deepagents/<assistant_id>/ by default with 0700 directories and 0600 cron files:

  • AGENTS.md, skills/, and agents/ store the materialized assistant instructions, skills, and subagent definitions.
  • cron/jobs.json stores cron prompts, origin conversation ids, message ids, run status, and errors. Active jobs are retained while enabled. Completed jobs are deleted on startup after DEEPAGENTS_TALON_CRON_RETENTION_DAYS, default 30.
  • channels/whatsapp/ stores WhatsApp LocalAuth credentials and Chromium profile state. These credentials are retained until the operator deletes the directory, because automatic deletion would silently unpair the channel.
  • media/inbound/ is reserved for downloaded inbound media. Files older than DEEPAGENTS_TALON_INBOUND_MEDIA_RETENTION_HOURS, default 24, are deleted on startup. Inbound and outbound channel media are capped by DEEPAGENTS_TALON_MAX_MEDIA_BYTES, default 1073741824 (1 GiB); WhatsApp is further clamped to 67108864 (64 MiB). The WhatsApp bridge stores downloaded inbound media under the assistant's inbound media directory and passes local paths plus MIME metadata to the host.

Conversation persistence is intentionally not durable yet. Runtime conversation state is in-memory unless a future backend explicitly adds thread persistence.

Development

uv sync --group test
uv run --group test pytest tests/
uv run deepagents-talon

Focused verification:

make lint
make test

Resources

  • LangChain Academy — Comprehensive, free courses on LangChain libraries and products, made by the LangChain team.
  • Code of Conduct — community guidelines and standards

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

deepagents_talon-0.0.3.tar.gz (411.5 kB view details)

Uploaded Source

Built Distribution

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

deepagents_talon-0.0.3-py3-none-any.whl (112.6 kB view details)

Uploaded Python 3

File details

Details for the file deepagents_talon-0.0.3.tar.gz.

File metadata

  • Download URL: deepagents_talon-0.0.3.tar.gz
  • Upload date:
  • Size: 411.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for deepagents_talon-0.0.3.tar.gz
Algorithm Hash digest
SHA256 7d8e3c1bd8ab87fc494c0c1395c11a148e55a13c8d1e36709a49ef6652df695f
MD5 9eaf8fd41aceb6efb087fae896610ee2
BLAKE2b-256 618d2364494d8190e8d92aedb2552ca968d23821f3a6bc02934b42aa9f140e28

See more details on using hashes here.

File details

Details for the file deepagents_talon-0.0.3-py3-none-any.whl.

File metadata

File hashes

Hashes for deepagents_talon-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 a7d9d86ac1e1cde2db716582690bbbdd22ac1979b7f2f1532b2b57eaa5763a69
MD5 4367bd992cec94424bc40acdf96c4e10
BLAKE2b-256 0de6336cad242703845d5d3071d19c42917b580a423c5f0b9052e77e2b345742

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