mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-10-27 21:50:36 +00:00
* fix(benchmark): validate sandbox lifecycle and concurrent measurements * feat(sandbox): prewarm likely AIO tool turns (cherry picked from commit 3a1017ed032ed9331987bc3dc61f23dcdac4e905) * fix(sandbox): bind bounded prewarming to execution leases * docs: trim frontend guidance below its existing size limit * fix(benchmark): separate failed lifecycle stage timings * test(sandbox): measure prewarm overlap and unused resources through agent graphs * fix(sandbox): finish lease and sampler cleanup after cancellation or errors * docs(benchmark): distinguish initialization wait from model overlap * docs(helm): align the configuration example with version 61 * fix(sandbox): preserve synchronous agent graphs when prewarming is enabled * test(cargo): isolate native fixtures from inherited make jobserver flags * fix(sandbox): require managed cleanup before prewarming * fix(sandbox): log denied prewarming as an expected skip * fix(benchmark): filter provider summary input records --------- Co-authored-by: nothingyuancando <1579035512@qq.com>
572 lines
25 KiB
YAML
572 lines
25 KiB
YAML
# DeerFlow Helm chart values
|
|
#
|
|
# Copy to my-values.yaml, edit, and install with:
|
|
# helm install deer-flow deploy/helm/deer-flow -n deer-flow --create-namespace -f my-values.yaml
|
|
|
|
# -- Target namespace (also used as the K8s sandbox namespace for provisioner-spawned Pods).
|
|
namespace: deer-flow
|
|
|
|
# -- Image registry & tag for the three DeerFlow images you build+push.
|
|
# Required: set `registry` to your registry (e.g. ghcr.io/yourorg).
|
|
image:
|
|
registry: "" # REQUIRED, e.g. ghcr.io/yourorg
|
|
tag: "latest"
|
|
pullPolicy: IfNotPresent
|
|
# -- Existing image pull secrets, e.g. [{ name: regcred }]
|
|
pullSecrets: []
|
|
|
|
# Image names match what .github/workflows/container.yaml publishes on GHCR
|
|
# as ${repository}-<name> (e.g. ghcr.io/<owner>/deer-flow-backend). Set
|
|
# `registry` to the owner prefix (e.g. ghcr.io/<owner>) and `tag` to consume
|
|
# the published images.
|
|
gatewayImage: deer-flow-backend
|
|
frontendImage: deer-flow-frontend
|
|
provisionerImage: deer-flow-provisioner
|
|
|
|
# -- Gateway (backend) deployment.
|
|
gateway:
|
|
# Replica count. 1 is the conservative default; >1 is supported for the web
|
|
# and API path once the prerequisites below hold, all of which this chart
|
|
# sets in `config` by default: Postgres (`database` + `checkpointer`),
|
|
# `run_events.backend: db`, `run_ownership.heartbeat_enabled: true` and the
|
|
# Redis stream bridge (sandbox ownership leases are inferred from it). The
|
|
# chart also exports DEER_FLOW_MULTI_INSTANCE=true when replicas > 1 so the
|
|
# Gateway's startup gate enforces those prerequisites instead of staying
|
|
# inert (its worker count only sees one Pod). IM channels follow
|
|
# `channels.leader_lease` in `config` (default `auto`, on with replicas > 1):
|
|
# one Pod holds each platform connection and another takes over when it
|
|
# dies; the startup gate refuses `enabled: false` while channels are enabled
|
|
# (see the chart README). Still single-instance: the WeChat QR login and
|
|
# browser tools.
|
|
# Multi-node clusters also need `persistence.home.accessMode: ReadWriteMany`,
|
|
# and `agent_storage.backend: db` keeps custom agents visible on every Pod.
|
|
# Memory stays on that shared volume, but DeerMem's SQLite retrieval index is
|
|
# Pod-local (`memory.backend_config.retrieval_index_path` in `config`, on an
|
|
# emptyDir at /var/lib/deerflow/memory-index); keep that line when you
|
|
# override `config`, or the Gateway warns at startup and every Pod shares one
|
|
# WAL database over the network filesystem.
|
|
# Scheduler multi_instance recovery is safe only when its config
|
|
# prerequisites are met; max_concurrent_runs is shared across Pods then.
|
|
replicas: 1
|
|
# Explicit multi-instance declaration (boolean). Leave unset (null) to derive
|
|
# it from `replicas` above. Set `true` before scaling the gateway with
|
|
# `kubectl scale` or an HPA: those change the replica count without a Helm
|
|
# upgrade, so the derived DEER_FLOW_MULTI_INSTANCE, the PodDisruptionBudget
|
|
# and the required shared AUTH_JWT_SECRET would otherwise keep their
|
|
# single-replica rendering. Note the PodDisruptionBudget (minAvailable: 1)
|
|
# is rendered as soon as this is true: until the scale-up actually happens
|
|
# it blocks voluntary evictions and node drains of the single Pod. Set
|
|
# podDisruptionBudget.enabled: false for that interim if you need to drain.
|
|
multiInstance: null
|
|
# Rollout strategy. Surge-then-drain keeps one Pod serving while a peer
|
|
# starts; with run-ownership heartbeats the new Pod leaves the old Pod's live
|
|
# runs alone (their leases keep renewing) while the old Pod drains them.
|
|
strategy:
|
|
type: RollingUpdate
|
|
rollingUpdate:
|
|
maxSurge: 1
|
|
maxUnavailable: 0
|
|
# PodDisruptionBudget, rendered only for a multi-instance gateway (replicas
|
|
# > 1 or multiInstance: true; a budget of 1 on a single replica would block
|
|
# node drains). minAvailable is an integer or a percentage string such as
|
|
# "50%" (quoted; a plain `int` cast would turn it into 0) and falls back to
|
|
# 1 when unset. 0 and "0%" fail the render -- a zero budget protects
|
|
# nothing -- so disable the budget instead.
|
|
podDisruptionBudget:
|
|
enabled: true
|
|
minAvailable: 1
|
|
# uvicorn --timeout-graceful-shutdown (seconds): how long open HTTP
|
|
# connections (long SSE streams included) may hold up lifespan shutdown
|
|
# after SIGTERM before uvicorn closes them. Without a bound one idle SSE
|
|
# client can push the whole shutdown past the grace period into SIGKILL.
|
|
# 0 closes open connections immediately on SIGTERM.
|
|
uvicornGracefulShutdownSeconds: 10
|
|
# Pod termination grace period (seconds). MUST exceed the Gateway's graceful
|
|
# shutdown work: preStopSleepSeconds + uvicornGracefulShutdownSeconds + the
|
|
# lifespan's worst case (five 5s-bounded hooks: trash sweep, notification
|
|
# worker, channel service, browser sessions, MCP session pool; the 1s
|
|
# retrieval-warm wait; the 5s run drain; the memory queue drain,
|
|
# memory.shutdown_flush_timeout_seconds, default 30s -- about 61s) + buffer.
|
|
# backend/tests/_gateway_shutdown_budget.py pins the arithmetic. K8s defaults
|
|
# to 30s, which SIGKILLs the memory drain mid-flight and silently re-introduces
|
|
# the memory loss that shutdown_flush is fixing. Raise this when you raise the
|
|
# memory timeout. See gateway-deployment.yaml + README "Graceful shutdown".
|
|
terminationGracePeriodSeconds: 90
|
|
# preStop hook sleep (seconds) before SIGTERM, so the Service/ingress
|
|
# deregisters the pod and in-flight HTTP requests drain before graceful
|
|
# shutdown begins (which runs the memory queue drain). 0 disables the hook.
|
|
# Counts against terminationGracePeriodSeconds.
|
|
preStopSleepSeconds: 5
|
|
resources:
|
|
requests:
|
|
cpu: 200m
|
|
memory: 512Mi
|
|
limits:
|
|
cpu: "2"
|
|
memory: 2Gi
|
|
|
|
# -- Frontend (Next.js) deployment.
|
|
frontend:
|
|
replicas: 1
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 512Mi
|
|
|
|
# -- nginx reverse-proxy deployment (preserves compose routing).
|
|
nginx:
|
|
replicas: 1
|
|
image:
|
|
repository: nginx
|
|
tag: alpine
|
|
resources:
|
|
requests:
|
|
cpu: 50m
|
|
memory: 64Mi
|
|
limits:
|
|
cpu: 500m
|
|
memory: 256Mi
|
|
service:
|
|
# -- Service type fronting nginx. `LoadBalancer` on Docker Desktop / kind /
|
|
# OrbStack routes to localhost (no Ingress controller needed). `ClusterIP`
|
|
# pairs with the Ingress resource. `NodePort` exposes on a node port.
|
|
type: ClusterIP
|
|
port: 2026
|
|
loadBalancerIP: ""
|
|
nodePort: ""
|
|
|
|
# -- Sandbox provisioner (K8s-native code execution). Creates sandbox Pods in
|
|
# this namespace via a ServiceAccount + RBAC.
|
|
provisioner:
|
|
enabled: true
|
|
# The gateway authenticates to the provisioner with PROVISIONER_API_KEY,
|
|
# which the chart generates into the `<release>-app` Secret (see
|
|
# existingAppSecret) and injects into both Pods; `config.sandbox` below
|
|
# references it as `provisioner_api_key: $PROVISIONER_API_KEY`. The
|
|
# provisioner rejects every /api/* request without a matching key. With
|
|
# `enabled: false` the gateway takes PROVISIONER_API_KEY from `secrets` /
|
|
# `existingSecret` when you supply one (external provisioner); otherwise
|
|
# its start command defaults the variable to "", so the default `config`
|
|
# below still loads even when a user-managed Secret lacks the key.
|
|
# Replica count. 1 is the conservative default, matching the gateway; >1 is
|
|
# safe as the provisioner stands: it keeps no state of its own between
|
|
# requests -- the sandbox Pods and Services it labels (`app=deer-flow-sandbox`,
|
|
# `sandbox-id`) are the only registry, every handler reads them back from
|
|
# the API server, and create tolerates the 409 AlreadyExists a concurrent
|
|
# creator on another replica produces (the race several gateway Pods already
|
|
# run against one provisioner). NodePorts are allocated by the API server,
|
|
# never by the provisioner. The `provisioner` Service spreads requests over
|
|
# every replica, so with 1 replica this is the last single point of failure
|
|
# in a multi-replica gateway deployment: while its Pod restarts or its node
|
|
# drains no sandbox can be created or discovered. Scaling it changes nothing
|
|
# else in the chart, so there is no multiInstance switch here.
|
|
replicas: 1
|
|
# Rollout strategy. Surge-then-drain keeps one Pod answering sandbox calls
|
|
# while a peer starts; a replica has nothing to hand over beyond its
|
|
# in-flight requests, so the default termination grace period is enough.
|
|
strategy:
|
|
type: RollingUpdate
|
|
rollingUpdate:
|
|
maxSurge: 1
|
|
maxUnavailable: 0
|
|
# PodDisruptionBudget, rendered only for replicas > 1 (a budget of 1 on a
|
|
# single replica would block node drains). minAvailable is an integer or a
|
|
# percentage string such as "50%" and falls back to 1 when unset; 0 and
|
|
# "0%" fail the render -- a zero budget protects nothing -- so disable the
|
|
# budget instead. Scaling with `kubectl scale` instead of `replicas` leaves
|
|
# the budget unrendered.
|
|
podDisruptionBudget:
|
|
enabled: true
|
|
minAvailable: 1
|
|
resources:
|
|
requests:
|
|
cpu: 50m
|
|
memory: 128Mi
|
|
limits:
|
|
cpu: 500m
|
|
memory: 512Mi
|
|
# -- AIO-compatible sandbox container image used for sandbox Pods.
|
|
sandboxImage: "enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest"
|
|
# -- Service type for per-sandbox Services. `ClusterIP` (default) exposes
|
|
# sandboxes only inside the cluster via Service DNS - correct for the
|
|
# in-cluster gateway and avoids binding the code-execution surface on
|
|
# every node's interfaces. `NodePort` is the Docker-Compose/hybrid escape
|
|
# hatch (used when the gateway is not in K8s); pair with `nodeHost`.
|
|
sandboxServiceType: "ClusterIP"
|
|
# -- Host the gateway uses to reach sandbox NodePorts. Only consulted when
|
|
# `sandboxServiceType: NodePort`. Empty (default) falls back to the
|
|
# provisioner pod's node IP via the Kubernetes downward API, which routes
|
|
# on most clusters because a NodePort is exposed on every node. Set
|
|
# explicitly only when pod->node-IP traffic is blocked by your
|
|
# CNI/network policy. In Docker Compose this is `host.docker.internal`.
|
|
nodeHost: ""
|
|
# -- Sandbox container port (must match the sandboxImage's listening port).
|
|
sandboxPort: 8080
|
|
# -- Optional lark-cli init image (Pattern A). Empty (default) leaves the
|
|
# sandbox without a lark-cli runtime, so an in-sandbox `lark-cli` call
|
|
# fails with "command not found". When set (e.g.
|
|
# `deer-flow/lark-cli-init:v1.0.65`), sandbox Pods requesting the runtime
|
|
# get an init container + shared emptyDir instead of a hostPath/PVC mount.
|
|
# Mirrors compose's `LARK_CLI_INIT_IMAGE`. See `docker/lark-cli-init/`.
|
|
larkCliInitImage: ""
|
|
# -- Optional lark-cli broker image (Pattern B, issue #4338). When set, the
|
|
# sandbox gets a shim + a `lark-cli-broker` sidecar that holds the
|
|
# credentials, so the plaintext config/data dirs are never mounted into
|
|
# the sandbox. Supersedes `larkCliInitImage` when both are set. Empty
|
|
# (default) ⇒ broker off. Mirrors compose's `LARK_CLI_BROKER_IMAGE`.
|
|
# See `docker/lark-cli-broker/`.
|
|
larkCliBrokerImage: ""
|
|
|
|
# -- PostgreSQL database. Bundled mode (default) deploys a single-instance
|
|
# postgres StatefulSet; set `enabled: false` to use an external managed DB.
|
|
# The gateway reads DATABASE_URL from the resolved Secret and config.yaml
|
|
# references it as $DATABASE_URL in database.postgres_url.
|
|
postgresql:
|
|
# -- Deploy a bundled postgres StatefulSet. Disable to use an external DB.
|
|
enabled: true
|
|
image:
|
|
repository: postgres
|
|
tag: "16"
|
|
auth:
|
|
database: deerflow
|
|
username: deerflow
|
|
# -- Password auto-generated (32 chars, persisted across upgrades) when
|
|
# empty. Ignored if existingSecret is set.
|
|
password: ""
|
|
# -- Use an existing Secret (key `database-url`, plus `postgres-password`
|
|
# in bundled mode) instead of generating one. Skips Secret creation.
|
|
existingSecret: ""
|
|
primary:
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 1Gi
|
|
persistence:
|
|
enabled: true
|
|
storageClass: "" # "" = cluster default
|
|
accessMode: ReadWriteOnce # RWX (NFS) only needed if postgres itself is HA
|
|
size: 20Gi
|
|
# -- External postgres (used when `enabled: false`). Provide either a full
|
|
# `databaseUrl` (chart wraps it into a Secret for you) or an
|
|
# `existingSecret` you manage (key `database-url`).
|
|
external:
|
|
# -- Full DSN, e.g. postgresql://user:pass@host:5432/deerflow. Chart
|
|
# writes it into the Secret so it never touches the gateway env directly.
|
|
databaseUrl: ""
|
|
# -- Secret you manage (key `database-url`). Use this with External Secrets
|
|
# / Vault / Sealed Secrets so the DSN never appears in values files.
|
|
existingSecret: ""
|
|
|
|
# -- Redis stream bridge. The gateway stores per-run SSE events in Redis Streams
|
|
# so live run events reach a client connected to any gateway pod (cross-pod
|
|
# SSE delivery + reconnect replay, PR #3191). Bundled mode (default) deploys
|
|
# a single-instance redis StatefulSet; set `enabled: false` to use an external
|
|
# managed Redis. The gateway reads DEER_FLOW_STREAM_BRIDGE_REDIS_URL from the
|
|
# resolved Secret; config.yaml's stream_bridge.type is `redis` by default.
|
|
redis:
|
|
# -- Deploy a bundled redis StatefulSet. Disable to use an external Redis.
|
|
enabled: true
|
|
image:
|
|
repository: redis
|
|
tag: "7-alpine"
|
|
auth:
|
|
# -- Empty (default) = no auth, matching the compose deployment (ClusterIP
|
|
# isolation only). Set a password to enable AUTH; the DSN becomes
|
|
# redis://:<password>@host:6379/0. Ignored if existingSecret is set.
|
|
password: ""
|
|
# -- Use an existing Secret (key `redis-url`, plus `redis-password` if auth)
|
|
# instead of generating one. Skips Secret creation.
|
|
existingSecret: ""
|
|
primary:
|
|
resources:
|
|
requests:
|
|
cpu: 50m
|
|
memory: 64Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 512Mi
|
|
persistence:
|
|
enabled: true
|
|
storageClass: "" # "" = cluster default
|
|
accessMode: ReadWriteOnce # RWX (NFS) only needed if redis itself is HA
|
|
size: 5Gi
|
|
# -- External redis (used when `enabled: false`). Provide either a full
|
|
# `redisUrl` (chart wraps it into a Secret for you) or an `existingSecret`
|
|
# you manage (key `redis-url`).
|
|
external:
|
|
# -- Full URL, e.g. redis://:pass@myredis.example:6379/0. Chart writes it
|
|
# into the Secret so it never touches the gateway env directly.
|
|
redisUrl: ""
|
|
# -- Secret you manage (key `redis-url`). Use with External Secrets / Vault
|
|
# / Sealed Secrets so the URL never appears in values files.
|
|
existingSecret: ""
|
|
|
|
# -- Persistent volume for runtime state (.deer-flow): sqlite DB, memory,
|
|
# custom agents, mutable extensions_config.json, and per-thread user-data.
|
|
# Also mounted (PVC mode) into provisioner-spawned sandbox Pods. When
|
|
# disabled, Gateway runtime state uses a pod-local emptyDir instead.
|
|
persistence:
|
|
home:
|
|
enabled: true
|
|
storageClass: "" # "" = cluster default
|
|
accessMode: ReadWriteOnce # Use ReadWriteMany (NFS/etc.) for multi-node
|
|
size: 10Gi
|
|
|
|
# -- Skills library mounted at /app/skills. Default: emptyDir (skills disabled).
|
|
# Populate via an existing PVC or ConfigMap, or bake skills into a custom
|
|
# gateway image. Provisioner PVC mode references this same claim when set.
|
|
skills:
|
|
enabled: false
|
|
existingClaim: ""
|
|
configMap: ""
|
|
|
|
# -- Provider/channel/search secrets injected as env vars into the gateway.
|
|
# Reference them from config.yaml as $VAR. Example:
|
|
# secrets:
|
|
# OPENAI_API_KEY: "sk-..."
|
|
# FEISHU_APP_ID: "cli_xxx"
|
|
# FEISHU_APP_SECRET: "xxx"
|
|
# GITHUB_TOKEN: "ghp_xxx"
|
|
secrets: {}
|
|
# -- Use an existing Secret instead of creating one from `secrets` above.
|
|
existingSecret: ""
|
|
# -- Use an existing Secret for the app secrets instead of generating
|
|
# `<release>-app`. It must hold BETTER_AUTH_SECRET (frontend),
|
|
# DEER_FLOW_INTERNAL_AUTH_TOKEN, PROVISIONER_API_KEY (the shared gateway ->
|
|
# sandbox-provisioner key, required while `provisioner.enabled`) and, for
|
|
# more than one gateway instance, AUTH_JWT_SECRET (the session-cookie
|
|
# signing key every Pod must share). It should also hold
|
|
# DEER_FLOW_CREDENTIALS_KEY (the at-rest key for stored credentials, a
|
|
# Fernet key); a multi-instance gateway with channel_connections enabled
|
|
# refuses to start without it.
|
|
existingAppSecret: ""
|
|
|
|
# -- Ingress in front of nginx (port 2026). nginx preserves all internal routing.
|
|
ingress:
|
|
enabled: true
|
|
className: "nginx"
|
|
host: "deer-flow.example.com"
|
|
annotations:
|
|
# Allows a 100 MiB .skill archive plus multipart framing at the outer ingress.
|
|
nginx.ingress.kubernetes.io/proxy-body-size: "101m"
|
|
# Streams request bodies to nginx instead of spooling them at the outer ingress.
|
|
nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
|
|
# Skill validation may perform multiple sequential LLM calls.
|
|
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
|
|
tls:
|
|
enabled: false
|
|
secretName: ""
|
|
# hosts: [] # defaults to [ingress.host]
|
|
|
|
# -- DeerFlow config.yaml content. Secrets MUST stay as $VAR references — never
|
|
# inline literal secret values here. The default enables provisioner sandbox.
|
|
config: |
|
|
config_version: 61
|
|
log_level: info
|
|
recursion_limit: 100
|
|
max_recursion_limit: 1000
|
|
|
|
# Optional provider-agnostic knowledge capability and custom-agent scope selector.
|
|
# RAGFlow connection/retrieval settings belong on the knowledge_search tool.
|
|
knowledge_base:
|
|
enabled: false
|
|
scope_selection_enabled: false
|
|
|
|
models: []
|
|
# Both switches are required for conversation-created schedules. Restart pods.
|
|
scheduler:
|
|
enabled: false
|
|
tool_enabled: false
|
|
# Example (uncomment & set the matching secret in `secrets`):
|
|
# - name: gpt-4
|
|
# display_name: GPT-4
|
|
# use: langchain_openai:ChatOpenAI
|
|
# model: gpt-4
|
|
# api_key: $OPENAI_API_KEY
|
|
# request_timeout: 600.0
|
|
|
|
sandbox:
|
|
use: deerflow.community.aio_sandbox:AioSandboxProvider
|
|
prewarm: false
|
|
# Pending/ready-unused speculation per provider instance in each process.
|
|
prewarm_max_concurrent: 1
|
|
provisioner_url: http://provisioner:8002
|
|
# Sent as X-API-Key on every provisioner request. The chart injects the
|
|
# generated `<release>-app` key into the gateway and provisioner Pods as
|
|
# PROVISIONER_API_KEY; without a matching value the provisioner answers
|
|
# 401 and no sandbox can be created.
|
|
provisioner_api_key: $PROVISIONER_API_KEY
|
|
image: enterprise-public-cn-beijing.cr.volces.com/vefaas-public/all-in-one-sandbox:latest
|
|
port: 8080
|
|
replicas: 3
|
|
|
|
database:
|
|
# PostgreSQL is the default backend (bundled StatefulSet, or external).
|
|
# DATABASE_URL is injected from the postgres Secret; $DATABASE_URL is
|
|
# resolved by the harness before the config is instantiated.
|
|
backend: postgres
|
|
postgres_url: $DATABASE_URL
|
|
pool_recycle: 300
|
|
command_timeout: 30
|
|
|
|
# The LangGraph Store (cross-thread memory + thread list) reads this legacy
|
|
# `checkpointer:` section — it does NOT fall back to `database:` the way the
|
|
# checkpointer does. Point it at the same postgres so the Store is shared
|
|
# across gateway pods (required for multi-replica operation).
|
|
checkpointer:
|
|
type: postgres
|
|
connection_string: $DATABASE_URL
|
|
|
|
# Stream bridge: `redis` (default) stores per-run SSE events in Redis Streams
|
|
# so live run events reach a client on any gateway pod (cross-pod SSE delivery
|
|
# + reconnect replay, PR #3191). The URL is read from the
|
|
# DEER_FLOW_STREAM_BRIDGE_REDIS_URL env var injected from the redis Secret.
|
|
# Set `type: memory` (and disable the redis chart) for single-pod-only mode.
|
|
stream_bridge:
|
|
type: redis
|
|
|
|
# Multi-replica prerequisites (harmless at 1 replica). Heartbeats give each
|
|
# run a lease, so a starting Pod only reclaims runs whose owner is really
|
|
# gone instead of writing every peer's live run off as an orphan; db run
|
|
# events share message history and delivery receipts across Pods. Sandbox
|
|
# ownership leases (#4206) are inferred from the Redis stream bridge above.
|
|
# Both are startup-only: restart every Gateway Pod together after changing
|
|
# them.
|
|
run_ownership:
|
|
heartbeat_enabled: true
|
|
run_events:
|
|
backend: db
|
|
|
|
# Custom agents and managed subagents default to per-Pod files under the
|
|
# home volume. Switch to the shared database when running more than one
|
|
# replica. From the repository root, use the installed backend environment
|
|
# and the Gateway's runtime/configuration selectors to preview the import:
|
|
# `uv run --no-sync --project backend python backend/scripts/migrate_agents_to_db.py --dry-run`
|
|
# Remove --dry-run after reviewing the preview to perform the import:
|
|
# agent_storage:
|
|
# backend: db
|
|
|
|
# Canonical memory (users/{uid}/memory.json plus fact Markdown) lives at the
|
|
# default root on the home volume. The derived SQLite FTS5 retrieval index is
|
|
# rebuildable and must not be shared between Pods: SQLite WAL is unsupported
|
|
# on network filesystems, every Pod start would rebuild the shared index
|
|
# under its peers, and one Pod's corruption recovery would delete files the
|
|
# others hold open. gateway-deployment.yaml mounts an emptyDir at this path;
|
|
# a Pod re-syncs a user's index on its next search after a peer writes.
|
|
memory:
|
|
backend_config:
|
|
retrieval_index_path: /var/lib/deerflow/memory-index
|
|
|
|
verification:
|
|
receipts_enabled: true
|
|
receipts_render_mode: "delegation_only"
|
|
judge_enabled: false
|
|
judge_model_name: null
|
|
|
|
# -- Tools configuration. The agent gets NO tools unless they're listed here
|
|
# (BUILTIN_TOOLS only adds present_file + ask_clarification). The file/bash
|
|
# tools run inside the AIO sandbox configured above. The web tools
|
|
# (web_search, web_fetch, image_search) need no API key but require outbound
|
|
# internet from the gateway pod - swap backends or remove entries for
|
|
# air-gapped clusters (see config.example.yaml).
|
|
tool_groups:
|
|
- name: web
|
|
- name: file:read
|
|
- name: file:write
|
|
- name: bash
|
|
# - name: knowledge # Enable with the RAGFlow tool below.
|
|
|
|
tools:
|
|
# Optional tenant-shared, read-only RAGFlow retrieval. Put RAGFLOW_API_KEY
|
|
# in `secrets`. `datasets` is an optional stable-ID allowlist; omit it to
|
|
# search all tenant-visible datasets. An explicit empty list is invalid.
|
|
# Empty datasets are skipped; remaining
|
|
# datasets are grouped by embedding model with up to four parallel retrieval
|
|
# requests and one global `page_size` limit. Multi-group scores are omitted
|
|
# because they are not comparable. The Agent cannot see the IDs.
|
|
# - name: knowledge_search
|
|
# group: knowledge
|
|
# use: deerflow.community.ragflow.tools:knowledge_search_tool
|
|
# base_url: http://ragflow:9380
|
|
# api_key: $RAGFLOW_API_KEY
|
|
# datasets: # Optional operator-controlled allowlist
|
|
# - 0123456789abcdef0123456789abcdef
|
|
# timeout: 30
|
|
# page_size: 8
|
|
# similarity_threshold: 0.2
|
|
# vector_similarity_weight: 0.3
|
|
# top_k: 256
|
|
# max_chars_per_chunk: 800
|
|
# max_total_chars: 8000
|
|
# - name: list_knowledge_bases
|
|
# group: knowledge
|
|
# use: deerflow.community.ragflow.tools:list_knowledge_bases_tool
|
|
# Optional tenant-shared, read-only LightRAG retrieval; alternative
|
|
# provider for the same knowledge_search tool (duplicate names keep the
|
|
# first entry, so configure exactly one). Requires LightRAG v1.4.9+. Put
|
|
# LIGHTRAG_API_KEY in `secrets` when the server enables API-key auth;
|
|
# omit `api_key` only for unauthenticated trusted-network deployments.
|
|
# Searches the single indexed workspace through the data-retrieval
|
|
# endpoint with no LLM generation inside LightRAG. Internal chunk and
|
|
# reference identifiers stay hidden from the Agent.
|
|
# - name: knowledge_search
|
|
# group: knowledge
|
|
# use: deerflow.community.lightrag.tools:knowledge_search_tool
|
|
# base_url: http://lightrag:9621
|
|
# api_key: $LIGHTRAG_API_KEY
|
|
# mode: mix
|
|
# timeout: 30
|
|
# top_k: 60
|
|
# chunk_top_k: 8 # Optional; omit to use the server default
|
|
# max_chars_per_chunk: 800
|
|
# max_total_chars: 8000
|
|
- name: web_search
|
|
group: web
|
|
use: deerflow.community.ddg_search.tools:web_search_tool
|
|
max_results: 5
|
|
- name: web_fetch
|
|
group: web
|
|
use: deerflow.community.jina_ai.tools:web_fetch_tool
|
|
timeout: 10
|
|
- name: image_search
|
|
group: web
|
|
use: deerflow.community.image_search.tools:image_search_tool
|
|
max_results: 5
|
|
- name: ls
|
|
group: file:read
|
|
use: deerflow.sandbox.tools:ls_tool
|
|
- name: read_file
|
|
group: file:read
|
|
use: deerflow.sandbox.tools:read_file_tool
|
|
- name: glob
|
|
group: file:read
|
|
use: deerflow.sandbox.tools:glob_tool
|
|
max_results: 200
|
|
- name: grep
|
|
group: file:read
|
|
use: deerflow.sandbox.tools:grep_tool
|
|
max_results: 100
|
|
- name: write_file
|
|
group: file:write
|
|
use: deerflow.sandbox.tools:write_file_tool
|
|
- name: str_replace
|
|
group: file:write
|
|
use: deerflow.sandbox.tools:str_replace_tool
|
|
- name: bash
|
|
group: bash
|
|
use: deerflow.sandbox.tools:bash_tool
|
|
|
|
# -- Initial DeerFlow extensions_config.json content (MCP servers + skill
|
|
# state). The Gateway copies this ConfigMap seed into its writable home
|
|
# volume only when no runtime file exists. With persistence enabled, API
|
|
# updates and the original seed survive pod replacement and Helm upgrades;
|
|
# remove the runtime file explicitly if a later seed should replace it.
|
|
extensionsConfig: |
|
|
{"mcpServers":{},"skills":{}}
|