Skip to content

Latest commit

 

History

History
167 lines (109 loc) · 6.54 KB

File metadata and controls

167 lines (109 loc) · 6.54 KB

DEVELOP (for developers)

This document is developer-facing notes for uag (a local tool-execution agent).

  • Entry points:
    • CLI: python -m uagent (command: uag)
    • GUI: python -m uagent.gui (command: uagg)
    • Web: python -m uagent.web (command: uagw)

0. Runtime requirements

  • Python: 3.11+
  • Git: required for development workflows and some tools
  • OS: Windows / macOS / Linux

1. Repository structure / key modules

Key modules:

  • Core state + UI integration: src/uagent/core.py
  • CLI UI loop: src/uagent/cli.py
  • LLM orchestration entrypoint: src/uagent/uagent_llm.py
    • Round/message/tool-call helpers are split into:
      • src/uagent/llm_helpers.py
      • src/uagent/llm_message_helpers.py
      • src/uagent/llm_round_helpers.py
      • src/uagent/llm_flow_helpers.py
    • Retry / backoff helpers live in src/uagent/llm_errors.py
  • Provider wiring (OpenAI/Azure/Gemini/Claude/Vertex AI/Ollama/etc.): src/uagent/util_providers.py
  • Common helpers (commands, callbacks injection, messages building, etc.): src/uagent/util_tools.py
  • Startup initialization: src/uagent/runtime_init.py (compatibility re-export)
    • src/uagent/runtime_workdir.py: decide_workdir() / apply_workdir()
    • src/uagent/runtime_banner.py: build_startup_banner()
    • src/uagent/runtime_env.py: validate_or_exit_startup_env(context=...)
    • src/uagent/runtime_memory.py: append_long_memory_system_messages()
  • runtime_init.py loads .env and .env.sec from the current working directory at import time when python-dotenv is available (.env first, then .env.sec decrypted with .uagent.key if present)

Documentation:

  • Tool development: src/uagent/docs/DEVELOP_TOOL.md
  • Host-side i18n: src/uagent/docs/DEVELOP_I18N.md (compile: python scripts/compile_locales.py, QC: python scripts/po_qc_summary.py)

2. High-level execution flow

  1. Start one of the entry points (uag / uagg / uagw).
  2. Startup initialization (runtime_init.py):
    • Decide workdir (--workdir/-C, UAGENT_WORKDIR, or current directory)
    • Create directory if needed and chdir
    • Build and print startup banner
    • Load .env and .env.sec from the current working directory if python-dotenv is available
  3. Tool plugins are loaded from src/uagent/tools/ (and optionally from an external directory).
  4. Provider client is created based on environment variables (util_providers.make_client).
  5. UI loop (CLI/GUI/Web) receives user input and enqueues events.
  6. LLM rounds run via uagent_llm.run_llm_rounds():
    • If the assistant returns tool calls, tools are executed and results are appended.
    • Retry/backoff behavior for rate limits is implemented in llm_errors.py.

3. Tools system (how it works)

3.1 Tool discovery and registration

Tools are plugin modules under src/uagent/tools/.

  • A module is registered as a tool when it provides:
    • TOOL_SPEC: dict (OpenAI function schema compatible)
    • run_tool(args: dict) -> str (runner)

Tool loading happens in src/uagent/tools/__init__.py and is triggered at import time.

  • Internal tools: discovered by pkgutil.iter_modules([tools_dir])
  • External tools (optional): loaded from UAGENT_EXTERNAL_TOOLS_DIR (each *.py file)

3.2 Callbacks injection (host → tools)

Tools can require host features (Busy status updates, human_ask synchronization, env access).

util_tools.init_tools_callbacks(core) injects callbacks into the tools runtime (tools.init_callbacks).

This is how tools share state with the CLI stdin loop (especially human_ask).

3.3 Tool specs passed to the LLM

tools.get_tool_specs() returns specs for LLM calls.

Important details:

  • Extended fields such as function.system_prompt are removed before sending to the LLM.
  • For compatibility, the function name may be mirrored to top-level name.

3.4 GPT-5.4+ Responses tool narrowing

For GPT-5.4 and later within the GPT-5 line, when Responses API is enabled, uag uses a lighter tool exposure path.

  • Target detection is implemented in uagent_llm._is_gpt54_tool_search_target(...)
  • A lightweight tools prompt is selected in util_tools.py
  • Candidate tool specs are selected by uagent_llm._select_tool_specs_for_gpt54(...)
  • tool_catalog provides a lightweight discovery surface before passing full tool definitions
  • A small safe fallback subset is kept when catalog search returns no hits

This preserves existing behavior for non-target models while reducing payload size for GPT-5.4+ Responses requests.

3.5 Tool trace output

By default, a one-line trace is printed to stdout before tool execution:

  • Example: [TOOL] 2025-... name=<tool> args=<masked-json>
  • Secret-like keys are masked.

A tool may suppress the trace using the extended flag:

  • TOOL_SPEC['function']['x_scheck']['emit_tool_trace'] = False

human_ask uses this to avoid logging the raw user reply.

3.6 Agent Skills lifecycle

  • :skills injects the selected skill as a dedicated [SKILL] ... system message.
  • Skill messages are persisted to the session log and restored on reload.
  • :skills status shows active skill messages; :skills clear removes them.
  • Keep skill instructions separate from the base SYSTEM_PROMPT.

4. Workdir / banner / long-term memory

4.1 Workdir selection

Workdir is decided in this priority order:

  1. CLI option: --workdir / -C
  2. Environment variable: UAGENT_WORKDIR
  3. Fallback: current directory

CLI/Web/GUI perform workdir initialization inside main() (not at module import time).

4.2 Startup banner

The startup banner (workdir/provider/base_url/api_version/Responses mode, etc.) is generated by:

  • runtime_init.build_startup_banner()

4.3 Long-term memory and shared memory

Long-term memory (personal) and shared memory can be inserted as system messages at startup.


5. MCP server tooling notes

MCP-related tools include:

  • mcp_servers_tool.py
  • mcp_tools_list_tool.py
  • handle_mcp_v2_tool.py
  • mcp_servers_shared.py

Recent smoke tests cover template creation and the basic add/list/validate/set_default/remove flow.

mcp_servers_validate_tool.py is hardened so it can still return raw output when callback-based truncation is unavailable.