Here is the comprehensive developer guide for the `adk` directory.

## Quick Summary
The `adk` directory serves as the core integration layer between the Solace AI Connector framework and Google's Agent Development Kit (ADK). It provides the essential components for building, configuring, and running sophisticated AI agents within a Solace messaging environment.

The architecture is designed for modularity and extensibility. The `setup.py` module acts as the main configuration hub, using factory functions from `services.py` to initialize pluggable services (like `FilesystemArtifactService` for artifact storage) and loading tools (Python functions, MCP tools) via the `ADKToolWrapper`.

Once initialized, the `AppLlmAgent` (a custom agent class) is managed by the `runner.py` module, which handles the asynchronous task execution loop. The agent's behavior is dynamically augmented at runtime by a rich set of callbacks from `callbacks.py`. These callbacks inject dynamic instructions, manage large tool responses, log events to Solace, and handle advanced features like streaming artifact creation and auto-continuation of conversations. The `models/` subdirectory provides the concrete LLM clients, with `LiteLlm` offering broad compatibility with various model providers.

## Files and Subdirectories Overview
- **Direct files:**
  - `__init__.py`: Standard Python package initializer.
  - `app_llm_agent.py`: Defines a custom `LlmAgent` subclass that holds a reference to its host component.
  - `callbacks.py`: Provides a rich set of ADK callback functions for dynamic instructions, metadata injection, and Solace integration.
  - `filesystem_artifact_service.py`: A local filesystem-based implementation of ADK's `BaseArtifactService`.
  - `invocation_monitor.py`: A utility for monitoring and logging agent invocations to YAML files for debugging.
  - `runner.py`: Manages the asynchronous execution of ADK agent tasks, including cancellation support.
  - `services.py`: Contains factory functions for initializing ADK services (session, artifact, memory) based on configuration.
  - `setup.py`: Handles the high-level initialization of the ADK agent, tools, and runner.
  - `stream_parser.py`: An internal utility for parsing fenced artifact blocks from an LLM's streaming response.
  - `tool_wrapper.py`: A wrapper for Python functions to make them compatible with ADK, handling embed resolution and config injection.
- **Subdirectories:**
  - `models/`: Contains concrete `BaseLlm` implementations for interfacing with various LLM providers.

## Developer API Reference

### Direct Files

#### app_llm_agent.py
**Purpose:** A custom `LlmAgent` subclass that includes a reference to its hosting component, allowing callbacks and tools to access host-level configurations and services.
**Import:** `from agent.adk.app_llm_agent import AppLlmAgent`

**Classes/Functions/Constants:**
- `AppLlmAgent(host_component: Any = None, **kwargs)`: A custom `LlmAgent` that can be linked to a host component. The `host_component` is set post-initialization and is excluded from serialization.

#### callbacks.py
**Purpose:** Provides a suite of ADK callback functions that hook into the agent's lifecycle to inject custom logic. These are typically not called directly but are assigned to the agent during setup.
**Import:** `from agent.adk import callbacks`

**Classes/Functions/Constants:**
- `inject_dynamic_instructions_callback(...)`: Injects instructions into the prompt based on host configuration, active tools, and peer agents.
- `manage_large_mcp_tool_responses_callback(...)`: Intercepts large tool responses, saves them as artifacts, and returns a truncated summary to the LLM.
- `after_tool_callback_inject_metadata(...)`: After a tool creates an artifact, this loads its metadata and injects it into the tool response.
- `process_artifact_blocks_callback(...)`: Processes streaming text to identify and save fenced artifact blocks (e.g., `«««save_artifact:...»»»`).
- `auto_continue_on_max_tokens_callback(...)`: Automatically continues a conversation if the LLM response was interrupted due to token limits.
- `notify_tool_invocation_start_callback(...)`: Sends a status update over Solace when a tool is about to be invoked.
- `solace_llm_invocation_callback(...)`: Sends a status update over Solace when the agent calls the LLM.

#### filesystem_artifact_service.py
**Purpose:** An implementation of `BaseArtifactService` that stores artifacts on the local filesystem, organized by scope, user, and session.
**Import:** `from agent.adk.filesystem_artifact_service import FilesystemArtifactService`

**Classes/Functions/Constants:**
- `FilesystemArtifactService(base_path: str, scope_identifier: str)`: A service for managing artifacts on the local disk.
  - `async save_artifact(...) -> int`: Saves an artifact and returns its version number.
  - `async load_artifact(...) -> Optional[adk_types.Part]`: Loads a specific version of an artifact, or the latest if unspecified.
  - `async list_artifact_keys(...) -> List[str]`: Lists the names of all artifacts for a given user/session.
  - `async delete_artifact(...)`: Deletes an artifact and all its versions.

#### invocation_monitor.py
**Purpose:** A debugging utility that logs the entire lifecycle of an agent invocation, from the initial request to the final response, into a structured YAML file.
**Import:** `from agent.adk.invocation_monitor import InvocationMonitor`

**Classes/Functions/Constants:**
- `InvocationMonitor()`: A class that monitors and logs agent message flows.
  - `log_message_event(direction: str, topic: str, payload: any, ...)`: Logs a single message event. The monitor automatically starts and stops logging based on topic patterns.
  - `cleanup()`: Finalizes any active logging sessions.

#### runner.py
**Purpose:** Provides the core asynchronous task execution logic for the ADK agent, including robust cancellation handling.
**Import:** `from agent.adk.runner import run_adk_async_task_thread_wrapper, TaskCancelledError`

**Classes/Functions/Constants:**
- `run_adk_async_task_thread_wrapper(component, adk_session, adk_content, ...)`: A high-level wrapper that runs an ADK task in a separate thread and handles all cleanup and error finalization.
- `TaskCancelledError(Exception)`: Custom exception raised when an agent task is cancelled externally.

#### services.py
**Purpose:** Provides factory functions to initialize the various ADK services based on the agent's configuration file.
**Import:** `from agent.adk.services import initialize_session_service, initialize_artifact_service, initialize_memory_service`

**Classes/Functions/Constants:**
- `initialize_session_service(component) -> BaseSessionService`: Creates a session service (e.g., `InMemorySessionService`).
- `initialize_artifact_service(component) -> BaseArtifactService`: Creates an artifact service (e.g., `FilesystemArtifactService`, `GcsArtifactService`).
- `initialize_memory_service(component) -> BaseMemoryService`: Creates a memory service (e.g., `InMemoryMemoryService`).

#### setup.py
**Purpose:** The main entry point for configuring and instantiating the ADK agent and its dependencies. These functions tie all the other modules together.
**Import:** `from agent.adk.setup import load_adk_tools, initialize_adk_agent, initialize_adk_runner`

**Classes/Functions/Constants:**
- `async load_adk_tools(component) -> Tuple[...]`: Loads all configured tools, including Python functions, MCP tools, and built-ins, wrapping them with `ADKToolWrapper`.
- `initialize_adk_agent(component, loaded_explicit_tools, ...)`: Creates an `AppLlmAgent` instance, assigns all the necessary callbacks from `callbacks.py`, and attaches the tools.
- `initialize_adk_