Files
YiemAgent/docs/7-implementation-plan.md
2026-09-11 08:28:49 +07:00

14 KiB

Implementation Plan: YiemAgent Agent Framework

1. Implementation Phases

Phase 1: Type System & Core Structures (COMPLETED)

Files: src/type.jl

Completed Tasks:

  • IMP-001: Define Julia struct types for messages (userMessage, assistantMessage, assistantMessageToolCall, toolResultMessage) with keyword constructors — COMPLETED (see src/type.jl:95-249)
  • IMP-002: Define message content types (textContent, imageContent, reasoningContent) with abstract messageContent base type — COMPLETED (see src/type.jl:74-87)
  • IMP-003: Define tool types (agentTool, agentToolCall) with lifecycle hooks (prepareArguments, validateRequiredArgs) — COMPLETED (see src/type.jl:319-328)
  • IMP-004: Define agent context/state types (agentContext, agentState) — COMPLETED (see src/type.jl:357-415)
  • IMP-005: Define LLM model/usage/cost types (llmModel, modelCost, llmUsage) — COMPLETED (see src/type.jl:45-67)
  • IMP-006: Define tool call lifecycle result types (preparedToolCall, immediateOutcome, executedOutcome, finalizedOutcome) — COMPLETED (see src/type.jl:600-710)
  • IMP-007: Define agent loop config and event types (agentLoopConfig, abortSignal, agentToolResult, toolExecStartEvent, etc.) — COMPLETED (see src/type.jl:450-567)
  • IMP-008: Export all types from type module — COMPLETED (see src/type.jl:2-26)

Validation Tests: Unit tests for struct construction with keyword args (SP-001..SP-008, SP-019..SP-022)

Traceability: FR-001, FR-002, FR-003, FR-004, FR-005, FR-006


Phase 2: Utility & Formatting Functions (COMPLETED)

Files: src/utils.jl

Completed Tasks:

  • IMP-010: Implement prepareContext(state, eventSink) -> agentContext — COMPLETED (see src/utils.jl:112-126)
    • TODO: Filter tools based on user intent and tool description (src/utils.jl:114)
    • TODO: Inject system prompt context (e.g., time, session state) (src/utils.jl:118)
    • TODO: Prune/reorder messages (src/utils.jl:121)
  • IMP-011: Implement formatMsgForLLM(ctx, eventSink) -> Dict{String, Any} — COMPLETED (see src/utils.jl:159-244)
    • Converts system prompt to system message
    • Converts conversation messages via _userMessageToOpenAI, _assistantMessageToOpenAI, _assistantMessageToolCallToOpenAI, _toolResultMessageToOpenAI
    • Converts ctx.tools to OpenAI function tool format via _toolsToOpenAI
  • IMP-012: Implement message converters (_userMessageToOpenAI, _assistantMessageToOpenAI, _assistantMessageToolCallToOpenAI, _toolResultMessageToOpenAI) — COMPLETED (see src/utils.jl:321-387)
  • IMP-013: Implement _messageContentToBlocks — converts textContent/imageContent to OpenAI content blocks — COMPLETED (see src/utils.jl:396-413)
  • IMP-014: Implement _toolsToOpenAI — converts OrderedDict{String, agentTool} to OpenAI tools array — COMPLETED (see src/utils.jl:429-447)
  • IMP-015: Implement beforeToolCall hook default (returns beforeToolCallResult(false, "N/A")) — COMPLETED (see src/utils.jl:278-284)
  • IMP-016: Implement afterToolCall hook default (returns nothing) — COMPLETED (see src/utils.jl:310-316)
  • IMP-017: Implement validateRequiredArgs(args, inputSchema) — validates required fields in tool arguments — COMPLETED (see src/utils.jl:479-497)
  • IMP-018: Implement validateToolArguments(tool, prepared) — wrapper that calls tool-specific or default hook — COMPLETED (see src/utils.jl:533-546)

Validation Tests: Unit tests for converters, validation hooks, and OpenAI format output structure (SP-011..SP-016, SP-023, SP-024)

Traceability: FR-001, FR-002, FR-003, FR-004, FR-005, FR-006


Phase 3: Tool Registry & MCP Integration (COMPLETED)

Files: src/toolRegistry.jl

Completed Tasks:

  • IMP-020: Implement _extract_text_content(result) — extracts text from MCP tool result content array — COMPLETED (see src/toolRegistry.jl:19-33)
  • IMP-021: Implement _wrap_mcp_tool(mcpserver, tool_def) — wraps MCP tool as agentTool with execute calling mcpserver("tools/call", ...) — COMPLETED (see src/toolRegistry.jl:41-106)
    • Handles MCP error responses (haskey(response, "error"))
    • Extracts text and isError from result
  • IMP-022: Implement register_mcp_tools(tools, mcpserver) — queries tools/list with pagination (nextCursor) — COMPLETED (see src/toolRegistry.jl:118-186)
    • Handles both result.tools and result.error response shapes
    • Skips already registered tools (idempotent)
  • IMP-023: Implement registerTool(tools, tool) — adds tool to OrderedDict — COMPLETED (see src/toolRegistry.jl:200-205)
  • IMP-024: Implement listTool(tools, mcpserver) — builtin tool that triggers runtime discovery and lists all tools — COMPLETED (see src/toolRegistry.jl:235-271)
  • IMP-025: Implement registerAllTools(tools, mcpserver) — discovers existing tools + registers listTools — COMPLETED (see src/toolRegistry.jl:286-289)

Validation Tests: Unit tests for MCP tools/list parsing, pagination, tool registration idempotency; contract tests for JSON-RPC 2.0 format (SP-009, SP-010)

Traceability: FR-002, FR-004


Phase 4: Agent Core & Loop (COMPLETED)

Files: src/agentCore.jl

Completed Tasks:

  • IMP-030: Define yiemAgent struct with channels, callbacks, MCP server — COMPLETED (see src/agentCore.jl:17-95)
  • IMP-031: Implement yiemAgent constructor — creates channels, discovers MCP tools, spawns _agentLoop task — COMPLETED (see src/agentCore.jl:126-199)
  • IMP-032: Implement _agentLoop(agent) — background @spawn task managing inputChannel/followUpChannel priority dispatch — COMPLETED (see src/agentCore.jl:225-364)
    • Handles shutdown signal: drains all channels, breaks loop
    • On error: catches, calls eventSink(errMsg), exits loop
  • IMP-033: Implement _processMessage(...) — drains input, calls llmCall, extracts tool calls, executes, loops until no tool calls — COMPLETED (see src/agentCore.jl:394-544)
    • while true loop: llmCall() → _extractToolCalls() → if hasToolCalls && length > 0 execute → append results → repeat
    • On toolResultBatch.terminate == true: build final response and break
    • Catches all errors and calls eventSink(err_msg)
  • IMP-034: Implement _extractToolCalls(response) — handles both formats:
    • Format 1: response["message"]["tool_calls"] (LMStudio/vLLM style) — COMPLETED (see src/agentCore.jl:671-683)
    • Format 2: response.content blocks with type => "tool_calls" or type => "tool_call" (OpenAI API style) — COMPLETED (see src/agentCore.jl:685-719)
    • Extracts reasoning_content, content text blocks, api, provider, model, usage, finish_reason — COMPLETED (see src/agentCore.jl:723-797)
    • Returns (hasToolCalls, toolCallList, assistant_message) — COMPLETED (see src/agentCore.jl:799-827)
  • IMP-035: Implement prepareToolCall(context, assistantMsg, toolCall, config, signal, eventSink) — resolves tool, validates args, runs beforeToolCall hook, never throws — COMPLETED (see src/agentCore.jl:974-1035)
  • IMP-036: Implement executePreparedToolCall(prep, signal, eventSink) — calls tool.execute(toolCallId, args, ...) — COMPLETED (see src/agentCore.jl:1078-1100)
  • IMP-037: Implement finalizeExecutedToolCall(context, msg, prep, executed, config, signal, eventSink) — runs afterToolCall hook, catches errors — COMPLETED (see src/agentCore.jl:1159-1198)
  • IMP-038: Implement prepareToolCallArguments(tool, toolCall) — calls tool.prepareArguments if present — COMPLETED (see src/agentCore.jl:908-917)
  • IMP-039: Implement createErrorToolResult(msg) — builds agentToolResult with error content — COMPLETED (see src/agentCore.jl:572-574)
  • IMP-040: Implement createToolResultMessage(f) — builds toolResultMessage from finalizedOutcome — COMPLETED (see src/agentCore.jl:606-612)

Note: Sequential and parallel execution implementations continue beyond line 1207 of src/agentCore.jl — implementation incomplete, requires review to ensure execution methods properly call hooks and emit lifecycle events. See IMP-041.

Validation Tests: Integration tests for full agent loop with mocked LLM and MCP; contract tests for response format extraction (WT-001..WT-032, SP-017, SP-018)

Traceability: FR-001, FR-002, FR-003, FR-004, FR-005


Phase 5: Public API (COMPLETED)

Files: src/api.jl

Completed Tasks:

  • IMP-050: Implement promptAgent(agent, msg::AbstractDict) — put to inputChannel, returns agent for chaining — COMPLETED (see src/api.jl:36-39)
  • IMP-051: Implement promptAgent(agent, text::String) — wraps text as OpenAI Dict and put to inputChannel — COMPLETED (see src/api.jl:41-44)
  • IMP-052: Implement takeResponse(agent) — blocks on outputChannel take!, returns OpenAI dict response — COMPLETED (see src/api.jl:66-68)
  • IMP-053: Implement followUp(agent, msg::AbstractDict) — put to followUpChannel, returns agent — COMPLETED (see src/api.jl:94-97)
  • IMP-054: Implement followUp(agent, text::String) — wraps text as OpenAI Dict and put to followUpChannel — COMPLETED (see src/api.jl:99-102)
  • IMP-055: Implement stopAgent(agent) — puts :shutdown, fetch(_agentLoop), closes all channels — COMPLETED (see src/api.jl:126-139)

Validation Tests: Integration tests for send/receive/stop lifecycle (WT-001..WT-005)

Traceability: FR-001, FR-006


2. Module Structure

src/
├── YiemAgent.jl     # Parent module, includes submodules in dependency order
├── type.jl           # All Julia struct types (exports 30+ types)
├── utils.jl          # Formatting, validation, hooks (default implementations)
├── toolRegistry.jl   # MCP tool discovery, registration, listTools builtin
├── agentCore.jl      # yiemAgent struct, _agentLoop, _processMessage, extractToolCalls
└── api.jl            # Public: promptAgent, takeResponse, followUp, stopAgent

Include order (per src/YiemAgent.jl lines 6-19):

  1. type.jl (no dependencies)
  2. utils.jl (depends on type)
  3. toolRegistry.jl (depends on type)
  4. agentCore.jl (depends on type, utils, toolRegistry)
  5. api.jl (depends on type, utils, agentCore, toolRegistry)

3. Task Dependencies

Task ID Title Depends On Status
IMP-001..IMP-008 Type system — COMPLETED
IMP-010..IMP-018 Utils (formatMsgForLLM, converters, hooks) IMP-001..IMP-008 COMPLETED
IMP-020..IMP-025 Tool registry (MCP discovery) IMP-003, IMP-017 COMPLETED
IMP-030..IMP-040 Agent core (agent loop, tool call execution) IMP-001..IMP-008, IMP-010..IMP-018, IMP-020..IMP-025 INCOMPLETE* (see note)
IMP-050..IMP-055 Public API IMP-030..IMP-040 COMPLETED

NOTE on IMP-030..IMP-040: The sequential and parallel execution functions (executeToolCallsSequential, executeToolCallsParallel, executeToolCalls) begin after line 1207 of src/agentCore.jl but the full implementation is truncated in file reads and requires review. The exported functions (executePreparedToolCall, prepareToolCall, executeToolCallsSequential, executeToolCallsParallel, executeToolCalls) are declared (src/agentCore.jl:4-5) but their full bodies may be incomplete. Requires manual validation.

Traceability: IMP-001..IMP-008 → SP-001..SP-008, IMP-020..IMP-025 → SP-009, SP-010; IMP-010..IMP-018 → SP-011..SP-016, SP-023, SP-024; IMP-030..IMP-040 → SP-017, SP-018, SP-019..SP-022


4. Remaining Work (TODOs)

File Line Description Priority
src/utils.jl 114 Filter tools from state.tools based on user intent and tool description High
src/utils.jl 118 Add system prompt context: time, session state, user preferences Medium
src/utils.jl 121 Prune/reorder/conversation messages before sending to LLM Medium
src/agentCore.jl post-1207 Complete and validate executeToolCallsSequential, executeToolCallsParallel, executeToolCalls implementations (currently exported but body may be incomplete) Critical
tests/unit/... — Write unit tests for all struct types (IMP-001..IMP-008) and converters (SP-011..SP-016) High
tests/unit/... — Write unit tests for tool validation hooks (SP-023, SP-024) High
tests/integration/... — Write integration tests for agent loop with mocked LLM/MCP (WT-001..WT-032) High
tests/contract/... — Write contract tests for response formats (SP-017, SP-018) Medium
tests/perf/... — Write performance tests (NFR-101, NFR-102) Medium

5. Build & Deployment

Build

cd /home/ton/docker-apps/sommpanion/YiemAgent
julia --project=. -e 'using Pkg; Pkg.instantiate(); using Pkg; Pkg.precompile()'

Test

julia --project=./tests -e 'using Pkg; Pkg.instantiate()'
julia --project=./tests -e 'using Test; Test.@testset "Unit" begin include("tests/unit/run_tests.jl") end'
julia --project=./tests -e 'using Test; Test.@testset "Integration" begin include("tests/integration/run_tests.jl") end'

CI/CD Preparation

  • Add .github/workflows/julia.yaml referencing ci/julia-pipeline.yaml steps
  • Add Project.toml dependencies:
    [deps]
    JSON = "682c8566-3430-5439-8f4e-b64832e8aaba"
    DataStructures = "892a3cad-33e6-51e5-808c-f3d90072be70"
    HTTP = "cd6eee30-4dd5-5329-8bad-3259ec48d0f4"
    # plus: UUIDs, Dates, PrettyPrinting, Serialization, DataFrames, NATS, LibPQ
    

6. Risk Mitigation

Risk Mitigation
Line 1207+ of agentCore.jl (sequential/parallel execution) is incomplete or broken Manually review and validate executeToolCallsSequential, executeToolCallsParallel, executeToolCalls against spec SP-021 (agentLoopConfig) and trace to test test_tool_call_execution_sequence
GeneralUtils internal package unavailable in CI Ensure GeneralUtils is installed as dependency (via Pkg.develop or registry)
NATS mcpServer struct is abstract — no concrete implementation Provide at least one mock mcpServer for tests that returns canned JSON responses
Message history grows unbounded Implement prepareContext pruning (TODO in code); add NFR-104 for max history tokens