--- name: agents-and-awel description: "Build and debug DB-GPT agents, tools, skills, teams, and AWEL workflows, including deterministic local DAG runs and HTTP-trigger topology without assuming an LLM, credential, or external service." metadata: disco-role: operating disable-model-invocation: true license: MIT --- # DB-GPT agents and AWEL Use this route when the task mentions `dbgpt.agent`, `ConversableAgent`, profiles, agent context or memory, tools, skills, middleware, teams, prompts, AWEL/DAG/flow, `MapOperator`, HTTP triggers, flow variables, or local workflow execution. Keep the work local and deterministic unless the user explicitly supplies a model, service, and credentials. Route these elsewhere: - datasource, document loading, chunking, embeddings, retrieval, and knowledge-space implementation -> `data-and-rag`; - provider installation, model backends, controller/worker deployment, and GPU setup -> `models-and-serving`; - HTTP CRUD endpoint semantics, Python client calls, file APIs, and sandbox service execution -> `apis-client-and-sandbox`. ## Operating workflow 1. **Classify the target.** Decide whether this is (a) a single agent conversation, (b) tool/resource or skill registration, (c) multi-agent/team planning, (d) a programmatic AWEL DAG, (e) an HTTP-triggered DAG, or (f) a serialized Flow UI definition. Do not treat graph construction as deployment. 2. **Establish a profile and lifecycle.** A `ConversableAgent` needs a `ProfileConfig` (unless a subclass supplies one). Bind the `AgentContext` before `build()`. Bind the LLM configuration and required memory/resources/actions before `build()` as described in [agent-api-reference.md](references/agent-api-reference.md). `bind()` is synchronous and returns the same agent; `build()` is async. 3. **Make dependencies explicit.** Define tools with a docstring and typed arguments, put them in a `ToolPack`, and bind the pack before an action that consumes it is built. A `Skill` sets the agent's prompt when bound, but its declared `required_tools` and `required_knowledge` are not a substitute for binding and checking actual resources. 4. **Construct AWEL in a DAG context.** Create `DAG("stable-id")`, instantiate operators inside `with dag:`, use explicit `task_id`/`task_name` where serialized identity matters, and connect nodes with `>>`. Inspect `root_nodes`, `leaf_nodes`, and `trigger_nodes` before running. Follow the stream and join constraints in [awel-workflows.md](references/awel-workflows.md). 5. **Validate without side effects first.** Instantiate pydantic request/response bodies, inspect the resolved endpoint and router metadata, and call a local leaf with a tiny fixture. Use `scripts/awel_smoke.py` for an independent no-model/no- network topology and execution check. Only then mount into the application's supported router or start a development server. 6. **Separate runtime modes.** `leaf.call()`/`call_stream()` use a local runner in the current process. An `HttpTrigger` mounted on an app invokes the leaf through the HTTP request path. A production DB-GPT service must register/load the DAG and provide the application lifecycle; `setup_dev_environment()` is a development helper and can start a blocking Uvicorn process. 7. **Verify failure paths.** Check duplicate IDs/names, invalid pydantic input, missing action resources, malformed tool schemas, missing skills, serialization boundaries, context budget state, and async/sync mismatches. Use the actionable checks in [troubleshooting.md](references/troubleshooting.md); do not claim provider or MCP coverage from a CPU-only local run. ## Quick patterns ### Local deterministic map ```python from dbgpt.core.awel import DAG, InputOperator, MapOperator, SimpleInputSource with DAG("double-local") as dag: source = InputOperator(SimpleInputSource(21), task_name="source") doubled = MapOperator(lambda value: value * 2, task_name="doubled") source >> doubled result = await doubled.call() # result == 42 ``` For a callable that is not known to be serializable, use it only for local experimentation. Serialized/deployed flows should use registered operator classes, metadata, stable IDs, and serializable callables; see [awel-workflows.md](references/awel-workflows.md). ### HTTP trigger topology ```python from dbgpt._private.pydantic import BaseModel, Field from dbgpt.core.awel import DAG, HttpTrigger, MapOperator class RequestBody(BaseModel): name: str = Field(..., description="User name") age: int = Field(18, description="User age") class Greeting(MapOperator[RequestBody, str]): async def map(self, body: RequestBody) -> str: return f"Hello, {body.name}; age={body.age}" with DAG("greeting-flow") as dag: trigger = HttpTrigger( "/examples/greeting/{dag_id}", methods="POST", request_body=RequestBody ) leaf = Greeting(task_name="greeting") trigger >> leaf ``` The trigger normalizes a missing leading slash, resolves `{dag_id}` from its DAG, and requires exactly one leaf when it runs through HTTP. POST/PUT-style routes receive a pydantic body; GET/DELETE model fields become query parameters. Mounting on a plain FastAPI `APIRouter` is suitable for inspection via `mount_to_router`; DB-GPT's app mount path uses its supported priority router. Do not infer a live server from router registration alone. ### Skill and middleware boundary The core skill API is exported from `dbgpt.agent.skill`: `Skill`, `SkillMetadata`, `SkillType`, `SkillBuilder`, `SkillLoader`, `SkillManager`, `initialize_skill`, and `get_skill_manager`. A file-based `SKILL.md` must begin with YAML frontmatter and have `name` and `description`; its instructions are the remainder of the file. A `SkillsMiddleware` exposes metadata first and reads full content on demand. Later configured directories override earlier names. Skill matching is simple keyword matching, not semantic routing, so always verify the selected skill explicitly. Details and safe fixture rules are in [skills-and-tools.md](references/skills-and-tools.md). ## API and safety notes - `AgentContext` carries `conv_id`, language, round/retry limits, generation settings, and opt-in context management. `ContextBudgetConfig.effective_budget` is `max_context_tokens - reserved_tokens`; the default maximum is 120000 and the default reserved output space is 4096. - `ConversableAgent.check_available()` requires context, action resources where an action declares `resource_need`, and an LLM config/client for non-human, non-team agents. `build()` preloads resources, performs this check, initializes actions and memory, and wraps the configured LLM client. - `AgentMessage` is the communication object. Preserve `content`, `role`, `context`, `action_report`, `review_info`, `current_goal`, and success state when forwarding or serializing messages. Use `to_llm_message()` only when the reduced LLM shape is intended. - `@tool` creates a `FunctionTool` wrapper with `._tool`; synchronous and async functions must be executed through their matching `execute`/`async_execute` path. Missing docstrings/descriptions and malformed explicit `args` are validation errors. - `MiddlewareManager` executes registered middleware in registration order and skips disabled middleware. Hook return dictionaries are merged; system-prompt hooks are applied sequentially. Middleware state is not automatically agent state. - `DAG` IDs are caller-supplied strings; node IDs default to UUIDs. Node names must be unique inside a DAG. `MapOperator` expects one parent during normal graph execution, `JoinOperator` accepts multiple parents, and `ReduceStreamOperator` requires stream input. `call_stream()` wraps a non-stream output as a one-item async stream. - `HttpTrigger` itself does not support direct `trigger()` execution. It delegates to the DAG's single leaf; streaming uses `call_stream()` and normally returns `text/event-stream` unless response settings override it. - Never put API keys, personal filesystem paths, private checkout paths, or live MCP URLs in a skill recipe. Treat `MCPToolPack`, code/shell tools, personal skill scripts, and provider-backed agent examples as optional side-effectful integrations. ## Progressive disclosure - [agent-api-reference.md](references/agent-api-reference.md) — signatures and lifecycle for profiles, agents, teams, memory/context, tools, and middleware. - [awel-workflows.md](references/awel-workflows.md) — DAG/operators/runners, pydantic HTTP triggers, flow variables, serialization, and deployment boundaries. - [skills-and-tools.md](references/skills-and-tools.md) — tool schema rules, packs, skill builder/loader/manager, SKILL.md middleware, and optional MCP. - [troubleshooting.md](references/troubleshooting.md) — symptom-to-check recovery table for binding, async loops, schemas, IDs, serialization, skills, and HTTP. - `scripts/awel_smoke.py` — safe local topology, router metadata, pydantic validation, and tiny-fixture DAG execution; it never starts a server or calls a model.