Self-Describing Capabilities
Agenticore agents auto-discover their enabled features at runtime and inject a capabilities block into every Claude session. This ensures the LLM knows what it can do — voice, Telegram, A2A, observability — without manual prompt maintenance.
Problem
An agent pod may have voice, Telegram, GitHub, and MCP gateway features enabled via environment variables. But Claude doesn’t read env vars — it only sees its system prompt. Without explicit injection, asking “reply by voice” gets “I don’t have voice capabilities.”
How It Works
Pod env vars + Config
│
▼
capabilities.py._build_registry()
│ reads get_config() + os.environ
│ builds list[Capability]
▼
render_capabilities_prompt()
│ filters to enabled only
│ renders markdown block
▼
Injected into Claude sessions:
- Agent Mode: --append-system-prompt in build_claude_cmd()
- Telegram: prepended to system message in _process_and_respond()
Capability Registry
Each capability is a simple dataclass:
@dataclass
class Capability:
name: str # identifier
enabled: bool # derived from env/config at runtime
description: str # what the agent can DO with this feature
Current capabilities:
| Name | Enabled By | Description |
|---|---|---|
voice | VOICE_SERVICE_URL | STT/TTS via HTTP voice service |
telegram | TELEGRAM_BOT_TOKEN | Connected as Telegram bot |
agent_mode | AGENT_MODE=true | Persistent agent with model/turns config |
agentibridge | AGENTIBRIDGE_URL | Agent-to-agent communication |
redis | REDIS_URL | Session persistence, job queue, events |
observability | OTel config | OpenTelemetry tracing |
github | GITHUB_TOKEN or GitHub App | Repository interaction |
langfuse | LANGFUSE_PUBLIC_KEY | LLM observability |
litellm_mcp | LITELLM_MCP_GATEWAY_KEY | External MCP tool servers |
Injection Points
Agent Mode (CLI sessions)
In agent_mode/agent.py, build_claude_cmd() appends the capabilities block after the system.md system prompt:
from agenticore.capabilities import render_capabilities_prompt
caps_prompt = render_capabilities_prompt()
if caps_prompt:
cmd.extend(["--append-system-prompt", caps_prompt])
Telegram Connector (in-process)
In connectors/telegram.py, capabilities are merged with TELEGRAM_SYSTEM_PROMPT before building the message list:
from agenticore.capabilities import render_capabilities_prompt
caps = render_capabilities_prompt()
full_system = "\n\n".join(filter(None, [system_prompt, caps]))
Adding a New Capability
One entry in _build_registry() inside agenticore/capabilities.py:
caps.append(Capability(
name="my_feature",
enabled=bool(os.environ.get("MY_FEATURE_URL")),
description="Feature X is available — can do A, B, C.",
))
No other files need changes. Every agent session on pods with that env var will automatically know about the feature.
Output Example
## Agenticore Agent Capabilities
You are **anton-agent**, an agenticore-powered AI agent.
The following capabilities are active on this instance:
- **voice**: You have voice capabilities (speech-to-text and text-to-speech)...
- **telegram**: You are connected to Telegram as a bot...
- **agent_mode**: Running in AGENT_MODE as a persistent AI agent...
- **agentibridge**: Connected to AgentiBridge for agent-to-agent communication...
Use these capabilities when relevant to user requests.
Do not claim you lack a capability listed above.
Design Principles
- Zero-maintenance — capabilities derived from existing config. No manual sync when features change.
- Declarative — each capability is data, not logic.
- Graceful absence — if no capabilities are enabled,
render_capabilities_prompt()returns empty string. No injection, no noise.