Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 6 additions & 19 deletions services/sandbox/SYSTEM_PROMPT.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
|websearch search "query" → web research
|slack search "query" → Slack search
|linear search "query" → Linear issue search
|vlogs query "level:error" → recent service errors
|centaur-investigator self → current sandbox/thread debug state
|Tool commands are normal CLIs backed by mounted repo packages. Use direct tool CLIs for tools.
|For tool smoke tests, use `<tool> health` as the canonical check. Do not invent ad hoc "test this tool" probes or raw upstream calls unless `health` fails and you are triaging the failure.
|For broad tool smoke tests, use the `tool-health-smoke` skill or run its health runner when it is available.
Expand All @@ -112,23 +112,10 @@
|Do not serialize independent searches across Slack, CRM, notes, web, or observability unless one result is needed to construct the next query.
|Prefer one batched lookup round with the most likely sources over broad sequential discovery. If a tool contract is already shown in this prompt, a live skill, or recent `<tool> --help` output, use that contract directly.
|
|[Observability — logs + execution data]
|You have full access to Centaur's internal observability via tool CLIs such as `vlogs`.
|If a user says a workflow, alert, or channel post never populated, or asks you to check the code for issues, investigate runtime evidence before proposing redesigns or simplifications: read the relevant code paths, check workflow status, and inspect `vlogs thread_trace` or `vlogs thread_logs` plus any other relevant observability tools first.
|If a user reports an internal tool integration or auth failure, inspect runtime evidence before suggesting secret or permission rewiring: check live tool behavior and `vlogs` evidence to confirm whether secrets resolved and what request failed, then compare the tool's code path with a known-good integration before recommending secret or permission changes.
|
|Logs (VictoriaLogs via `vlogs`):
| vlogs errors → errors across all services (last 1h)
| vlogs errors --service api --start 6h → API errors in last 6h
| vlogs thread_logs --thread-key C0AJ07U8Z1N:1234 → all logs for a specific thread
| vlogs thread_trace --thread-key C0AJ07U8Z1N:1234 → end-to-end timeline across API, sandbox, tools, subagents, and delivery
| vlogs slow_requests --threshold-ms 3000 → requests slower than 3s
| vlogs tool_calls --tool-name websearch --start 24h → tool call history
| vlogs execution_timeline --execution-id exe_123 → full execution trace
| vlogs service_health → error/request counts per service
| vlogs sandbox_activity → sandbox container lifecycle
| vlogs tool_analytics --start 7d → tool usage stats
| vlogs query 'level:error AND event:tool_call_completed' --limit 20 → raw LogsQL
|[Observability — current sandbox only]
|Use `centaur-investigator self` for Centaur runtime debugging. It is scoped to this sandbox's current thread/session by default.
|If a user reports a workflow, alert, channel post, tool integration, or auth failure, inspect repo code and then use `centaur-investigator self --json` for runtime evidence before proposing secret, permission, or design changes.
|Do not run raw `vlogs`, `vmetrics`, Grafana, broad session searches, or arbitrary Postgres queries for other threads/sandboxes unless the sandbox has explicit operator-mode access for that investigation.
|
[Ethereum Mainnet RPC]
|When you need an Ethereum mainnet RPC endpoint and the user has not specified another provider, use the Reth-hosted mainnet endpoints:
Expand All @@ -152,7 +139,7 @@
| twitter search ethereum --limit 20
| linear search "bug in auth"
| notion search "meeting notes"
| vlogs query 'level:error AND _stream:{service="api"}' --limit 20
| centaur-investigator self --json

[Tool discovery — discover before you call]
|IMPORTANT: Before using any unfamiliar tool CLI, run `<tool> --help` to see commands, parameters, and descriptions.
Expand Down
40 changes: 37 additions & 3 deletions tools/infra/centaur_investigator/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,26 @@

app = typer.Typer(
name="centaur-investigator",
help="Investigate Centaur threads and sessions from readonly Postgres.",
help="Investigate the current Centaur sandbox/thread by default.",
)


@app.command("health")
def health():
"""Assert centaur-investigator connectivity and auth with a safe read-only check."""
"""Assert centaur-investigator connectivity without scanning other threads."""
from .client import _client

client = _client()
try:
details = client.search_sessions(limit=1)
details = client.self_state(limit=1, include_observability=False)
if details.get("status") == "error" and "requires CENTAUR_THREAD_KEY" in str(
details.get("error")
):
details = {
"status": "ok",
"scope": "unclaimed",
"note": "health ran outside a claimed session; self-debug activates with CENTAUR_THREAD_KEY",
}
if isinstance(details, dict) and details.get("status") == "error":
raise RuntimeError(
str(details.get("error") or "centaur-investigator health check failed")
Expand Down Expand Up @@ -91,6 +99,32 @@ def _print_investigation(result: dict[str, Any]) -> None:
console.print(table)


@app.command("self")
def self_debug(
limit: int = typer.Option(25, "--limit", "-n", help="Max rows per source."),
observability: bool = typer.Option(
True,
"--observability/--no-observability",
help="Query self-scoped aggregate vlogs/vmetrics metadata.",
),
window_hours: int = typer.Option(24, "--window-hours", help="Observability lookback."),
logs_limit: int = typer.Option(100, "--logs-limit", help="Max log metadata rows."),
json_output: bool = typer.Option(False, "--json", help="Output raw JSON."),
) -> None:
"""Inspect only this sandbox's current thread/session state."""
result = CentaurInvestigatorClient().self_state(
limit=limit,
include_observability=observability,
window_hours=window_hours,
logs_limit=logs_limit,
)
_require_ok(result)
if json_output:
_print_json(result)
return
_print_investigation(result)


@app.command("investigate")
def investigate(
query: str = typer.Argument(..., help="Natural-language query, Slack link, or thread_key."),
Expand Down
Loading
Loading