Query NASA data: find closest asteroids, retrieve space images (APOD). Use for aerospace research, space data queries, NASA API integration, asteroid tracking, astronomy images.
Query NASA's Near Earth Object (NEO) and Astronomy Picture of the Day (APOD) APIs through a structured CLI interface with custom Claude SDK tools.
Structured NASA Data Access:
Two Custom Tools:
sentinel_find_closest - NEO Web Service integration (today's closest asteroid)sentinel_get_visual - APOD integration (images by date)Invoke this skill when users ask about:
User Query
↓
Claude Agent (this skill)
↓
Custom Tools (sentinel_find_closest, sentinel_get_visual)
↓
Sentinel CLI (business logic)
↓
NASA APIs (NeoWs, APOD)
Constitutional Compliance:
NASA API Key (required):
export NASA_API_KEY="your_api_key_here"
Get free key at: https://api.nasa.gov
Anthropic API Key (for agent usage):
export ANTHROPIC_API_KEY="your_key_here"
Sentinel CLI Installation:
pip install -e .
Test the CLI is installed:
sentinel --help
sentinel find-closest --help
sentinel get-visual --help
The skill provides two structured tools defined in sentinel_skill.py:
Find today's closest asteroid approaching Earth.
Input Schema:
{
"verbose": false // Optional: enable diagnostic output
}
Output:
{
"status": "success",
"data": {
"asteroid": {
"name": "2024 AA1",
"distance_miles": 2340000.5,
"velocity_mph": 25000.3,
"approach_date": "2024-02-16T14:23:00Z",
"is_potentially_hazardous": false
}
},
"message": "Found closest asteroid: 2024 AA1"
}
Get NASA's Astronomy Picture of the Day.
Input Schema:
{
"date": "2024-01-15", // Optional: YYYY-MM-DD format, defaults to today
"verbose": false // Optional: enable diagnostic output
}
Date Constraints:
Output:
{
"status": "success",
"data": {
"visual": {
"date": "2024-01-15",
"url": "https://apod.nasa.gov/apod/image/2401/orion_jwst.jpg",
"title": "Orion Nebula in Infrared",
"description": "This stunning image...",
"media_type": "image",
"copyright": "NASA/ESA/CSA",
"hdurl": "https://apod.nasa.gov/apod/image/2401/orion_jwst_hd.jpg"
}
},
"message": "Retrieved image for 2024-01-15"
}
When to use: User asks about asteroids, near-Earth objects, or space threats.
Steps:
sentinel_find_closest tool with optional verbose flagExample Agent Interaction:
User: "What's the closest asteroid today?"
Agent Actions:
1. Invokes sentinel_find_closest tool
2. Receives: {"status": "success", "data": {"asteroid": {...}}}
3. Responds: "The closest asteroid today is 2024 AA1, approaching
at 2,340,000 miles with a velocity of 25,000 mph at 2:23 PM UTC.
It is not classified as potentially hazardous."
When to use: User asks for space images, APOD, or images from specific dates.
Steps:
sentinel_get_visual tool with date parameterExample Agent Interaction:
User: "Show me NASA's image from January 15th, 2024"
Agent Actions:
1. Invokes sentinel_get_visual with {"date": "2024-01-15"}
2. Receives: {"status": "success", "data": {"visual": {...}}}
3. Responds: "Here's NASA's Astronomy Picture of the Day for
January 15, 2024: 'Orion Nebula in Infrared' by NASA/ESA/CSA.
[View Image](https://apod.nasa.gov/apod/image/2401/orion_jwst.jpg)
This stunning image captured by the James Webb Space Telescope..."
When to use: User asks for multiple types of data.
Steps:
Example:
User: "What's happening in space today?"
Agent Actions:
1. Call sentinel_find_closest for asteroid data
2. Call sentinel_get_visual for today's image
3. Combine: "Today's closest asteroid is... and NASA's Astronomy
Picture of the Day shows..."
All tools return CLIOutput structure with status field:
{
"status": "success",
"data": { /* tool-specific data */ },
"message": "Descriptive success message"
}
{
"status": "error",
"data": null,
"message": "Detailed error with remediation guidance"
}
Missing API Key:
"NASA API key not found. Set NASA_API_KEY environment variable.
Get key at https://api.nasa.gov"
→ Guide user to obtain and set NASA_API_KEY
Rate Limit:
"NASA API rate limit exceeded. Retry after 3600 seconds or use
a registered API key."
→ Inform user to wait or upgrade API key
Invalid Date:
"Future date 2025-01-01 is not valid. APOD images are only
available up to today (2024-02-16)."
→ Clarify date constraints (1995-06-16 to today)
No Data:
"No asteroids found for today (2024-02-16)"
→ Explain no close approaches detected today
Network Timeout:
"Network request timed out after 30 seconds. Check your internet
connection and retry."
→ Suggest retrying, checking connectivity
The sentinel_skill.py script provides:
Class: SentinelSkillExecutor
Function: create_tool_handler()
Function: discover_cli_capabilities()
sentinel --help to verify CLI availabilityConstant: SENTINEL_TOOLS
from scripts.sentinel_skill import SENTINEL_TOOLS, create_tool_handler, discover_cli_capabilities
import anthropic
# Initialize
client = anthropic.Anthropic()
tool_handler = create_tool_handler()
# Discover CLI (Rule of Discovery)
cli_info = discover_cli_capabilities()
if not cli_info.get("available"):
# Handle CLI not installed
pass
# Use tools in conversation
response = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=4096,
tools=SENTINEL_TOOLS,
messages=[{"role": "user", "content": "What's the closest asteroid?"}]
)
# Handle tool execution
for block in response.content:
if block.type == "tool_use":
result = tool_handler(block.name, block.input)
# Continue conversation with result
Enable diagnostic output for debugging:
tool_handler("sentinel_find_closest", {"verbose": True})
tool_handler("sentinel_get_visual", {"date": "2024-01-15", "verbose": True})
Verbose output includes:
For historical analysis, loop through date ranges:
from datetime import date, timedelta
start = date(2024, 1, 1)
end = date(2024, 1, 7)
current = start
while current <= end:
result = tool_handler("sentinel_get_visual", {
"date": current.isoformat()
})
# Process result
current += timedelta(days=1)
For multiple asteroid checks throughout the day, cache results:
# Cache asteroid data to avoid repeated API calls
asteroid_cache = None
cache_time = None
def get_cached_asteroid():
global asteroid_cache, cache_time
from datetime import datetime, timedelta
now = datetime.utcnow()
if asteroid_cache is None or (now - cache_time) > timedelta(hours=1):
asteroid_cache = tool_handler("sentinel_find_closest", {})
cache_time = now
return asteroid_cache
Before using tools, verify CLI works directly:
# Test asteroid lookup
sentinel find-closest --json
# Test visual lookup
sentinel get-visual --date 2024-01-15 --json
# Test error handling
sentinel get-visual --date 2030-01-01 --json # Future date
sentinel find-closest --json # Without NASA_API_KEY set
Test the skill executor independently:
from scripts.sentinel_skill import create_tool_handler
handler = create_tool_handler()
# Test asteroid tool
result = handler("sentinel_find_closest", {})
assert result["status"] == "success"
assert "asteroid" in result["data"]
# Test visual tool
result = handler("sentinel_get_visual", {"date": "2024-01-15"})
assert result["status"] == "success"
assert "visual" in result["data"]
Symptom: "Sentinel CLI not found. Install with: pip install -e ."
Solutions:
pip list | grep sentinelwhich sentinelpip install -e .Symptom: "Invalid NASA API key"
Solutions:
echo $NASA_API_KEYSymptom: "Module not found" for sentinel_skill
Solutions:
ls .github/skills/sentinel/scripts/sentinel_skill.pySymptom: "Failed to parse JSON output"
Solutions:
Specification: specs/001-sentinel-nasa-cli/
CLI Source: sentinel/ Agent: agent.py - Example agent implementation Skill Executor: scripts/sentinel_skill.py