Index
agent_cover.instrumentation
Instrumentation Core.
This package orchestrates the interception of agent activities. It employs a Hybrid Instrumentation Strategy supported by a shared infrastructure layer.
🧠 Instrumentation Strategies
AgentCover distinguishes between Structured Objects (like Classes/Methods) and Unstructured Data (like Strings).
1. Direct Patching (Runtime Wrapping)
We wrap defined Python objects to intercept their lifecycle. Crucially, these patched objects interact to establish and respect the Execution Scope.
A. The Context System (Avoiding False Positives)
Some components (Tools, Prompts) are ambiguous: they can be called by the Agent or by your test setup code (e.g., asserting a prompt matches an expected string). To prevent false positives, we distinguish between Providers and Consumers:
-
Scope Providers: Agents wrap the main entry point (e.g.,
invoke). They activate the AgentContextManager, signaling "Agent Logic is running". -
Scope Consumers: Tools and Prompts wrap execution methods. They check the AgentContextManager. If the scope is inactive, they ignore the call.
B. Context-Agnostic Inspectors
Certain components inherently belong to the agent's runtime or represent system boundaries. They do not check the AgentContextManager because their execution implies a relevant event:
- LLM Providers:
Wraps API calls (e.g.,
openai.create). -
Why Agnostic: An LLM call is an expensive I/O operation that defines the agent's behavior. Whether it happens inside a framework or in a custom script, it is always a "Decision Point" worth analyzing. It represents the result of the agent's thinking, so we capture it unconditionally.
-
PromptFlow Runtime: Wraps PromptFlow internals (
render_jinja_template,@tool). -
Why Agnostic: PromptFlow is an orchestration framework. If its internal rendering functions are called, the agent execution is essentially active by definition.
-
Callbacks (detecting Raw Strings): Injects listeners into framework event loops (e.g., LangChain).
- Why Agnostic: The Agent's
CallbackManageris architecturally bound to the agent's lifecycle: it only executes when the agent runs, guaranteeing an implicit valid scope.
Configuration (targets.py):
To decouple patching logic from library definitions, each instrumentor relies on a specific targets.py registry (e.g., agents.targets).
2. Callback Injection (Event Listening)
Used for: Raw Strings.
Why: You cannot "patch" a python string definition (e.g., PROMPT = "...").
To track if a raw string was used, we must wait until it passes through a choke point. In frameworks like LangChain, the Callback System is that choke point.
- We inject a CoverageCallbackHandler that listens for
on_llm_start. - We scan the compiled prompt text sent to the LLM.
- We match this text against the regex patterns discovered by scan_raw_string_prompts.
3. Static Analysis (Source Scanning)
Used for: Discovery, Raw Strings Scanner, Structures Scanner, PromptFlow Scanner.
Why: Before code runs, we need a "map" of what exists. We scan source files and loaded modules to find:
- Files & Modules: The discovery module walks the file system to import user code.
- Heuristics: The raw_strings scanner reads source code to find global variables matching specific patterns.
- Data Structures: The structures scanner inspects Pydantic models to auto-generate decision rules.
- Definitions: The promptflow scanner parses YAML DAGs to identify Jinja templates.
🛠️ Core Infrastructure
The strategies above rely on a set of shared components defined in this package:
-
BaseInstrumentor (
base.py): The abstract base class for all instrumentors. It handles the lifecycle of applying/reverting patches (instrument()/uninstrument()), ensures idempotency (preventing double-patching), and manages Version Checkers to skip unsupported library versions. -
OutputAnalyzer (
analyzer.py): The verification engine. It receives raw text payloads (from LLM providers or callbacks) and performs "Fuzzy Parsing" to check if they satisfy the business rules defined inagent-cover.yaml. -
PatchManager (
base.py): A utility that performs the actualsetattr/getattroperations safely, ensuring that original methods can always be restored during cleanup. -
WrapperStrategies (
strategies.py): A collection of specialized wrappers (Sync, Async, Generator) that handle the complex logic of maintaining theContextVarstate across different execution models. -
TargetConfig (
definitions.py): Data classes used to strictly type the configuration of targets, ensuring validation of module paths and version strings.
Usage
While mostly used internally by the pytest plugin, you can manually trigger instrumentation:
from agent_cover.instrumentation import instrument_all
from agent_cover.registry import get_registry
# 1. Apply patches
instrument_all()
# 2. Run your agent code
my_agent.invoke("Hello world")
# 3. Check registry
reg = get_registry()
print(reg.executions)
Classes
AgentInstrumentor
Bases: BaseInstrumentor
Instruments agent classes with context management strategies.
This class handles the lifecycle of patching agent runners. It identifies target modules, loads them if necessary, resolves the specific classes, and wraps execution methods with the appropriate context managers.
Attributes:
| Name | Type | Description |
|---|---|---|
targets_provider |
A callable returning a list of targets to instrument. |
|
strategies |
A dictionary mapping strategy keys to WrapperStrategy instances. |
|
registry |
The agent registry instance. |
|
context_manager |
The context manager for handling agent contexts. |
|
patch_manager |
The manager responsible for applying and reverting patches. |
|
module_iterator |
A callable returning the current snapshot of sys.modules. |
|
importer_func |
A callable used to import modules by name. |
|
is_instrumented |
A boolean indicating if instrumentation has been applied. |
Methods:
| Name | Description |
|---|---|
instrument |
Performs the instrumentation process on all defined targets. |
Source code in src/agent_cover/instrumentation/agents/patcher.py
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
Functions
__init__(registry=None, context_manager=None, patch_manager=None, module_iterator=None, importer_func=None, targets_provider=None, strategies=None)
Initializes the AgentInstrumentor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
Optional registry for tracking agents. |
None
|
context_manager
|
Optional[AgentContextManager]
|
Optional manager for agent context. |
None
|
patch_manager
|
Optional[PatchManager]
|
Optional manager for handling patches. |
None
|
module_iterator
|
Optional[Callable[[], Dict[str, Any]]]
|
Optional callable to get current modules. |
None
|
importer_func
|
Optional[Callable[[str], Any]]
|
Optional callable to import modules. |
None
|
targets_provider
|
Optional[Callable[[], TargetList]]
|
Optional callable to provide instrumentation targets. |
None
|
strategies
|
Optional[Dict[str, WrapperStrategy]]
|
Optional dictionary of instrumentation strategies. |
None
|
Source code in src/agent_cover/instrumentation/agents/patcher.py
instrument()
Applies instrumentation to all discoverable agent targets.
This method iterates through the targets provided by the targets_provider. It attempts to load the module if it is not present, resolves the target class using the base class resolver, and applies the configured wrapper strategies to the specified methods.
Source code in src/agent_cover/instrumentation/agents/patcher.py
CoverageCallbackHandler
Bases: BaseCallbackHandler
A custom callback handler that integrates with AgentCover to track and analyze LLM and tool usage.
This handler acts as a bridge between the LangChain execution lifecycle and the AgentRegistry. It performs two main tasks:
- Raw String Detection: During
on_llm_start, it scans the prompt text to see if it matches any raw string patterns registered in the system. - Output Analysis: During
on_llm_endoron_chain_end, it captures the generated text and passes it to the OutputAnalyzer to verify if business decisions/rules are met.
Attributes:
| Name | Type | Description |
|---|---|---|
registry |
AgentRegistry
|
The registry instance used to track execution coverage. |
analyzer |
OutputAnalyzer
|
The component used to analyze LLM generations against configured decisions. |
Examples:
Manually using the handler without the global instrumentor:
from langchain_chat.chat_models import ChatOpenAI
from agent_cover.instrumentation.callbacks import CoverageCallbackHandler
# Create the handler
handler = CoverageCallbackHandler()
# Pass it to a LangChain model
llm = ChatOpenAI(callbacks=[handler])
llm.invoke("Hello world")
Source code in src/agent_cover/instrumentation/callbacks.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
Functions
__init__(registry=None, analyzer=None)
Initializes the CoverageCallbackHandler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
An optional |
None
|
analyzer
|
Optional[OutputAnalyzer]
|
An optional |
None
|
Source code in src/agent_cover/instrumentation/callbacks.py
on_chain_end(outputs, **kwargs)
Handles the end of a chain execution.
Analyzes the final chain outputs. This is useful for agents that return structured dictionaries rather than just raw strings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
outputs
|
Dict[str, Any]
|
The final dictionary returned by the chain. |
required |
**kwargs
|
Any
|
Additional keyword arguments. |
{}
|
Source code in src/agent_cover/instrumentation/callbacks.py
on_chain_end_async(outputs, **kwargs)
async
Asynchronously handles the end of a chain execution.
Delegates logic to on_chain_end.
Source code in src/agent_cover/instrumentation/callbacks.py
on_chat_model_start(serialized, messages, **kwargs)
Handles the start of a chat model call.
Iterates through the list of message objects (e.g., HumanMessage, SystemMessage),
extracts their content, and performs raw string detection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serialized
|
Dict[str, Any]
|
Metadata about the chat model. |
required |
messages
|
List[List[Any]]
|
A list of lists, where each inner list contains LangChain message objects. |
required |
**kwargs
|
Any
|
Additional arguments. |
{}
|
Source code in src/agent_cover/instrumentation/callbacks.py
on_chat_model_start_async(serialized, messages, **kwargs)
async
Asynchronously handles the start of a chat model call.
Delegates logic to on_chat_model_start.
Source code in src/agent_cover/instrumentation/callbacks.py
on_llm_end(response, **kwargs)
Handles the end of an LLM call to analyze output quality.
Extracts the generated text from the response object and passes it to the
analyzer to check for Decision Coverage (e.g., "Did the agent output 'REFUND'?").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Any
|
The |
required |
**kwargs
|
Any
|
Additional arguments. |
{}
|
Source code in src/agent_cover/instrumentation/callbacks.py
on_llm_end_async(response, **kwargs)
async
Asynchronously handles the end of an LLM call.
Delegates logic to on_llm_end.
Source code in src/agent_cover/instrumentation/callbacks.py
on_llm_start(serialized, prompts, **kwargs)
Handles the start of an LLM call to detect raw string usage.
It concatenates all input prompts into a single text block and checks if this block matches any regex patterns defined for "Raw String" prompts (variables tracked by scan_raw_string_prompts).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serialized
|
Dict[str, Any]
|
A dictionary containing the serialized LLM call information. |
required |
prompts
|
List[str]
|
A list of string prompts passed to the LLM. |
required |
**kwargs
|
Any
|
Additional keyword arguments. |
{}
|
Source code in src/agent_cover/instrumentation/callbacks.py
on_llm_start_async(serialized, prompts, **kwargs)
async
Asynchronously handles the start of an LLM call.
Delegates logic to on_llm_start.
Source code in src/agent_cover/instrumentation/callbacks.py
on_tool_start(serialized, input_str, **kwargs)
Handles the start of a tool call.
Note
Currently, this method is a placeholder. Tool execution tracking is primarily handled by the ToolInstrumentor which patches the tool methods directly, rather than relying on callbacks.
Source code in src/agent_cover/instrumentation/callbacks.py
GlobalCallbackInstrumentor
Bases: BaseInstrumentor
Instrumentor that globally injects the CoverageCallbackHandler into LangChain.
This class performs monkey-patching on langchain_core.callbacks.manager.CallbackManager
and AsyncCallbackManager. It wraps their __init__ methods to automatically
append a CoverageCallbackHandler
to every new manager instance.
Attributes:
| Name | Type | Description |
|---|---|---|
registry |
AgentRegistry
|
The registry instance. |
handler_factory |
Callable
|
A factory function that returns a new handler instance. |
Methods:
| Name | Description |
|---|---|
instrument |
Applies the instrumentation to Langchain's callback managers. |
_patch_manager_init |
Internal method to patch the init of a manager class. |
Source code in src/agent_cover/instrumentation/callbacks.py
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | |
Functions
__init__(registry=None, patch_manager=None, handler_factory=None)
Initializes the instrumentor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The registry instance. |
None
|
patch_manager
|
Optional[PatchManager]
|
The patch manager instance to ensure safe patching. |
None
|
handler_factory
|
Optional[Callable]
|
Optional factory for dependency injection (testing).
If None, defaults to creating a real |
None
|
Source code in src/agent_cover/instrumentation/callbacks.py
instrument()
Applies the patches to LangChain's CallbackManagers.
If langchain_core is not installed, this method returns silently.
Source code in src/agent_cover/instrumentation/callbacks.py
InspectionProvider
Helper class to abstract the calls to inspect that touch the filesystem.
Methods:
| Name | Description |
|---|---|
get_file |
Any) -> str: Returns the file path of the given object. |
get_source_lines |
Any) -> Tuple[List[str], int]: Returns the source code lines and starting line number of the given object. |
Source code in src/agent_cover/instrumentation/structures/scanner.py
Functions
get_file(obj)
Returns the file path of the given object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
The object to get the file path for. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The file path of the object. |
get_source_lines(obj)
Returns the source code lines and starting line number of the given object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
The object to get the source code lines for. |
required |
Returns:
| Type | Description |
|---|---|
Tuple[List[str], int]
|
A tuple containing the source code lines as a list of strings and the starting line number. |
Source code in src/agent_cover/instrumentation/structures/scanner.py
LLMProviderInstrumentor
Bases: BaseInstrumentor
Instrumentor that sits at the edge of the system (External APIs).
Unlike other instrumentors that track code coverage, this tracks Data Coverage. It intercepts the raw string response from the LLM to analyze if business logic requirements (Decisions) were met.
Attributes:
| Name | Type | Description |
|---|---|---|
registry |
Optional[AgentRegistry]
|
The registry for agent components. |
analyzer |
OutputAnalyzer
|
The component responsible for analyzing extracted text. |
importer_func |
Callable
|
Function used to import modules dynamically. |
module_iterator |
Callable
|
Function that returns the current mapping of loaded modules. |
targets_provider |
Callable
|
Function that returns a list of targets to instrument. |
extractors |
List[PayloadExtractor]
|
List of strategies used to parse LLM results. |
is_instrumented |
bool
|
Flag indicating if instrumentation has already run. |
Methods:
| Name | Description |
|---|---|
instrument |
Performs the actual patching of target methods. |
_resolve_target |
helper to find the specific object/method to patch. |
_create_wrapper |
Creates the closure that wraps the original method. |
_delegate_extraction |
Iterates through extractors to parse the result. |
Source code in src/agent_cover/instrumentation/llm_providers/patcher.py
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | |
Functions
__init__(registry=None, analyzer=None, patch_manager=None, importer_func=None, module_iterator=None, targets_provider=None, extractors=None)
Initializes the LLMProviderInstrumentor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The registry instance. |
None
|
analyzer
|
Optional[OutputAnalyzer]
|
Custom analyzer instance. |
None
|
patch_manager
|
Optional[PatchManager]
|
The patch manager for safe patching. |
None
|
importer_func
|
Optional[Callable]
|
Custom import function. |
None
|
module_iterator
|
Optional[Callable]
|
Custom module iterator provider (for dependency injection). |
None
|
targets_provider
|
Optional[Callable]
|
Custom provider for patch targets. |
None
|
extractors
|
Optional[List[PayloadExtractor]]
|
Custom list of payload extractors. |
None
|
Source code in src/agent_cover/instrumentation/llm_providers/patcher.py
instrument()
Applies patches to the defined LLM provider targets.
This method iterates through the targets provided by targets_provider.
It loads the necessary modules (using a snapshot to allow for test isolation)
and wraps the specified methods/functions to enable output analysis.
Source code in src/agent_cover/instrumentation/llm_providers/patcher.py
PromptFlowInstrumentor
Bases: BaseInstrumentor
Instruments Microsoft PromptFlow components.
PromptFlow defines flows using a mix of YAML configuration (flow.dag.yaml),
Python tools (@tool), and Jinja2 templates. This instrumentor applies patches
to track:
- Template Rendering: Patches internal render functions to track when a Jinja template is used.
- Tool Execution: Wraps the
@tooldecorator to track when a node in the flow is executed.
It works in tandem with scan_promptflow_definitions
which statically registers the files found in the DAG.
Attributes:
| Name | Type | Description |
|---|---|---|
analyzer |
OutputAnalyzer
|
The analyzer used to process execution results. |
targets_provider |
Callable
|
A function that returns a list of targets to instrument. |
registry |
AgentRegistry
|
The registry where execution data is stored. |
patch_manager |
PatchManager
|
Manager for applying and reverting patches. |
module_iterator |
Callable
|
Function to retrieve current sys.modules. |
importer_func |
Callable
|
Function to import modules dynamically. |
is_instrumented |
bool
|
Flag indicating if instrumentation has already run. |
Methods:
| Name | Description |
|---|---|
instrument |
Applies patches to the target PromptFlow modules. |
Source code in src/agent_cover/instrumentation/promptflow/patcher.py
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | |
Functions
__init__(registry=None, analyzer=None, patch_manager=None, module_iterator=None, importer_func=None, targets_provider=None)
Initializes the PromptFlowInstrumentor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The agent registry instance. |
None
|
analyzer
|
Optional[OutputAnalyzer]
|
Optional output analyzer instance. |
None
|
patch_manager
|
Optional[PatchManager]
|
Optional patch manager instance. |
None
|
module_iterator
|
Optional[Callable[[], Dict[str, Any]]]
|
Optional callable to get current modules. |
None
|
importer_func
|
Optional[Callable[[str], Any]]
|
Optional callable to import modules. |
None
|
targets_provider
|
Optional[Callable[[], TargetList]]
|
Optional callable to provide instrumentation targets. |
None
|
Source code in src/agent_cover/instrumentation/promptflow/patcher.py
instrument()
Applies runtime patches to PromptFlow's core modules.
It targets:
- promptflow.tools.common.render_jinja_template: To catch prompt usage.
- promptflow.core.tool: To catch python tool usage.
Note
This method is fault-tolerant; if PromptFlow is not installed, it simply skips instrumentation without raising errors.
Source code in src/agent_cover/instrumentation/promptflow/patcher.py
PromptInstrumentor
Bases: BaseInstrumentor
Instruments prompt classes to track their definition and runtime usage.
This instrumentor applies a dual-strategy approach:
1. Init Strategy: Patches __init__ to register the prompt instance in the registry immediately upon creation. This establishes the "Total Prompts" count.
2. Execution Strategy: Patches methods like format or format_messages to track when a prompt is actually used by the agent.
Attributes:
| Name | Type | Description |
|---|---|---|
registry |
AgentRegistry
|
The registry to store coverage data. |
init_strategy |
PromptInitStrategy
|
Strategy for wrapping initialization. |
exec_strategy |
PromptExecutionStrategy
|
Strategy for wrapping execution methods. |
Examples:
How it tracks a LangChain prompt:
# 1. __init__ triggers registration (Definition Coverage)
prompt = PromptTemplate.from_template("Hello {name}")
# 2. format() triggers execution (Runtime Coverage)
prompt.format(name="World")
Source code in src/agent_cover/instrumentation/prompts/patcher.py
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | |
Functions
__init__(registry=None, context_manager=None, patch_manager=None, module_iterator=None, importer_func=None, targets_provider=None, init_strategy=None, exec_strategy=None, stack_walker=None)
Initializes the PromptInstrumentor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The AgentRegistry. |
None
|
context_manager
|
Optional[AgentContextManager]
|
The AgentContextManager. |
None
|
patch_manager
|
Optional[PatchManager]
|
The PatchManager. |
None
|
module_iterator
|
Optional[Callable[[], Dict[str, Any]]]
|
A callable to iterate through modules. |
None
|
importer_func
|
Optional[Callable[[str], Any]]
|
A function to import modules. |
None
|
targets_provider
|
Optional[Callable[[], TargetList]]
|
A callable to provide instrumentation targets. |
None
|
init_strategy
|
Optional[PromptInitStrategy]
|
The strategy for wrapping the init method. |
None
|
exec_strategy
|
Optional[PromptExecutionStrategy]
|
The strategy for wrapping execution methods. |
None
|
stack_walker
|
Optional[Callable[[Any], Iterator[Any]]]
|
A callable used to walk the stack and |
None
|
Source code in src/agent_cover/instrumentation/prompts/patcher.py
instrument()
Instruments the prompts.
This method retrieves the targets, iterates through the modules, and applies the appropriate strategies to patch the prompt classes.
Source code in src/agent_cover/instrumentation/prompts/patcher.py
ToolInstrumentor
Bases: BaseInstrumentor
Instrumentor for Tool classes and decorators.
This class handles the complexity of tracking tools across different frameworks.
It distinguishes between:
- Class-based Tools: (e.g., LangChain's BaseTool) where we patch _run and _arun.
- Decorated Tools: (e.g., @tool) where we wrap the decorated function.
It ensures that every tool available to the agent is registered as a "coverage target".
Methods:
| Name | Description |
|---|---|
register_existing_tools |
Scans the memory for tools that were instantiated before instrumentation started. |
instrument |
Applies patches to the classes defined in |
Source code in src/agent_cover/instrumentation/tools/patcher.py
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | |
Functions
__init__(registry=None, context_manager=None, patch_manager=None, module_iterator=None, importer_func=None, targets_provider=None, stack_walker=None)
Initializes the ToolInstrumentor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The agent registry to record data into. |
None
|
context_manager
|
The context manager for tracking execution flow. |
None
|
|
patch_manager
|
Optional[PatchManager]
|
The manager responsible for applying safe patches. |
None
|
module_iterator
|
Optional[Callable[[], Dict[str, Any]]]
|
A callable that returns the current snapshot of sys.modules. |
None
|
importer_func
|
Optional[Callable[[str], Any]]
|
A callable to import modules dynamically. |
None
|
targets_provider
|
Optional[Callable[[], TargetList]]
|
A callable returning specific tool classes to target. |
None
|
stack_walker
|
Optional[Callable[[Any], Iterator[Any]]]
|
A callable to walk the stack for location resolution. |
None
|
Source code in src/agent_cover/instrumentation/tools/patcher.py
instrument()
Performs the instrumentation process for tools.
It iterates through the targets, resolves the classes (e.g. langchain.tools.BaseTool),
and applies a wrapper that records execution to the AgentRegistry
before delegating to the original method.
Source code in src/agent_cover/instrumentation/tools/patcher.py
register_existing_tools()
Scans currently loaded modules for tools that may have been missed.
This is useful for tools instantiated before the instrumentor was initialized. It scans variables in loaded modules to find objects that look like tools.
Source code in src/agent_cover/instrumentation/tools/patcher.py
Functions
instrument_all(registry=None, context_manager=None, patch_manager=None, analyzer=None, config=None, importer_func=None, module_iterator=None, inspection_provider=None, targets_provider_map=None, stack_walker=None)
Applies all available instrumentation strategies.
This function orchestrates the initialization and execution of various instrumentors, including raw strings, callbacks, agents, prompts, tools, LLM providers, and PromptFlow. It uses dependency injection to allow custom implementations for testing purposes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The agent registry to use. If None, the global registry is used. |
None
|
context_manager
|
Optional[AgentContextManager]
|
The context manager for tracking agent state. |
None
|
patch_manager
|
Optional[PatchManager]
|
The manager for applying safe patches. |
None
|
analyzer
|
Optional[OutputAnalyzer]
|
The analyzer for processing outputs. |
None
|
config
|
Optional[AgentCoverConfig]
|
The configuration object. |
None
|
importer_func
|
Optional[Callable[[str], Any]]
|
Optional function to import modules (for DI). |
None
|
module_iterator
|
Optional[Callable[[], Dict[str, Any]]]
|
Optional function to iterate over modules (for DI). |
None
|
inspection_provider
|
Optional[InspectionProvider]
|
Optional provider for code inspection (for DI). |
None
|
targets_provider_map
|
Optional[Dict[str, Callable]]
|
Optional map of target providers (for DI). |
None
|
stack_walker
|
Optional[Callable[[Any], Iterator[Any]]]
|
Optional function to walk the stack (for DI). |
None
|
Returns:
| Type | Description |
|---|---|
List[BaseInstrumentor]
|
List[BaseInstrumentor]: A list of successfully initialized and |
List[BaseInstrumentor]
|
active instrumentor instances. |
Source code in src/agent_cover/instrumentation/__init__.py
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | |
instrument_promptflow(registry=None)
Legacy helper function to instantiate and run the instrumentor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
Optional AgentRegistry instance. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
PromptFlowInstrumentor |
The instrumentor instance. |
Source code in src/agent_cover/instrumentation/promptflow/patcher.py
register_existing_prompts(registry=None, root_path=None, module_iterator=None)
Registers existing prompts by scanning modules.
This function scans modules for prompts that are already defined.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The AgentRegistry to register the prompts with. |
None
|
root_path
|
Optional[str]
|
The root path to search for modules. |
None
|
module_iterator
|
Optional[Callable]
|
A callable to iterate through modules. |
None
|
Source code in src/agent_cover/instrumentation/prompts/patcher.py
scan_pydantic_models(registry=None, config=None, root_path=None, adapter_registry=None, module_iterator=None, inspector=None)
Scans loaded modules to automatically generate Business Logic decisions.
This function inspects Pydantic models and Dataclasses to find fields with
finite sets of expected values. It automatically populates the
AgentCoverConfig with these rules.
Supported Types:
- Enum: Expects all enum members.
- Literal: Expects all literal values (e.g., Literal["yes", "no"]).
- Bool: Expects True and False.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The AgentRegistry instance. Defaults to the result of get_registry(). |
None
|
config
|
Optional[AgentCoverConfig]
|
The AgentCoverConfig instance. Defaults to the result of get_config(). |
None
|
root_path
|
Optional[str]
|
The root path to scan for modules. Defaults to the current working directory. |
None
|
adapter_registry
|
Optional[AdapterRegistry]
|
The AdapterRegistry instance. Defaults to the result of get_default_adapter_registry(). |
None
|
module_iterator
|
Optional[Callable[[], Dict[str, Any]]]
|
A callable that returns an iterator over the modules. Defaults to _default_module_iterator. |
None
|
inspector
|
Optional[InspectionProvider]
|
An instance of InspectionProvider for abstracting inspect calls. Defaults to None. |
None
|
Examples:
If you have this model:
This scanner creates a Decision rule expecting both "POSITIVE" and "NEGATIVE" to appear in thelabel field during testing.
Source code in src/agent_cover/instrumentation/structures/scanner.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | |
scan_raw_string_prompts(registry=None, root_path=None, module_iterator=None, source_reader=None)
Scans for raw string prompts in Python modules and registers them.
It iterates through all loaded modules in sys.modules that reside within
root_path. For each string variable matching the configured prefixes/suffixes,
it:
1. Calculates a regex pattern for runtime matching.
2. Registers it in the AgentRegistry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
An optional AgentRegistry instance. If not provided, it defaults to the global registry. |
None
|
root_path
|
Optional[str]
|
An optional root path to start the scan from. If not provided, it defaults to the current working directory. |
None
|
module_iterator
|
Optional[Callable[[], Dict[str, Any]]]
|
An optional callable for iterating through loaded modules. Defaults to _default_module_iterator. |
None
|
source_reader
|
Optional[Callable[[str], List[str]]]
|
An optional callable for reading source file contents. Defaults to _default_source_reader. |
None
|
Source code in src/agent_cover/instrumentation/raw_strings/scanner.py
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
scan_static_definitions(registry=None, config=None, root_path=None, module_iterator=None, source_reader=None, inspector=None)
Scans the codebase for static definitions.
This function triggers static analysis to identify prompts, raw strings, and data structures (like Pydantic models) without executing the code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
registry
|
Optional[AgentRegistry]
|
The agent registry to store findings. |
None
|
config
|
Optional[AgentCoverConfig]
|
The configuration object. |
None
|
root_path
|
Optional[str]
|
The root directory to scan. |
None
|
module_iterator
|
Optional[Callable]
|
Optional function to iterate over modules. |
None
|
source_reader
|
Optional[Callable]
|
Optional function to read source files. |
None
|
inspector
|
Optional[InspectionProvider]
|
Optional provider for code inspection. |
None
|