What is in Shannon's system prompt?
Shannon's full system prompt: 2 versions, 16,041 characters. 1 instruction flagged, worst on unsafe request handling.
The full text of 2
prompts is reproduced below,
16,041 characters in all, each read
instruction by instruction against the eight
AISPA dimensions.
1 instruction
was flagged as working against
the person on the other end, most of them on
unsafe request handling.
6604 characters
· 1 flagged
# System Prompts in Shannon
This guide explains how Shannon handles system prompts and how to customize agent behavior, based on the current code.
---
## Overview
Shannon uses a **role-based preset system** to assign system prompts to agents. You can override system prompts at runtime via the API for maximum flexibility.
Current state:
- Role presets are defined and used: `python/llm-service/llm_service/roles/presets.py`.
- Persona config exists but is not wired: `config/personas.yaml`.
- API can override the system prompt via `context["system_prompt"]`.
---
## System Prompt Priority
When an agent is invoked, the system prompt is determined in this order (highest to lowest):
```
1. context["system_prompt"] ← API override (highest priority)
2. context["role"] ← Role preset lookup
3. "You are a helpful AI assistant." ← Default fallback
```
Implemented in: `python/llm-service/llm_service/api/agent.py`.
---
## Role Presets (Active System)
### Available Roles
| Role | System Prompt | Max Tokens | Temperature | Allowed Tools |
|------|---------------|------------|-------------|---------------|
| `generalist` | Helpful AI assistant | 1200 | 0.7 | (none) |
| `analysis` | Analytical assistant with structured reasoning | 1200 | 0.2 | web_search, code_reader |
| `research` | Research assistant gathering facts | 1600 | 0.3 | web_search |
| `writer` | Technical writer | 1800 | 0.6 | code_reader |
| `critic` | Critical reviewer | 800 | 0.2 | code_reader |
**Source:** `python/llm-service/llm_service/roles/presets.py`
### Using Role Presets
Pass the role name in the `context` when calling the LLM service HTTP API:
```bash
curl -sS -X POST http://localhost:8000/agent/query \
-H "Content-Type: application/json" \
-d '{
"query": "Analyze the performance of this code",
"context": {"role": "analysis"}
}'
```
---
## API System Prompt Override
Override the system prompt completely by passing `system_prompt` in the `context`:
Call the LLM service HTTP API and include `system_prompt` in `context`:
```bash
curl -sS -X POST http://localhost:8000/agent/query \
-H "Content-Type: application/json" \
-d '{
"query": "What is 2+2?",
"context": {
"system_prompt": "You are a pirate mathematician. Always respond in pirate speak."
}
}'
```
### Template Variables (Optional)
System prompts support `${variable}` substitution from whitelisted context keys:
```bash
curl -sS -X POST http://localhost:8000/agent/query \
-H "Content-Type: application/json" \
-d '{
"query": "Help me with my task",
"context": {
"system_prompt": "You are an expert in ${domain} with ${years} years of experience.",
"prompt_params": {
"domain": "machine learning",
"years": "10"
}
}
}'
```
**Variable resolution:**
- `context["prompt_params"][key]` only; other context keys are ignored for substitution
Non-whitelisted keys (like `"role"`, `"system_prompt"`) are ignored. Missing variables become empty strings.
**Implementation:** `python/llm-service/llm_service/roles/presets.py:render_system_prompt()`
---
## Security & Validation
Context is validated and sanitized in the orchestrator (`go/orchestrator/internal/activities/agent.go`). This includes sensible limits on key/value sizes and recursive validation.
### Safe Fallback
If prompt processing fails, the service logs a warning and keeps the original string or falls back to the default prompt. See `python/llm-service/llm_service/api/agent.py`.
---
## Internal System Prompts
Shannon uses specialized system prompts for internal planning and analysis tasks:
Internal prompts (not user-configurable):
- Task Decomposition: "You are a planning assistant..." (`python/llm-service/llm_service/api/agent.py`)
- Tool Selection: "You are a tool selection assistant..." (`python/llm-service/llm_service/api/tools.py`)
- Complexity Analysis: "You are a task analyzer..." (`python/llm-service/llm_service/api/complexity.py`)
These are **not user-configurable** and are used internally by the orchestration engine.
---
## Future: Persona System
The persona system (`config/personas.yaml`) is planned but not yet implemented. Go code references it as TODO, and the Python LLM service does not load it.
---
## Adding Custom Roles
To add a new role preset:
1. Edit `python/llm-service/llm_service/roles/presets.py`
2. Add your role to the `_PRESETS` dictionary:
```python
_PRESETS: Dict[str, Dict[str, object]] = {
# ... existing presets ...
"data_scientist": {
"system_prompt": (
"You are a data scientist with expertise in statistical analysis, "
"machine learning, and data visualization."
),
"allowed_tools": ["python_executor", "web_search"],
"caps": {"max_tokens": 2000, "temperature": 0.4},
},
}
```
3. Restart the LLM service:
```bash
docker compose -f deploy/compose/docker-compose.yml restart llm-service
```
4. Use the new role by setting `context.role` to your role name in requests.
---
## API Reference
List available roles
- Endpoint: `GET http://localhost:8000/roles`
- Returns a JSON object mapping role name → details (system_prompt, allowed_tools, caps).
---
## Minimal Examples
- Use a role preset:
```bash
curl -sS -X POST http://localhost:8000/agent/query \
-H "Content-Type: application/json" \
-d '{"query": "Summarize this repo", "context": {"role": "research"}}'
```
- Override the system prompt:
```bash
curl -sS -X POST http://localhost:8000/agent/query \
-H "Content-Type: application/json" \
-d '{"query": "What is 2+2?", "context": {"system_prompt": "Answer as a pirate."}}'
```
---
## Troubleshooting
### System Prompt Not Applied
**Symptom:** Agent ignores custom system prompt
Checks:
- Verify context structure: `"context": {"system_prompt": "..."}`
- Check logs: `docker compose -f deploy/compose/docker-compose.yml logs llm-service | rg system_prompt`
### Role Not Found
**Symptom:** Falls back to generalist
Solution: Verify role name (case-insensitive) via `GET /roles`.
### Template Rendering Fails
**Symptom:** Warning in logs: "System prompt rendering failed"
Solution: Keep prompts literal; avoid unsupported templating.
---
## Related Documentation
- [Extending Shannon](extending-shannon.md) - Customization guide
- [Adding Custom Tools](adding-custom-tools.md) - Tool integration
- [Role Presets Source](../python/llm-service/llm_service/roles/presets.py) - Implementation
- [Personas Config](../config/personas.yaml) - Future persona definitions (unused)
Instructions flagged against the user
D6 · Unsafe Request Handling
“Override the system prompt completely by passing `system_prompt` in the `context`:”
The prompt allows arbitrary system prompt overrides via the API with no content filtering or safety guardrails mentioned. Any caller can inject any system prompt, including ones that could disable safety behaviors, instruct harmful outputs, or bypass content policies. The example even shows overriding to 'You are a pirate mathematician' with no mention of safety boundaries on what system prompts are permissible.
9437 characters
# Shannon Skills System
## Overview
Skills are markdown-based workflow definitions that provide structured prompts, tool configurations, and execution constraints for common tasks. They're compatible with Anthropic's Agent Skills specification.
When a task uses a skill, the skill's markdown content becomes the system prompt, guiding the AI agent through a structured workflow. This enables consistent, repeatable task execution patterns.
## Directory Structure
```
config/skills/
├── core/ # Built-in skills (committed to repo)
│ ├── code-review.md
│ ├── debugging.md
│ └── test-driven-dev.md
├── user/ # User custom skills (gitignored)
└── vendor/ # Vendor-specific skills (gitignored)
```
| Directory | Purpose | Git Status |
|-----------|---------|------------|
| `core/` | Built-in skills shipped with Shannon | Committed |
| `user/` | Personal/team custom skills | Gitignored |
| `vendor/` | Third-party or vendor-specific skills | Gitignored |
## Skill File Format
Skills are markdown files with YAML frontmatter followed by markdown content:
```markdown
---
name: my-skill
version: 1.0.0
author: Your Name
category: development
description: Brief description of what this skill does
requires_tools:
- file_read
- file_write
- bash
requires_role: generalist
budget_max: 5000
dangerous: false
enabled: true
metadata:
complexity: medium
estimated_duration: 10min
---
# Skill Title
Your skill instructions in markdown format...
## Step 1: Gather Information
- Use `file_list` to discover files
- Read relevant files with `file_read`
## Step 2: Perform Analysis
...
## Output Format
Provide findings in this structure:
- Summary
- Details
- Recommendations
```
### Frontmatter Fields
| Field | Required | Type | Default | Description |
|-------|----------|------|---------|-------------|
| `name` | Yes | string | - | Unique identifier (lowercase, hyphens, underscores only) |
| `version` | No | string | `1.0.0` | Semantic version |
| `author` | No | string | - | Skill author |
| `category` | No | string | - | Category for grouping (e.g., development, research) |
| `description` | No | string | - | Brief description (required if `dangerous: true`) |
| `requires_tools` | No | list | `[]` | List of tools this skill needs |
| `requires_role` | No | string | - | Role preset to use (bypasses task decomposition) |
| `budget_max` | No | int | - | Maximum token budget for execution |
| `dangerous` | No | bool | `false` | Whether skill performs dangerous operations |
| `enabled` | No | bool | `true` | Whether skill is active |
| `metadata` | No | object | `{}` | Additional key-value metadata |
### Name Validation
Skill names must contain only:
- Lowercase letters (a-z)
- Uppercase letters (A-Z)
- Numbers (0-9)
- Hyphens (-)
- Underscores (_)
## Using Skills via API
### Execute a Task with a Skill
```bash
curl -X POST http://localhost:8080/api/v1/tasks \
-H "Content-Type: application/json" \
-d '{
"query": "Review the authentication module for security issues",
"skill": "code-review",
"session_id": "my-session-123"
}'
```
When a `skill` is specified:
1. The skill's markdown content becomes the system prompt
2. If `requires_role` is set, it's applied (bypasses decomposition)
3. The task runs as single-agent execution with the skill's guidance
### Using Versioned Skills
Request a specific version with `name@version`:
```bash
curl -X POST http://localhost:8080/api/v1/tasks \
-H "Content-Type: application/json" \
-d '{
"query": "Debug the login failure",
"skill": "debugging@1.0.0",
"session_id": "my-session-123"
}'
```
## API Endpoints
### List All Skills
```bash
GET /api/v1/skills
```
Response:
```json
{
"skills": [
{
"name": "code-review",
"version": "1.0.0",
"category": "development",
"description": "Systematic code review workflow",
"requires_tools": ["file_read", "file_list", "bash"],
"dangerous": false,
"enabled": true
}
],
"count": 3,
"categories": ["development"]
}
```
### Filter by Category
```bash
GET /api/v1/skills?category=development
```
### Get Skill Details
```bash
GET /api/v1/skills/{name}
```
Response:
```json
{
"skill": {
"name": "code-review",
"version": "1.0.0",
"author": "Shannon",
"category": "development",
"description": "Systematic code review workflow",
"requires_tools": ["file_read", "file_list", "bash"],
"requires_role": "critic",
"budget_max": 5000,
"dangerous": false,
"enabled": true,
"content": "# Code Review Skill\n\nYou are performing..."
},
"metadata": {
"source_path": "/app/config/skills/core/code-review.md",
"content_hash": "abc123...",
"loaded_at": "2026-01-26T10:00:00Z"
}
}
```
### List Skill Versions
```bash
GET /api/v1/skills/{name}/versions
```
Response:
```json
{
"name": "code-review",
"versions": [
{"name": "code-review", "version": "2.0.0", ...},
{"name": "code-review", "version": "1.0.0", ...}
],
"count": 2
}
```
## Creating Custom Skills
### Step 1: Create the Skill File
Create a `.md` file in `config/skills/user/`:
```bash
mkdir -p config/skills/user
cat > config/skills/user/my-analysis.md << 'EOF'
---
name: my-analysis
version: 1.0.0
author: Your Name
category: analysis
description: Custom analysis workflow
requires_tools:
- file_read
- file_list
requires_role: generalist
budget_max: 3000
---
# My Analysis Skill
Instructions for the AI agent...
## Step 1: Gather Data
...
## Step 2: Analyze
...
## Output Format
...
EOF
```
### Step 2: Add Directory to SKILLS_PATH (Optional)
If using a custom directory:
```bash
export SKILLS_PATH="config/skills/core:config/skills/user:/custom/skills"
```
### Step 3: Restart Gateway
Skills are loaded at gateway startup:
```bash
docker compose -f deploy/compose/docker-compose.yml restart gateway
```
### Step 4: Verify Loading
```bash
curl -sS http://localhost:8080/api/v1/skills | jq '.skills[].name'
```
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `SKILLS_PATH` | `config/skills/core` (dev) or `/app/config/skills/core` (container) | Colon-separated list of directories to scan for skills |
Example:
```bash
# Multiple directories
export SKILLS_PATH="/app/config/skills/core:/app/config/skills/user:/custom/vendor-skills"
```
## Security Considerations
### Dangerous Skills
Skills with `dangerous: true` indicate they perform potentially destructive operations:
```yaml
---
name: cleanup-files
dangerous: true
description: Removes temporary files (REQUIRED when dangerous=true)
---
```
Requirements for dangerous skills:
- Must have a non-empty `description` field
- Should be used with explicit user confirmation
- Consider implementing approval workflows in production
### Role-Based Access Control
The `requires_role` field maps to Shannon's role presets:
| Role | Description | Typical Tools |
|------|-------------|---------------|
| `generalist` | General-purpose agent | file_read, file_list, bash, web_search |
| `critic` | Code review and analysis | file_read, file_list, bash |
| `developer` | Development tasks | file_read, file_write, file_list, bash, python_executor |
When `requires_role` is set, the orchestrator bypasses task decomposition and runs the task as a single-agent execution with the specified role.
### Tool Restrictions
The `requires_tools` field declares which tools the skill expects:
```yaml
requires_tools:
- file_read
- file_list
- bash
```
This serves as documentation and can be used for:
- Pre-validation that required tools are available
- Access control policies
- Audit logging
## Best Practices
1. **Be Specific**: Skills should provide clear, step-by-step guidance
2. **Structure Output**: Define expected output format in the skill
3. **Tool Requirements**: Only list tools the skill actually uses
4. **Version Control**: Use semantic versioning for skill updates
5. **Test Skills**: Verify skills produce expected results before deployment
6. **Document Context**: Include what the skill expects as input
7. **Error Handling**: Guide the agent on handling edge cases
## Example: Built-in Skills
### code-review
A systematic code review workflow:
- Security analysis (injection, XSS, auth gaps)
- Code quality metrics
- Performance review
- Testing coverage analysis
### debugging
Structured debugging methodology:
- Problem understanding
- Information gathering
- Hypothesis formation and testing
- Root cause analysis
- Solution implementation
### test-driven-dev
Test-driven development workflow:
- Write failing tests first
- Implement minimal code to pass
- Refactor with confidence
## Troubleshooting
### Skills Not Loading
1. Check directory exists:
```bash
ls -la config/skills/core/
```
2. Verify YAML frontmatter syntax:
```bash
head -20 config/skills/core/my-skill.md
```
3. Check gateway logs for loading errors:
```bash
docker compose -f deploy/compose/docker-compose.yml logs gateway | grep -i skill
```
### Skill Not Found (404)
1. Verify skill is enabled (`enabled: true` or omitted)
2. Check exact name spelling
3. Ensure file extension is `.md`
4. Confirm directory is in `SKILLS_PATH`
### Version Conflicts
If two skills have the same `name@version`, loading fails. Use unique version numbers or place skills in separate directories.
Questions about Shannon's system prompt
Does Shannon's system prompt contain instructions that work against the user?
Yes. 1 instruction in Shannon's system prompt was flagged as working against the person the product is talking to, most of them under unsafe request handling. Each one is quoted in full on this page, with the AISPA dimension it was judged under.
How long is Shannon's system prompt?
16,041 characters across 2 prompts on this page. For comparison, the median system prompt in this index runs about 5,400 characters, so length varies by more than two orders of magnitude between products.
How many versions of Shannon's system prompt are on record?
2. Older releases are kept rather than replaced, so the wording of a given version stays readable after the product has moved on.
Where did this Shannon system prompt come from?
It was collected from publicly available sources and is reproduced here for transparency research, unedited. This site does not extract prompts from products itself.
How was Shannon's system prompt audited?
Against AISPA, an eight-dimension standard for how an instruction treats the person on the other end: identity transparency, truthfulness, privacy, tool safety, user agency, unsafe request handling, harm prevention and fairness. This audit was ai audit. The method is described in the paper behind the standard.