rlm-context-scout
Reconnaissance techniques for exploring large contexts before reading them. Teaches agents to probe, filter, and map data structures without consuming context window.
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
RLM Context Scout — Filtering Without Seeing
You are the eyes of the RLM. The Manager sends you in first.
The Scout's Creed
Never read what you can probe. Never consume what you can sample. Never search blind when you have priors.
The context window is a scarce resource. Every character you load that isn't relevant is a character that crowds out what is. Your mission: maximum signal, minimum noise.
Core Techniques
Technique 1: Structural Probing
Goal: Understand the skeleton of the data without reading the meat.
# Discover document structure
print(f"Total characters: {len(context)}")
print(f"Total lines: {len(context.splitlines())}")
print(f"Section boundaries: {context.count('---')}")
print(f"Paragraph breaks: {context.count('\\n\\n')}")
# Find headers (markdown)
import re
headers = re.findall(r'^#+\s+(.+)$', context, re.MULTILINE)
print(f"Headers found: {headers[:20]}...") # First 20
# Find headers (HTML)
html_headers = re.findall(r'<h[1-6][^>]*>(.+?)</h[1-6]>', context, flags=re.IGNORECASE)
# Find JSON structure
if context.strip().startswith('{') or context.strip().startswith('['):
import json
sample = json.loads(context)
if isinstance(sample, list):
print(f"JSON array with {len(sample)} items")
print(f"First item keys: {sample[0].keys() if sample else 'empty'}")
elif isinstance(sample, dict):
print(f"JSON object with keys: {list(sample.keys())}")
Technique 2: Strategic Sampling
Goal: Get a representative taste of the data without reading it all.
# Sample beginning, middle, and end
sample_size = 500
total = len(context)
print("=== START ===")
print(context[:sample_size])
print("=== MIDDLE ===")
print(context[total//2 : total//2 + sample_size])
print("=== END ===")
print(context[-sample_size:])
# Sample random chunks (for heterogeneous data)
import random
chunks = context.split('\n\n')
random_samples = random.sample(chunks, min(5, len(chunks)))
for i, sample in enumerate(random_samples):
print(f"=== RANDOM SAMPLE {i+1} ===")
print(sample[:300]) # First 300 chars of each
Technique 3: Prior-Based Keyword Search
Goal: Use what you already know to find what you need.
This is the RLM's superpower: filtering without seeing. You can use domain knowledge and query keywords to locate relevant chunks before reading them.
# Extract keywords from the query
query_keywords = ["festival", "La Union", "beauty pageant", "winner"]
# Search for keyword presence (without reading context)
for keyword in query_keywords:
matches = [(m.start(), m.end()) for m in re.finditer(re.escape(keyword), context, re.IGNORECASE)]
if matches:
print(f"'{keyword}' found {len(matches)} times at positions: {matches[:5]}")
# Now we know WHERE to look
# Get context around matches
def extract_context_around(text, keyword, window=500):
"""Extract text around keyword matches"""
results = []
for match in re.finditer(re.escape(keyword), text, re.IGNORECASE):
start = max(0, match.start() - window)
end = min(len(text), match.end() + window)
results.append(text[start:end])
return results
relevant_chunks = extract_context_around(context, "La Union", window=1000)
print(f"Found {len(relevant_chunks)} relevant chunks around 'La Union'")
Technique 4: Regex-Based Reconnaissance
Goal: Find patterns in data structure that guide your chunking strategy.
# Find dates (temporal organization)
dates = re.findall(r'\b(19|20)\d{2}\b', context)
print(f"Years mentioned: {set(dates)}")
# Find email addresses (if analyzing correspondence)
emails = re.findall(r'\b[\w.-]+@[\w.-]+\.\w+\b', context)
print(f"Unique emails: {set(emails)}")
# Find code blocks (if analyzing docs with code)
code_blocks = re.findall(r'```(\w+)?\n(.*?)```', context, re.DOTALL)
print(f"Found {len(code_blocks)} code blocks, languages: {[b[0] for b in code_blocks]}")
# Find numbered lists or enumerations
numbered = re.findall(r'^\s*\d+[.)]\s+.+$', context, re.MULTILINE)
print(f"Found {len(numbered)} numbered list items")
# Find definition patterns (term: definition)
definitions = re.findall(r'^([^:\n]+):\s*(.+)$', context, re.MULTILINE)
print(f"Found {len(definitions)} potential definitions")
Technique 5: Metadata Extraction
Goal: Extract high-value summary information that's often at boundaries.
# YAML frontmatter (common in markdown)
frontmatter_match = re.match(r'^---\n(.*?)\n---', context, re.DOTALL)
if frontmatter_match:
print("=== FRONTMATTER ===")
print(frontmatter_match.group(1))
# JSON metadata fields
if 'metadata' in context.lower():
meta_match = re.search(r'"metadata"\s*:\s*({[^}]+})', context)
if meta_match:
print("=== METADATA ===")
print(meta_match.group(1))
# Table of contents (if present)
toc_patterns = [
r'## Table of Contents\n(.*?)##', # Markdown TOC
r'<nav[^>]*>(.*?)</nav>', # HTML nav
r'Contents:?\n((?:\s*[-*]\s*.+\n)+)', # Simple list TOC
]
for pattern in toc_patterns:
toc = re.search(pattern, context, re.DOTALL | re.IGNORECASE)
if toc:
print("=== TABLE OF CONTENTS ===")
print(toc.group(1)[:1000]) # First 1000 chars
break
Reconnaissance Strategies by Document Type
Strategy: Structured Documents (Books, Papers, Docs)
# 1. Extract table of contents or headers
headers = re.findall(r'^#{1,3}\s+(.+)$', context, re.MULTILINE)
# 2. Build section map
sections = re.split(r'\n(?=#{1,3}\s)', context)
section_map = {i: sections[i][:100] for i in range(len(sections))}
# 3. Identify relevant sections based on query keywords
relevant_indices = [i for i, s in section_map.items()
if any(kw.lower() in s.lower() for kw in query_keywords)]
# 4. Only read relevant sections
for i in relevant_indices:
finding = llm_query(f"Analyze section:\n{sections[i]}\n\nFind: {query}")
Strategy: Data Collections (JSON, CSV, Logs)
# 1. Understand schema
lines = context.splitlines()
header = lines[0] if lines else ""
print(f"Columns/Schema: {header}")
# 2. Count and sample
print(f"Total entries: {len(lines) - 1}")
print(f"Sample entries: {lines[1:6]}")
# 3. Filter with regex before reading
relevant_lines = [l for l in lines if "error" in l.lower()]
print(f"Filtered to {len(relevant_lines)} error entries")
Strategy: Correspondence (Emails, Chats, Messages)
# 1. Find message boundaries
messages = re.split(r'\n(?=From:|Subject:|Date:)', context)
print(f"Found {len(messages)} messages")
# 2. Extract metadata per message
for msg in messages[:5]: # Sample
from_match = re.search(r'From:\s*(.+)', msg)
subject_match = re.search(r'Subject:\s*(.+)', msg)
print(f"From: {from_match.group(1) if from_match else 'N/A'}")
print(f"Subject: {subject_match.group(1) if subject_match else 'N/A'}")
Strategy: Codebases
# 1. Build file tree (if provided as context)
files = re.findall(r'(?:^|\n)(?:File|Path):\s*(.+)', context)
print(f"Files in context: {files}")
# 2. Find function/class definitions
python_defs = re.findall(r'^(?:def|class)\s+(\w+)', context, re.MULTILINE)
print(f"Definitions: {python_defs}")
# 3. Find import statements (dependencies)
imports = re.findall(r'^(?:import|from)\s+(\w+)', context, re.MULTILINE)
print(f"Imports: {set(imports)}")
The Scout's Decision Tree
START: Received massive context
│
├─► Q: Can I probe the structure?
│ YES → Use Structural Probing
│ NO → Use Strategic Sampling
│
├─► Q: Do I have keywords from the query?
│ YES → Use Prior-Based Keyword Search
│ NO → Use Regex-Based Reconnaissance
│
├─► Q: Is there obvious metadata?
│ YES → Use Metadata Extraction
│ NO → Sample and infer structure
│
└─► OUTPUT: Map of where relevant info lives
→ Pass to Orchestrator for chunking strategy
Output Format
After reconnaissance, report to the Orchestrator:
## Scout Report
**Total Size:** X characters / Y lines
**Structure Type:** [Structured | Semi-structured | Unstructured]
**Section Count:** N sections/chunks identified
### Content Map
- Section 0: [brief description] — Relevance: [High/Medium/Low]
- Section 1: [brief description] — Relevance: [High/Medium/Low]
...
### Recommended Chunking Strategy
[Semantic | Fixed | Targeted | Hierarchical]
### Keyword Hits
- "keyword1": Found in sections [0, 3, 7]
- "keyword2": Found in sections [2, 5]
### Ready Chunks (if targeted)
[Pre-filtered chunks ready for sub-LM processing]
Integration
Parent Skill: rlm-orchestrator/SKILL.md — The Orchestrator delegates reconnaissance to you.
Sibling Skill: rlm-repl-environment/SKILL.md — The technical environment where your code runs.
When to be called:
- Orchestrator detects large context
- Orchestrator needs to understand data shape
- Before any chunking or sub-query spawning
What to return:
- Structure summary
- Relevance map
- Recommended chunking approach
- Pre-filtered relevant chunks (if possible)
The Scout's Mantra
I do not read; I probe.
I do not consume; I sample.
I do not search blind; I use my priors.
The context window is sacred.
Only signal passes through.
The noise stays on disk.
See the shape. Find the signal. Guide the Manager.
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!