Prompt Detection Strategies
Overview
When executing commands on network devices via terminal (SSH/Telnet), RADKit needs to detect when a command has finished executing and the device is ready for the next input. This is achieved through prompt detection strategies.
A prompt detection strategy is an algorithm that determines when command execution is complete by monitoring the terminal output stream and identifying patterns, timeouts, or other indicators that signal readiness for new input.
RADKit provides five built-in strategies, each optimized for different scenarios and device behaviors:
Test Probe (default) - Active marker injection with backoff algorithms
Auto Prompt - Discovers prompt dynamically, then uses regex matching
Regex - Pattern-based matching for known prompt formats
Timeout - Simple wait-based detection for fixed-duration commands
Idle Detection - Monitors stream inactivity to detect completion
Note
Prompt detection is automatically handled by RADKit during command
execution via Device.exec().
Most users will not need to explicitly configure these strategies, as
the default Test Probe strategy works reliably across most device
types.
Available Strategies
Device-Type Aware Defaults
RADKit automatically selects a prompt detection strategy based on the device type. This infrastructure allows the system to optimize behavior for specific network operating systems and platforms when needed.
Current Defaults:
Most device types (IOS-XR, NX-OS, ASA, Linux, etc.) default to the Test Probe with Exponential Backoff strategy, which has proven reliable across all platforms.
IOS-XE exception: For IOS-XE devices, RADKit automatically switches
to the Auto Prompt strategy when the command contains
show platform integrity. This is because these commands abort their
output if any keystroke (including a test probe) is received during
execution.
Overriding Device-Type Defaults:
You can override the automatic default by explicitly specifying a
prompt_detection_strategy parameter:
from radkit_client import RegexPromptDetectionStrategy
device = client.get_device("device-id")
# Uses device-type default (test-probe-exponential-backoff)
result = device.exec("show version")
# Explicitly override with regex strategy
result = device.exec(
"show version",
prompt_detection_strategy=RegexPromptDetectionStrategy(
patterns=[r"[\w\-]+#\s*$"],
max_timeout=15.0,
),
)
Test Probe Strategy (Default)
The test probe strategy is the default and most reliable method for prompt detection. It works by actively injecting marker strings into the terminal session and detecting when they appear in the output.
How it works:
Clears the terminal screen (CTRL+L)
Sends the user’s command
Injects a unique marker string (e.g.,
$prompttest-1$)Monitors output until the marker appears on the current line
Removes the marker using CTRL+U (line erase)
Returns captured output
Variants:
test-probe-exponential-backoff: Increases wait time exponentially between detection attempts (default)test-probe-linear-backoff: Increases wait time linearlytest-probe-constant-backoff: Uses fixed wait time between attempts
Configuration example:
from radkit_client import TestProbeExponentialBackoffPromptDetectionStrategy
strategy = TestProbeExponentialBackoffPromptDetectionStrategy(
max_probes=50, # Maximum marker injection attempts
read_chunk_timeout=1.0, # Timeout for each read attempt (seconds)
)
When to use: Default choice for most devices. Highly reliable but slightly intrusive due to marker injection.
Advantages:
Most reliable across different device types
Handles devices with unpredictable prompt formats
Automatically adapts timing with backoff algorithms
Disadvantages:
Injects test markers that briefly appear in terminal
Slightly more overhead than passive strategies
Auto Prompt Strategy
The auto prompt strategy first discovers the current prompt by sending
an empty \r command using the test probe technique. Once the prompt
is known, it switches to regex-based matching for the actual command,
avoiding any further keystrokes during output collection.
This makes it the correct choice for commands that abort their output
when a keystroke is received mid-stream (e.g., show platform integrity
sign on IOS-XE).
How it works:
Sends an empty
\rusing the test probe strategy to capture the current promptBuilds a set of regex patterns from the discovered prompt (also replacing the trailing
>,$, or#to handle prompt changes)Sends the actual command
Uses the regex strategy to detect completion by matching the known prompt
Configuration example:
from radkit_client import AutoPromptDetectionStrategy
strategy = AutoPromptDetectionStrategy(
max_probes=50, # Probes used for initial prompt discovery
max_timeout=15.0, # Max wait for regex match on actual command
read_chunk_timeout=1.0,
)
When to use: For commands that abort their output when receiving any
keystroke during execution, such as show platform integrity sign on
IOS-XE. RADKit enables this strategy automatically for those commands.
Advantages:
Non-intrusive during actual command output collection
No prior knowledge of the prompt format required
Handles prompt changes (e.g.,
>to#) caused by the command
Disadvantages:
Slightly slower than pure regex (requires an extra round-trip to discover the prompt)
Falls back silently if prompt discovery fails
The regex strategy detects prompts by matching regular expression patterns against the terminal output stream.
How it works:
Sends the user’s command
Continuously reads output chunks
Checks each chunk against configured regex pattern(s)
Returns captured output when a match is found
Falls back to timeout if no match occurs within
max_timeout
Configuration example:
from radkit_client import RegexPromptDetectionStrategy
# Single pattern
strategy = RegexPromptDetectionStrategy(
patterns=r"#\s*$", # Match '#' followed by optional whitespace at line end
max_timeout=15.0,
match_mode="current-line", # or "full-buffer"
)
# Multiple patterns (alternation)
strategy = RegexPromptDetectionStrategy(
patterns=[
r"#\s*$", # Privileged mode prompt
r">\s*$", # User mode prompt
r"\$\s*$", # Shell prompt
],
max_timeout=15.0,
match_mode="current-line",
)
Match modes:
current-line: Match pattern only against the last line of output (faster, recommended)full-buffer: Match pattern anywhere in the entire output buffer (slower, use for prompts appearing mid-output)
When to use: When device prompts follow consistent, predictable patterns. Ideal for homogeneous device environments.
Advantages:
Non-intrusive (passive detection)
Fast when patterns match quickly
No terminal manipulation required
Disadvantages:
Requires knowing device prompt patterns in advance
May fail on devices with dynamic/changing prompts
Can produce false positives if pattern matches command output
Timeout Strategy
The timeout strategy simply waits a fixed duration after sending the command, then returns all accumulated output.
How it works:
Sends the user’s command
Waits for
wait_timesecondsOptionally exhausts remaining stream data
Returns all captured output
Configuration example:
from radkit_client import TimeoutPromptDetectionStrategy
strategy = TimeoutPromptDetectionStrategy(
wait_time=5.0, # Wait 5 seconds after sending command
exhaust_stream=True, # Read remaining data after wait_time (default: False)
stream_exhausting_timeout=0.5, # Timeout for draining remaining data
)
When to use: For devices without interactive prompts, or commands with known execution duration. Also useful for troubleshooting when other strategies fail.
Advantages:
Extremely simple and predictable
Works on any device type
Useful for commands with fixed execution time
Disadvantages:
Inefficient (waits full duration even if command finishes earlier)
May truncate slow command output if timeout is too short
No confirmation that command actually completed
Idle Detection Strategy
The idle detection strategy monitors the output stream for periods of inactivity, confirming the command is complete when no data arrives for multiple consecutive timeout periods.
How it works:
Sends the user’s command
Monitors stream for data arrival
Counts consecutive
idle_timeoutperiods with no dataReturns captured output when
confirmation_readsconsecutive idle periods are detectedEnforces
max_total_timeas an absolute timeout limit
Configuration example:
from radkit_client import IdleDetectionStrategy
strategy = IdleDetectionStrategy(
idle_timeout=1.0, # Timeout for each idle check (seconds)
confirmation_reads=3, # Number of consecutive idle periods to confirm
max_total_time=60.0, # Absolute maximum wait time (seconds)
)
When to use: For commands that produce intermittent output (e.g., ping, traceroute) or devices where prompt detection is unreliable.
Advantages:
Handles commands with slow/intermittent output
Adapts to actual command execution time
More robust than simple timeout
Disadvantages:
Slower than active detection strategies
May trigger prematurely if command has long pauses
Requires tuning parameters for optimal performance
Using Strategies with Device.exec()
Basic Usage
To use a specific strategy, pass it to the prompt_detection_strategy
parameter of Device.exec():
>>> from radkit_client import RegexPromptDetectionStrategy
>>> response = device.exec(
... "show version",
... prompt_detection_strategy=RegexPromptDetectionStrategy(
... patterns=r"router1#\s*$",
... max_timeout=15.0,
... ),
... )
>>> response.wait()
>>> print(response.data)
It is also possible to specify a strategy per individual command, when multiple
commands are passed to Device.exec(), by passing
Command objects instead of strings:
>>> from radkit_client import AutoPromptDetectionStrategy, RegexPromptDetectionStrategy
>>> from radkit_client.sync import Command
>>> response = device.exec(
... [
... Command(
... "show version",
... # Override prompt detection strategy for this command.
... prompt_detection_strategy=AutoPromptDetectionStrategy(),
... ),
... Command(
... "show clock"
... ),
... ],
... # Default strategy for commands that don't specify a strategy. If
... # not passed at all, the service will choose the default.
... prompt_detection_strategy=RegexPromptDetectionStrategy(
... patterns=r"router1#\s*$",
... ),
... )
Forward and Backward Compatibility
Warning
The direct-model style shown above is the recommended approach. This class is made for power-users; it is only recommended as a workaround, in conjunction with expert advice from Cisco.
If you have existing code using the GenericPromptDetectionStrategy wrapper, or need
to use a strategy name/options not yet modelled by the current client version,
the wrapper is still supported.
The name field accepts both PromptDetectionStrategyName enum
values and plain strings, and options accepts both Pydantic model
instances and plain dictionaries. This means you can use strategies that
a newer RADKit Service supports even if your client version doesn’t have
the corresponding enum or model yet:
from radkit_client import GenericPromptDetectionStrategy
# Existing code using the wrapper still works unchanged
strategy = GenericPromptDetectionStrategy(
name="regex-prompt",
options={
"patterns": r"#\s*$",
},
)
# Also useful for strategies added in a newer Service version that the
# current client does not yet model
strategy = GenericPromptDetectionStrategy(
name="some-future-strategy",
options={
"some_param": 42,
},
)
Note
Strategy resolution happens on the service side. The client serializes the strategy name and options and sends them over the wire, which allows older clients to use new strategies added in newer service versions.
Performance Considerations
Strategy Performance Comparison
Strategy |
Speed |
Reliability |
Device Support |
Best Use Case |
|---|---|---|---|---|
Test Probe (default) |
Medium |
Very High |
Universal |
General purpose, heterogeneous environments |
Auto Prompt |
Medium |
High |
Universal |
Commands that abort on keystrokes (e.g., |
Regex |
Fast |
Medium |
Universal |
Homogeneous environments with known prompts |
Timeout |
Slow |
Medium |
Universal |
Fixed-duration commands, troubleshooting |
Idle Detection |
Medium-Slow |
Medium |
Universal |
Commands with intermittent output |
Optimization Tips
Use regex strategy for performance-critical scenarios when prompt patterns are well-known and consistent.
Tune backoff parameters for test probe strategy based on device response times:
Fast devices: Use smaller initial/max intervals
Slow devices: Increase max_probes and timeouts
Adjust timeout values based on command characteristics:
Quick commands (show, status): 5-10 seconds
Configuration commands: 15-30 seconds
Long-running commands (backup, copy): 60+ seconds
Use idle detection for commands with variable execution time (e.g., pings with dynamic counts).
Best Practices
Strategy Selection Guidelines
Start with the default (test probe with exponential backoff) - it works reliably for most devices.
Switch to auto prompt if:
The command aborts its output when any keystroke is received (e.g.,
show platform integrity signon IOS-XE)RADKit enables this automatically for known affected commands
Switch to regex if:
Performance is critical
You manage many devices of the same type with consistent prompts
You can invest time in prompt pattern development/testing
Use timeout only when:
Other strategies consistently fail
Devices lack interactive prompts
Commands have known, fixed execution time
Consider idle detection for:
Commands with intermittent output patterns
Devices where prompt detection is unreliable
Network latency introduces variable delays
Troubleshooting
Common Issues
Command output truncated
Cause: Timeout too short for command execution
Solution: Increase
max_timeoutorwait_timedepending on strategy
Command never completes / hangs
Cause: Prompt detection pattern doesn’t match device prompt
Solution:
Verify actual device prompt format
Use more flexible regex patterns (e.g.,
.*#\s*$instead ofhostname#$)Switch to test probe strategy for reliability
Spurious markers in output (test probe)
Cause: Device doesn’t properly handle CTRL+U (line erase)
Solution: Switch to regex or idle detection strategy
Regex matches command output instead of prompt
Cause: Pattern too broad, matches unintended text
Solution:
Use more specific patterns (e.g., add
$anchor for end-of-line)Switch
match_modeto"current-line"Use test probe strategy instead