Sensor Tasking - Query and Command EDR Agents
This skill orchestrates sending tasks (commands) to EDR sensors and handling responses. It solves two key challenges of sensor tasking:
- Offline agents: Sensors may be offline when you want to task them
- Response collection: Some tasks generate data that needs to be collected
LimaCharlie Integration
Prerequisites: Run /init-lc to initialize LimaCharlie context.
LimaCharlie CLI Access
All LimaCharlie operations use the limacharlie CLI directly:
limacharlie <noun> <verb> --oid <oid> --output yaml [flags]
For command help and discovery: limacharlie <command> --ai-help
Critical Rules
| Rule |
Wrong |
Right |
| CLI Access |
Call MCP tools or spawn api-executor |
Use Bash("limacharlie ...") directly |
| Output Format |
--output json |
--output yaml (more token-efficient) |
| Filter Output |
Pipe to jq/yq |
Use --filter JMESPATH to select fields |
| LCQL Queries |
Write query syntax manually |
Use limacharlie ai generate-query first |
| Timestamps |
Calculate epoch values |
Use date +%s or date -d '7 days ago' +%s |
| OID |
Use org name |
Use UUID (call limacharlie org list if needed) |
When to Use
Use this skill when the user wants to:
- Live Response: Query running processes, network connections, registry keys, services
- Forensic Collection: Collect memory maps, file listings, autoruns, packages
- Fleet Operations: Execute commands across many sensors (by tag, platform, etc.)
- Incident Response: Isolate hosts, kill processes, gather evidence
- Data Collection at Scale: Get OS versions, installed software, users across fleet
Example requests:
- "Get running processes from sensor X"
- "List all files in C:\Windows\Temp on compromised hosts"
- "Get OS version from all Windows servers when they come online"
- "Run a memory collection on all hosts tagged 'incident-response'"
- "Execute netstat on all online Linux servers"
Core Concepts
Challenge 1: Offline Agents
Direct tasking (getprocesses, dirlist, etc.) only works for online sensors. If a sensor is offline, the task fails immediately.
Reliable tasking queues tasks for delivery when sensors come online. Tasks persist for a configurable TTL (default: 1 week).
| Approach |
Use When |
Pros |
Cons |
| Direct Task |
≤5 online sensors, need immediate response |
Fast, response inline |
Fails if offline |
| Reliable Task |
>5 sensors, offline sensors, or can wait |
Guaranteed delivery |
Response via telemetry |
Challenge 2: Receiving Responses
| Method |
Use When |
How It Works |
| Inline Response |
Direct tasking small numbers |
Response returned directly from API |
| LCQL Query |
Need to collect reliable task responses |
Query for routing/investigation_id containing your context |
| D&R Rule |
Need automated action on responses |
Create rule matching investigation_id, with response actions |
Decision Tree
START: User wants to task sensors
|
v
Are all targets online AND ≤5 sensors?
|
|--YES--> Use Direct Tasking (inline response, parallel execution)
|
|--NO--> Use Reliable Tasking (>5 sensors OR any offline)
|
v
Do you need the response data?
|
|--NO (action-only like isolate)--> Create Reliable Task, done
|
|--YES--> Do you need automated handling?
|
|--NO--> Create Reliable Task, wait 2+ min, then LCQL query
|
|--YES--> 1. Create D&R rule with TTL FIRST
2. THEN create Reliable Task
(rule must exist before task to avoid missing responses)
How to Use
Step 1: Understand the Request
Parse the user's request to determine:
- Target scope: Single sensor, selector, all sensors?
- Task type: Data collection (needs response) or action (unidirectional)?
- Urgency: Need immediate response or can wait?
- Response handling: Inline, LCQL collection, or automated D&R?
Step 2: Get Organization and Sensors
If you don't have the OID, get it first:
limacharlie org list --output yaml
Check sensor status if targeting specific sensors:
limacharlie sensor get --sid <sid> --oid <oid> --output yaml
CRITICAL: Filter to Taskable EDR Sensors
Before spawning executor agents or tasking sensors, you MUST verify sensors are EDR agents (not adapters or cloud sensors).
Non-EDR sensors will fail with UNSUPPORTEDFORPLATFORM.
Taskable sensors require BOTH:
- Platform: windows, linux, macos, or chrome
- Architecture: NOT usp_adapter (code 9)
A sensor running on Linux platform but with arch=usp_adapter is an adapter (USP), not an EDR agent. These adapters forward logs but cannot execute commands.
Use combined selector when listing sensors:
```bash
limacharlie sensor list --selector "(plat==windows or plat==linux or plat==macos) and arch!=usp_adapter" --online --oid <oid> --output yaml
```
Or check sensor info before tasking - verify both platform is in ["windows", "linux", "macos", "chrome"] AND arch is not 9 / usp_adapter.
Step 3A: Direct Tasking (≤5 Online Sensors)
For immediate data collection from a small number of online sensors (up to 5), use direct tasking functions with parallel execution.
Available Direct Task Commands (return response inline via limacharlie task send --sid <sid> --task <command>):
| Task Command |
Description |
Common Use |
os_processes |
Running processes |
Process investigation |
oskillprocess |
Kill a process |
Incident response |
os_modules --pid [pid] |
Loaded modules |
Malware analysis |
netstat |
Active connections |
C2 hunting |
os_version |
OS details |
Asset inventory |
os_users |
System users |
Account enumeration |
os_services |
Windows services |
Persistence check |
os_drivers |
Loaded drivers |
Rootkit detection |
os_autoruns |
Persistence mechanisms |
Malware persistence |
os_packages |
Installed packages |
Software inventory |
reg_list [path] |
Registry values |
Config/persistence |
dir_list [path] |
Directory listing |
File investigation |
find_strings |
String search |
Memory forensics |
yara_scan --pid [pid] |
YARA scan process |
Malware detection |
yara_scan --filePath [path] |
YARA scan file |
File analysis |
yara_scan --dirPath [path] |
YARA scan directory |
Bulk scanning |
Example - Get processes from a sensor:
limacharlie task send --sid <sid> --task os_processes --oid <oid> --output yaml
Step 3B: Reliable Tasking (>5 Sensors or Offline)
For more than 5 sensors, offline sensors, or fleet-wide operations, use reliable tasking.
IMPORTANT: Order of Operations
If you need automated response handling via D&R rules, you MUST create the D&R rule FIRST, before creating the reliable task. This ensures no responses are missed between task creation and rule deployment.
Order: D&R Rule → Reliable Task (not the other way around)
Create a reliable task:
# reliable-send is per-sensor; first list matching sensors, then loop
limacharlie sensor list --selector 'plat==windows' --oid <oid> --filter '[].sid' --output yaml
for sid in <sid-list>; do
limacharlie task reliable-send --sid $sid --command 'os_version' --investigation-id 'fleet-inventory-2024-01' --ttl 86400 --oid <oid> --output yaml
done
Key Parameters:
--sid: Target sensor ID (reliable-send operates per-sensor)
--command: The command to execute (e.g., osversion, memmap --pid 4, run --shell-command whoami)
--investigation-id: Identifier that appears in routing/investigation_id of responses (for collection)
--ttl: Time-to-live in seconds (default: 604800 = 1 week)
Available Task Commands:
Any sensor command can be used as a task. Common ones:
| Task Command |
Description |
os_version |
Get OS details |
mem_map --pid [pid] |
Memory map of process |
mem_strings --pid [pid] |
Strings from process memory |
file_get [path] |
Get file contents |
dir_list [path] |
List directory |
netstat |
Network connections |
run --shell-command [cmd] |
Execute shell command |
deny_tree -p [process] |
Kill process tree |
isolate_network |
Network isolation |
rejoin_network |
End network isolation |
Step 4: Collecting Responses
Option A: LCQL Query (Manual Collection)
After reliable tasking, wait at least 2 minutes for responses to arrive, then query:
First, generate the LCQL query:
limacharlie ai generate-query --prompt "Find all events in the last 2 hours where investigation_id contains 'fleet-inventory-2024-01'" --oid <oid> --output yaml
Then run the query:
limacharlie search run --query "<generated_query>" --start <ts> --end <ts> --oid <oid> --output yaml
Option B: D&R Rule (Automated Handling)
For automated response handling, create a D&R rule that matches the investigation_id.
CRITICAL: Create the D&R rule BEFORE creating the reliable task. Online sensors may respond within milliseconds - if the rule doesn't exist yet, those responses will be missed.
Step 1: Generate the detection:
limacharlie ai generate-detection --description "Match events where investigation_id contains 'fleet-inventory-2024-01'" --oid <oid> --output yaml
Step 2: Generate the response:
limacharlie ai generate-response --description "Report to output 'siem' and add detection 'FLEET_INVENTORY_RESPONSE'" --oid <oid> --output yaml
Step 3: Write to temp files and validate:
cat > /tmp/detect.yaml << 'EOF'
<detection_yaml>
EOF
cat > /tmp/respond.yaml << 'EOF'
<response_yaml>
EOF
limacharlie dr validate --detect /tmp/detect.yaml --respond /tmp/respond.yaml --oid <oid>
Step 4: Deploy with expiry:
Calculate expiry timestamp (e.g., 7 days from now):
date -d '+7 days' +%s
cat > /tmp/rule.yaml << 'EOF'
detect:
<detection_yaml>
respond:
<response_yaml>
EOF
limacharlie dr set --key temp-fleet-inventory-handler --input-file /tmp/rule.yaml --oid <oid>
Step 5: NOW create the reliable task
Only after the D&R rule is deployed, create the reliable task (see Step 3B above). The rule will catch all responses as sensors execute the task.
Monitoring Reliable Tasks
List pending tasks for a sensor:
limacharlie task reliable-list --sid <sensor-id> --oid <oid> --output yaml
Delete/cancel a task:
limacharlie task reliable-delete --sid <sensor-id> --task-id <task_id> --oid <oid>
Example Workflows
Example 1: Get Processes from Single Sensor
User: "Get running processes from sensor abc-123"
# Check sensor status
limacharlie sensor get --sid abc-123 --oid c7e8f940-... --output yaml
# If online, get processes directly
limacharlie task send --sid abc-123 --task os_processes --oid c7e8f940-... --output yaml
Example 2: Fleet-Wide OS Inventory
User: "Get OS version from all Windows servers when they come online"
# List Windows sensors first
limacharlie sensor list --selector 'plat == windows' --oid c7e8f940-... --filter '[].sid' --output yaml
# Create reliable task per sensor (loop over SIDs)
for sid in <sid-list>; do
limacharlie task reliable-send --sid $sid --command 'os_version' --investigation-id 'os-inventory-20240120' --oid c7e8f940-... --output yaml
done
Response to user: "Created reliable tasks to collect OS version from all Windows sensors.
- Online sensors will execute immediately
- Offline sensors will execute when they reconnect
- Task will remain active for 1 week (default TTL)
- Use investigation ID 'os-inventory-20240120' to query responses via LCQL"
Example 3: Incident Response Collection
User: "Run memory collection on all hosts tagged 'incident-response', I need the data sent to our SIEM"
# Step 1: Create D&R rule FIRST to forward responses to SIEM
# Use AI generation for the detection and response, then deploy:
limacharlie ai generate-detection --description "Match events where investigation_id contains 'ir-memcollect-001'" --oid c7e8f940-... --output yaml
limacharlie ai generate-response --description "Report to output 'siem' and add detection 'IR_MEMCOLLECT_RESPONSE'" --oid c7e8f940-... --output yaml
# Write generated YAML to files, validate, then deploy:
limacharlie dr validate --detect /tmp/detect.yaml --respond /tmp/respond.yaml --oid c7e8f940-... --output yaml
# Combine into single rule file with detect/respond keys, then set:
limacharlie dr set --key temp-ir-memcollect-handler --input-file /tmp/ir-rule.yaml --oid c7e8f940-...
# Step 2: Get sensors tagged 'incident-response'
limacharlie sensor list --tag incident-response --oid c7e8f940-... --filter '[].sid' --output yaml
# Step 3: THEN create reliable task per sensor (rule is now in place to catch responses)
for sid in <sid-list>; do
limacharlie task reliable-send \
--sid $sid \
--command 'mem_map --pid 4' \
--investigation-id 'ir-memcollect-001' \
--ttl 172800 \
--oid c7e8f940-... --output yaml
done
Example 4: Quick Data Collection with Inline Response
User: "What's the OS version on all 5 of our production Linux servers?"
If sensors are online and small in number, parallel direct tasking is faster:
# Run parallel tasks for each sensor
limacharlie task send --sid sid1 --task os_version --oid <oid> --output yaml &
limacharlie task send --sid sid2 --task os_version --oid <oid> --output yaml &
limacharlie task send --sid sid3 --task os_version --oid <oid> --output yaml &
limacharlie task send --sid sid4 --task os_version --oid <oid> --output yaml &
limacharlie task send --sid sid5 --task os_version --oid <oid> --output yaml &
wait
Important Notes
Taskable Sensors (EDR Only)
WARNING: Sensor tasking only works for EDR agents (real endpoint agents). Cloud sensors, adapters, and USP log sources cannot receive tasks.
Taskable sensors require BOTH conditions:
- Platform is Windows, Linux, macOS, or Chrome
- Architecture is NOT
usp_adapter (code 9)
Platforms that support tasking:
| Platform |
Platform ID (hex) |
Platform ID (decimal) |
Selector |
| Windows |
0x10000000 |
268435456 |
plat==windows |
| Linux |
0x20000000 |
536870912 |
plat==linux |
| macOS |
0x30000000 |
805306368 |
plat==macos |
| Chrome |
Architecture 0x00000006 |
6 |
arch==chromium |
Non-taskable sensors include:
- Cloud sensors (Office365, Okta, AWS, GCP, Azure, etc.)
- External adapters (
ext-* sensors like ext-zeek, ext-strelka)
- USP log sources (Syslog, S3 buckets, webhooks)
- Any sensor with
arch=usp_adapter (architecture code 9) - even if platform is Linux/macOS
These sensors will return UNSUPPORTEDFORPLATFORM errors when tasked.
Recommendation: When tasking a fleet, filter by both platform AND architecture:
- Use combined selector:
(plat==windows or plat==linux or plat==macos) and arch!=usp_adapter
- Or check sensor info for both
platform and arch fields before direct tasking
Extension Requirement
Reliable tasking requires the ext-reliable-tasking extension to be subscribed in the organization. If you get a 403 error, the extension may not be enabled.
Selector Syntax
Selectors use bexpr syntax:
plat==windows - Windows sensors
plat==linux - Linux sensors
production in tags - Sensors with 'production' tag
hostname matches '^web-' - Hostname starts with 'web-'
sid=='abc-123-def-456' - Specific sensor
* - All sensors
Context for Response Collection
The context parameter in reliable tasking:
- Appears in
routing/investigation_id of response events
- Use unique identifiers (include date/time)
- Can be used in LCQL queries or D&R rules for matching
Timestamps
When setting TTL or expiry:
- Use bash for timestamp calculation:
date -d '+7 days' +%s
- TTL is in seconds from now
- D&R rule expiry is absolute Unix timestamp
Related Skills
detection-engineering - For creating D&R rules to handle responses
sensor-health - For checking sensor online status across fleet
sensor-coverage - For understanding fleet coverage before tasking
Reference