This document records critical runtime fixes, hardening efforts, and architectural corrections implemented in the AgentDock generator and runner layers following end-to-end system audits.
- Component: Runtime Orchestrator (
apps/orchestrator/src/config/loader.ts) - Root Cause: The
workflow.yamlfile stores main configuration metadata (id,name,version) under a nestedworkflow:key, butconnectionsandagentsarrays live at the document's top level. The loader executedworkflow = raw?.workflow ?? workflow, replacing the configuration with the nested sub-object and discarding all workflow connections. Because of this, the trigger manager received an empty array and downstream agents never fired. - Fix: Merged the nested
workflowmetadata block with the top-level connections and agents lists:workflow = { ...(raw?.workflow ?? {}), connections: raw?.connections ?? raw?.workflow?.connections ?? [], agents: raw?.agents ?? raw?.workflow?.agents ?? [], };
- Component: Builder API Generator (
apps/builder-api/src/generator/agent-config-gen.ts) - Root Cause: When the LLM omitted the MCP
commandattribute (frequent with stdio-based servers), the generator emitted an empty string (command: '') inside the agent's configuration YAML. On container startup, the MCP client validated stdio transports, threw amcp_connect_failedexception, and crashed the runtime. - Fix: Added validation checks to filter out MCP entries with empty commands or invalid transport configurations before compiling the system configs.
- Component: Agent Runtime (
apps/agent-runtime/app/communication/task_receiver.py) - Root Cause: Smaller inference models (e.g., 0.6B parameters) occasionally returned empty strings due to context congestion or prompt fatigue. The runtime wrote these blank strings directly to output communication files, producing 0-byte outputs that stalled downstream pipeline steps.
- Fix: Implemented an output check. If an agent returns an empty output, the execution loop retries once with a simplified instruction prompt. If it fails a second time, the runtime throws an explicit execution exception rather than writing empty data.
- Component: Agent Runtime Git Memory (
apps/agent-runtime/app/memory/git.py) - Root Cause: Both the
write()andappend()methods in the memory manager spawned asynchronous background git commits viaasyncio.create_task(self.git.commit(...)). When multiple files (e.g.,task_queue.mdandstate.md) were updated simultaneously, concurrentgit add .executions collided, resulting in Git index lock errors (exit code 128). - Fix: Integrated an
asyncio.Lockinside theGitManagerclass. This serializes all git commit transactions for the agent's volume, guaranteeing thread-safe, non-overlapping updates.
- Component: Base Agent Image (
template/agent-base.Dockerfile) - Root Cause:
git initwas executed programmatically during python startup insideMemoryManager.setup(). However, if the docker volume was mounted or checked early during container health checks, git operations failed with "not a git repository" errors. - Fix: Moved repository initialization to the docker building layer by running
git init /memoryduring the Docker image compilation.
- Component: Agent Runtime (
apps/agent-runtime/app/communication/task_receiver.py) - Root Cause: Prompt templates reference
profiles/{{input.userId}}.mdto load user histories. If a user had no existing profile (e.g., on first interaction), the engine passed literal missing path instructions, confusing the LLM and wasting token budget on invalid tool calls. - Fix: The parser now verifies the existence of user state profiles. If a profile is absent, it injects a fallback message:
(no profile file found at ... — skip reading it and proceed with defaults).
- Component: Agent Runtime RAG (
apps/agent-runtime/app/rag/manager.py) - Root Cause: The embedding processor utilized a character-length sliding window (
chunk_size=500,chunk_overlap=50) that arbitrarily sliced markdown headers, code snippets, and sentences, introducing semantic noise and degrading retrieval accuracy. - Fix: Replaced the naive chunker with a markdown-aware parser that splits content hierarchically:
- Splitting on Markdown Headers (
#,##,###) to preserve section context. - Splitting on blank lines (paragraphs) when sections exceed max chunk size.
- Splitting on sentences as a final fallback.
- Splitting on Markdown Headers (