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 (seesrc/type.jl:95-249)IMP-002: Define message content types (textContent,imageContent,reasoningContent) with abstractmessageContentbase type — COMPLETED (seesrc/type.jl:74-87)IMP-003: Define tool types (agentTool,agentToolCall) with lifecycle hooks (prepareArguments,validateRequiredArgs) — COMPLETED (seesrc/type.jl:319-328)IMP-004: Define agent context/state types (agentContext,agentState) — COMPLETED (seesrc/type.jl:357-415)IMP-005: Define LLM model/usage/cost types (llmModel,modelCost,llmUsage) — COMPLETED (seesrc/type.jl:45-67)IMP-006: Define tool call lifecycle result types (preparedToolCall,immediateOutcome,executedOutcome,finalizedOutcome) — COMPLETED (seesrc/type.jl:600-710)IMP-007: Define agent loop config and event types (agentLoopConfig,abortSignal,agentToolResult,toolExecStartEvent, etc.) — COMPLETED (seesrc/type.jl:450-567)IMP-008: Export all types fromtypemodule — COMPLETED (seesrc/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: ImplementprepareContext(state, eventSink) -> agentContext— COMPLETED (seesrc/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)
- TODO: Filter tools based on user intent and tool description (
IMP-011: ImplementformatMsgForLLM(ctx, eventSink) -> Dict{String, Any}— COMPLETED (seesrc/utils.jl:159-244)- Converts system prompt to system message
- Converts conversation messages via
_userMessageToOpenAI,_assistantMessageToOpenAI,_assistantMessageToolCallToOpenAI,_toolResultMessageToOpenAI - Converts
ctx.toolsto OpenAI function tool format via_toolsToOpenAI
IMP-012: Implement message converters (_userMessageToOpenAI,_assistantMessageToOpenAI,_assistantMessageToolCallToOpenAI,_toolResultMessageToOpenAI) — COMPLETED (seesrc/utils.jl:321-387)IMP-013: Implement_messageContentToBlocks— convertstextContent/imageContentto OpenAI content blocks — COMPLETED (seesrc/utils.jl:396-413)IMP-014: Implement_toolsToOpenAI— convertsOrderedDict{String, agentTool}to OpenAI tools array — COMPLETED (seesrc/utils.jl:429-447)IMP-015: ImplementbeforeToolCallhook default (returnsbeforeToolCallResult(false, "N/A")) — COMPLETED (seesrc/utils.jl:278-284)IMP-016: ImplementafterToolCallhook default (returnsnothing) — COMPLETED (seesrc/utils.jl:310-316)IMP-017: ImplementvalidateRequiredArgs(args, inputSchema)— validates required fields in tool arguments — COMPLETED (seesrc/utils.jl:479-497)IMP-018: ImplementvalidateToolArguments(tool, prepared)— wrapper that calls tool-specific or default hook — COMPLETED (seesrc/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 (seesrc/toolRegistry.jl:19-33)IMP-021: Implement_wrap_mcp_tool(mcpserver, tool_def)— wraps MCP tool asagentToolwithexecutecallingmcpserver("tools/call", ...)— COMPLETED (seesrc/toolRegistry.jl:41-106)- Handles MCP error responses (
haskey(response, "error")) - Extracts text and
isErrorfrom result
- Handles MCP error responses (
IMP-022: Implementregister_mcp_tools(tools, mcpserver)— queriestools/listwith pagination (nextCursor) — COMPLETED (seesrc/toolRegistry.jl:118-186)- Handles both
result.toolsandresult.errorresponse shapes - Skips already registered tools (idempotent)
- Handles both
IMP-023: ImplementregisterTool(tools, tool)— adds tool to OrderedDict — COMPLETED (seesrc/toolRegistry.jl:200-205)IMP-024: ImplementlistTool(tools, mcpserver)— builtin tool that triggers runtime discovery and lists all tools — COMPLETED (seesrc/toolRegistry.jl:235-271)IMP-025: ImplementregisterAllTools(tools, mcpserver)— discovers existing tools + registerslistTools— COMPLETED (seesrc/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: DefineyiemAgentstruct with channels, callbacks, MCP server — COMPLETED (seesrc/agentCore.jl:17-95)IMP-031: ImplementyiemAgentconstructor — creates channels, discovers MCP tools, spawns_agentLooptask — COMPLETED (seesrc/agentCore.jl:126-199)IMP-032: Implement_agentLoop(agent)— background@spawntask managinginputChannel/followUpChannelpriority dispatch — COMPLETED (seesrc/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, callsllmCall, extracts tool calls, executes, loops until no tool calls — COMPLETED (seesrc/agentCore.jl:394-544)while trueloop:llmCall()→_extractToolCalls()→ ifhasToolCalls && length > 0execute → 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 (seesrc/agentCore.jl:671-683) - Format 2:
response.contentblocks withtype => "tool_calls"ortype => "tool_call"(OpenAI API style) — COMPLETED (seesrc/agentCore.jl:685-719) - Extracts
reasoning_content,contenttext blocks,api,provider,model,usage,finish_reason— COMPLETED (seesrc/agentCore.jl:723-797) - Returns
(hasToolCalls, toolCallList, assistant_message)— COMPLETED (seesrc/agentCore.jl:799-827)
- Format 1:
IMP-035: ImplementprepareToolCall(context, assistantMsg, toolCall, config, signal, eventSink)— resolves tool, validates args, runsbeforeToolCallhook, never throws — COMPLETED (seesrc/agentCore.jl:974-1035)IMP-036: ImplementexecutePreparedToolCall(prep, signal, eventSink)— callstool.execute(toolCallId, args, ...)— COMPLETED (seesrc/agentCore.jl:1078-1100)IMP-037: ImplementfinalizeExecutedToolCall(context, msg, prep, executed, config, signal, eventSink)— runsafterToolCallhook, catches errors — COMPLETED (seesrc/agentCore.jl:1159-1198)IMP-038: ImplementprepareToolCallArguments(tool, toolCall)— callstool.prepareArgumentsif present — COMPLETED (seesrc/agentCore.jl:908-917)IMP-039: ImplementcreateErrorToolResult(msg)— buildsagentToolResultwith error content — COMPLETED (seesrc/agentCore.jl:572-574)IMP-040: ImplementcreateToolResultMessage(f)— buildstoolResultMessagefromfinalizedOutcome— COMPLETED (seesrc/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: ImplementpromptAgent(agent, msg::AbstractDict)— put toinputChannel, returns agent for chaining — COMPLETED (seesrc/api.jl:36-39)IMP-051: ImplementpromptAgent(agent, text::String)— wraps text as OpenAIDictand put toinputChannel— COMPLETED (seesrc/api.jl:41-44)IMP-052: ImplementtakeResponse(agent)— blocks onoutputChanneltake!, returns OpenAI dict response — COMPLETED (seesrc/api.jl:66-68)IMP-053: ImplementfollowUp(agent, msg::AbstractDict)— put tofollowUpChannel, returns agent — COMPLETED (seesrc/api.jl:94-97)IMP-054: ImplementfollowUp(agent, text::String)— wraps text as OpenAIDictand put tofollowUpChannel— COMPLETED (seesrc/api.jl:99-102)IMP-055: ImplementstopAgent(agent)— puts:shutdown,fetch(_agentLoop), closes all channels — COMPLETED (seesrc/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):
type.jl(no dependencies)utils.jl(depends ontype)toolRegistry.jl(depends ontype)agentCore.jl(depends ontype,utils,toolRegistry)api.jl(depends ontype,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.yamlreferencingci/julia-pipeline.yamlsteps - Add
Project.tomldependencies:[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 |