8.8 KiB
YiemAgent: Agile Agent Framework
1. Business Context & Success Metrics
Business Goal
YiemAgent is a Julia-based AI agent framework that enables building chatbot assistants with tool-calling capabilities, model-agnostic LLM integration, and runtime tool discovery via MCP (Model Context Protocol). It provides an asynchronous agent loop with channel-based message passing, supporting both single-turn and multi-turn conversations with automatic tool call resolution.
User Stories
- US-001: As a developer, I want to create an AI agent with a simple constructor so that I can quickly prototype chatbot functionality in Julia
- US-002: As a developer, I want the agent to discover tools automatically from an MCP server so that I don't need to manually register tool APIs
- US-003: As a developer, I want the agent to handle tool calls automatically in a loop so that the LLM can use tools without external orchestration
- US-004: As a developer, I want to intercept tool calls with before/after hooks so that I can add user approval, logging, or result sanitization
- US-005: As a developer, I want the framework to support multiple LLM models and providers through a pluggable
llmCallinterface so that I can swap models without changing agent logic
KPIs & Targets
- KPI-001: Agent loop processes messages with <500ms overhead for sequential tool calls (validates US-003)
- KPI-002: MCP tool discovery completes within 2 seconds for 50+ tools (validates US-002)
- KPI-003: 100% of message types have OpenAI format conversion (validates US-001)
2. Technical Boundaries
In Scope
- Julia module implementing an AI agent with asynchronous message processing
- Channel-based input (user→agent), follow-up (async queue), and output (agent→user) interfaces
- LLM model abstraction with tool call extraction from multiple response formats (OpenAI content blocks, LMStudio/vLLM format)
- Tool registry with MCP server integration (tools/list, tools/call via JSON-RPC 2.0)
- Agent loop with before/after tool call hooks for lifecycle management
- Message type system with OpenAI format conversion utilities
- Abort signal and termination flag support via tool implementations
Out of Scope
- GUI/CLI interface (exposed via channels only; UI layer is external)
- Persistent chat history or long-term memory (TODO comments in code)
- Multi-agent orchestration (single agent instance per
yiemAgentstruct) - Embedding generation or retrieval-augmented generation (RAG)
- Natural language-to-code generation or execution sandboxes
Dependencies
- Julia Standard Library:
Dates,UUIDs,Base.Threads - External Packages:
JSON,DataStructures,HTTP,PrettyPrinting,Serialization,DataFrames - Internal Package:
GeneralUtils(project-specific utility library) - Optional:
NATS(MCP server communication),LibPQ(PostgreSQL)
Deployment Constraints
- NFR-001: Library designed for embedded use in Docker containers (MicroK8s cluster, per
NFR-501from template) - NFR-002: Must support Julia 1.9+ for module include/export semantics compatibility
- NFR-003: Thread-safe channel operations; single-agent instance processes messages sequentially on background
@spawntask
3. Functional Requirements (FR)
FR-001: Agent Message Processing
The agent shall process user messages through an asynchronous loop that:
- Accepts messages via
inputChannel(capacity 16) andfollowUpChannel(capacity 32) - Prioritizes
inputChannelmessages overfollowUpChannelmessages - Feeds responses to
outputChannel(capacity 16) in OpenAI message format - Exits cleanly on
:shutdownsignal
Traceability: US-001, US-003
FR-002: LLM Model Agnosticism
The agent shall accept a pluggable llmCall function that:
- Receives formatted messages and returns an LLM response dict
- The response dict may contain
message.tool_calls(LMStudio format) orcontentblocks (OpenAI format) - The framework extracts tool calls regardless of response format
Traceability: US-005
FR-003: Tool Call Execution Loop
The agent shall automatically execute tool calls returned by the LLM:
- Extract tool calls via
_extractToolCalls()which supports bothmessage.tool_callsandcontent[{type="tool_calls"}]formats - Build
agentContextviaprepareContext()(pluggable hook) - Format messages via
formatMsgForLLM()to OpenAI format - Extract tool calls → loop: execute tool calls → append results to history → call LLM again
- Break loop when LLM response has no tool calls
- Support
terminateflag: iftoolResultBatch.terminate == true, break loop and return final response
Traceability: US-003
FR-004: Tool Discovery and Registration
The agent shall:
- Query MCP server via
mcpserver("tools/list")(JSON-RPC 2.0) to discover tools - Support pagination via
nextCursorfield - Wrap each MCP tool definition as an
agentToolwithexecutehook that callsmcpserver("tools/call", name, args, sessionId) - Register a builtin
listToolstool that triggers runtime discovery and lists all available tools - Skip tools already registered (idempotent)
Traceability: US-002
FR-005: Tool Call Lifecycle Hooks
The agent shall support two lifecycle hooks:
beforeToolCall(beforeToolCallContext, signal)— can block execution by returningbeforeToolCallResult(true, reason)afterToolCall(afterToolCallContext)— can transform result by returning modifiedagentToolResult- Errors from hooks are caught and converted to
immediateOutcome/error tool result messages (never throw)
Traceability: US-004
FR-006: Message Type Conversion
The agent shall:
- Convert internal message types (
userMessage,assistantMessage,assistantMessageToolCall,toolResultMessage) to OpenAI format via_userMessageToOpenAI(),_assistantMessageToOpenAI(),_assistantMessageToolCallToOpenAI(),_toolResultMessageToOpenAI() - Convert internal
messageContenttypes (textContent,imageContent,reasoningContent) to OpenAI content blocks via_messageContentToBlocks() - Convert
agentTooldefinitions to OpenAI function tool format via_toolsToOpenAI()
Traceability: US-001
4. Non-Functional Requirements (NFRs)
4.1 Performance & Scalability
- NFR-101: Agent loop message processing overhead <500ms per sequential tool call (measured KPI: KPI-001)
- NFR-102: MCP tool discovery for 50+ tools completes within 2 seconds (measured KPI: KPI-002)
- NFR-103: Channel buffers prevent unbounded memory growth —
inputChannel(16),followUpChannel(32),outputChannel(16)
4.2 Availability & Reliability
- NFR-201: Agent loop catches all errors via
try/catchin_agentLoop()and callseventSink(errMsg)before exit (measured by event sink logging) - NFR-202:
prepareToolCall()never throws errors — validation failures returnimmediateOutcomewith error tool result
4.3 Privacy & Security
- Data Classification: Tool arguments and results may contain PII (user messages); MCP tool results treated as untrusted input
- No built-in auth/authz: Responsibility of
mcpServerimplementation andbeforeToolCallhook - Input validation: JSON schema validation via
validateToolArguments()checks required fields only (tools need custom validation viavalidateRequiredArgshook)
4.4 Observability & Telemetry
- Required Logs:
agentLoopevents (viaeventSink) emit state machine steps (_agentLoop 1through_agentLoop 6),_processMessagesteps (1 through 18),prepareToolCallsteps (1 through 10) - Critical Metrics:
agent._state.messages.length— conversation history size (logged at each step)toolExecutionStart/toolExecutionEndevents (viatoolExecStartEvent,toolExecEndEventstructs)
- Retention: No built-in log retention; agent is a library, does not manage external logging
5. Acceptance Conditions
- FR-001: Agent processes messages through channel system with priority ordering (inputChannel > followUpChannel)
- FR-002:
llmCallis pluggable; response formats supported includemessage.tool_callsdict andcontentarray blocks - FR-003: Agent loops on tool calls until LLM returns no tool calls or terminate flag is set
- FR-004: MCP tools are discovered via
tools/listwith pagination; all registered tools are callable viatools/call - FR-005:
beforeToolCallhook can block;afterToolCallhook can transform result; errors return error tool result - FR-006: All message types (userMessage, assistantMessage, assistantMessageToolCall, toolResultMessage) convert to OpenAI format
- NFR-101: Message processing overhead <500ms per sequential tool call
- NFR-102: MCP discovery for 50+ tools completes <2 seconds
- NFR-201: Agent loop catches errors and exits gracefully without panics