ReskPoints · Documentation
Agent action logging
ReskPoints records structured “agent action” events — agent, action, probability, parameters, result, timing — masks sensitive fields, samples what matters and fans out to console, file, webhook, Datadog and Prometheus.
On this page
Install
pip install reskpoints
pip install "reskpoints[datadog,prometheus,opentelemetry,webhook]"
pip install "reskpoints[all]"
Core dependencies are pyyaml, httpx and python-dotenv. Exporter SDKs are optional extras.
Quick start
from reskpoints import AgentLogger
logger = AgentLogger() # reads ./reskpoints.yaml, falls back to defaults
results = logger.log(
"agent-1", # agent_id
"tool_call", # action
0.95, # probability
{"tool": "search", "api_key": "sk-abcdef1234567890"},
"3 results", # result
)
print(results) # [LogResult(success=True, platform='console', …)]
print(logger.health()) # per-platform status
Console output masks credentials by default:
[11:13:43.120] ✓ agent-1 | tool_call p=0.95 | params={"api_key": "sk****90"} | result=3 results
Decorator and async
from reskpoints import log_action
@log_action(agent_id="coder")
def execute_python(code: str) -> str:
...
await logger.alog("agent-1", "search", 0.95, {"q": "papers"}, "3 results")
The decorator targets synchronous functions; for async def call alog() yourself. Exceptions are logged with success=False and re-raised.
API
| Symbol | Purpose |
|---|---|
AgentLogger(config=None) | Loads ./reskpoints.yaml when no config/path is given. |
logger.log(...) / alog(...) | Build, mask, sample and dispatch an ActionLog; returns one LogResult per platform. |
logger.log_action(entry) | Dispatch an existing ActionLog. |
logger.health() | Status, queue size and last success/failure per platform. |
ActionLog / LogResult | Dataclasses with to_dict()/from_dict() for JSONL and webhooks. |
FieldMasker | Field-name masking plus regex masking of long identifiers and keys. |
Configuration
# reskpoints.yaml
agent_logger:
environment: "${ENV:development}"
masking:
enabled: true
sensitive_fields: [api_key, password, token, secret, authorization]
sampling:
default_rate: 1.0
rules:
- action: "heartbeat"
rate: 0.01
- action: "message_*"
rate: 0.5
platforms:
console: {enabled: true, format: "human"}
file: {enabled: false, path: "/var/log/resk/agent_actions.jsonl"}
webhook:
enabled: false
url: "https://example.internal/events"
signing_secret: "${WEBHOOK_SECRET}"
prometheus: {enabled: false, pushgateway_url: "http://localhost:9091", job_name: "resk"}
datadog: {enabled: false, api_key: "${DD_API_KEY}", site: "datadoghq.com"}
${VAR} and ${VAR:default} are interpolated recursively. There are no RESKPOINTS_* variables; pass a path to AgentLogger(path) to use another file. The YAML is a shallow merge over defaults: if you provide an agent_logger block, include the platforms block too, or nothing is enabled (see limitations).
Platforms
| Platform | Output | Notes |
|---|---|---|
| Console | Human-readable line or JSON | Enabled by default |
| File | JSONL appended to a path | Directory is created at construction |
| Webhook | HTTP POST with HMAC-SHA256 signature | SSRF checks at construction; allow_private for internal endpoints |
| Datadog | Logs API v2, ddsource=reskpoints | Requires datadog-api-client |
| Prometheus | agent_action_total pushed per event | Requires prometheus-client |
| OpenTelemetry | One span per event, OTLP/HTTP | Selectable from YAML (platforms.opentelemetry) |
# reskpoints.yaml
agent_logger:
platforms:
opentelemetry:
enabled: true
endpoint: "http://localhost:4318"
service_name: "my-agent"
Registering a platform programmatically still works when you need a custom configuration object: logger.platforms["opentelemetry"] = OpenTelemetryPlatform({...}).
CLI
reskpoints --config reskpoints.yaml log --agent-id a1 --action tool_call --probability 0.9 --params '{"tool":"search"}'
reskpoints status
reskpoints test
reskpoints replay events.jsonl
--config is a global option and must come before the subcommand. replay re-applies sampling and masking.
Limitations
- Missing
platformsblock. The shallow merge means a partial YAML enables nothing; the logger falls back to an in-memory mock, still reports success, and now logs a warning. Checklogger.platformsin health checks. - Retry/buffering YAML sections are not wired at the top level; the per-platform defaults apply. Buffered events are dropped rather than retried, and overflow is silent.
- Masking covers
parametersonly — notresult,metadataor the envelope. Its regex also masks any 20+ character alphanumeric token. - Webhook signatures are computed over a differently serialised body than the one sent; verify against the parsed JSON or disable signature checks until fixed.
- CLI
tailis a placeholder (sleeps until Ctrl-C).
Links
- GitHub · PyPI · project page