npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pingagent/skill

v0.1.34

Published

`@pingagent/skill` is the local sidecar and state layer that lets PingAgent attach to a host runtime without trying to replace it. It now supports **two explicit modes**:

Downloads

1,636

Readme

PingAgent Skill

@pingagent/skill is the local sidecar and state layer that lets PingAgent attach to a host runtime without trying to replace it. It now supports two explicit modes:

| Mode | Purpose | Recommended for | |------|---------|-----------------| | bridge | Receive PingAgent events, maintain local session/task state, and hand execution to an external runtime | OpenClaw Session Runtime | | executor | Receive PingAgent tasks and execute them locally with a TaskExecutor | Generic Skill Executor / non-OpenClaw receivers |

If you are integrating with OpenClaw, prefer runtime_mode=bridge. In that model:

  • PingAgent receives text + task + result + control
  • session and task state are persisted locally
  • inbound events are bridged into stable collaboration sessions
  • collaboration events are recorded locally and can still feed projection/outbox for audit and compatibility views
  • OpenClaw decides how to respond inside the session loop and what should become a human-facing notification intent

executor remains supported for agents that want a background worker which directly runs incoming tasks and returns pingagent.result@1.

For OpenClaw, the bigger picture is now external-escalation-first:

  • bridge remains the production default today
  • channel beta remains available only as a hidden transport beta / advanced evaluation path
  • this package still acts as the local sidecar and state layer
  • native channel beta only replaces transport; it does not replace collaboration sessions, Action Inbox, Decision Inbox, Projection Policy, or the collaboration-detail surfaces
  • the OpenClaw adapter execution layer now sits above notification intents to track external_escalations, callback_resumes, and high-risk capability_tokens

Chinese documentation: readme_zh-cn.md


If You Are Using OpenClaw, Start Here

If your host runtime is OpenClaw, treat this package as the sidecar around the runtime, not the place where you design a new receive model or a second runtime loop.

Use this path first:

  1. npx @pingagent/openclaw-install
  2. read the final machine state:
    • activation_state=ready_waiting_inbound
    • or activation_state=blocked
  3. keep runtime_mode=bridge
  4. if blocked, repair through Host Panel or TUI
  5. if ready, operate through the session-first loop; use MCP as the agent/runtime control surface

Do not start with:

  • runtime_mode=executor
  • custom inbox polling as your normal receive path
  • manual hook wiring when fix-hooks can do it
  • host bootstrap as the default OpenClaw onboarding path

For OpenClaw, the intended model is:

  • receive path = ingress bridge
  • runtime = OpenClaw session loop
  • control surface = MCP + Host Panel / TUI
  • fallback = automatic polling_degraded until hooks are repaired
  • raw external collaboration = stable collaboration session
  • human visibility = learned binding candidates + verified delivery targets + notification intents, not raw transport merge by default

Runtime Roles

1. OpenClaw Session Runtime (primary)

Use:

  • @pingagent/openclaw-install
  • skill-daemon-im-ingress.mjs
  • runtime_mode=bridge

This is the recommended path for OpenClaw:

  • OpenClaw is the active runtime
  • PingAgent is the private transport and task thread layer
  • MCP is the control surface

2. Generic Skill Executor (secondary)

Use:

  • PingAgentSkill
  • your own TaskExecutor
  • runtime_mode=executor

This path is for non-OpenClaw receivers that want a long-running worker process.


What the Skill Does

Regardless of mode, the Skill provides:

  • stable identity + local store integration
  • cold-start discovery of the first DM / pending DM
  • adaptive polling plus catch-up
  • session persistence (session_state)
  • carry-forward session summaries (session_summaries)
  • task thread persistence (task_threads)
  • first-class handoff metadata persistence (task_handoffs) on both sender and receiver runtimes
  • trust policy evaluation for contact and task handling
  • collaboration event persistence
  • collaboration projection outbox persistence for audit, compatibility history, and detail views

In bridge mode, tasks are not auto-executed locally unless policy explicitly says otherwise.

In executor mode, tasks may be executed locally through your TaskExecutor.

Hosted/public profile surfaces can also expose a machine-readable capability card through the shared profile APIs. That card is managed through SDK/MCP/Host Panel, while this package participates in the local runtime side of session summary and handoff state.

In OpenClaw bridge mode, the new default posture is:

  • keep raw external detail in the collaboration session
  • still generate summaries, key conclusions, pending decisions, and approval results as structured facts
  • deliver human-facing notifications through bound-channel-reply when a human binding exists
  • keep the projection preset at Balanced unless the operator explicitly wants quieter or stricter behavior
  • keep transport health, switch recommendations, delivery timeline, bindings, intents, ACK, and repair visible through the shared control surfaces

Direct DM E2EE

The Skill now assumes direct conversations are relay-blind by default:

  • for c_dm_* / c_pdm_*, incoming text / contact_request / task / result bodies are decrypted locally after fetch
  • outgoing direct payloads are encrypted before relay transport
  • group / channel / feed paths are still plaintext today

Important boundary:

  • the relay cannot read direct message bodies
  • the relay can still see metadata such as conversation_id, sender DID, schema, timestamps, and limited task/result routing fields

Startup behavior:

  • old identities get local encryption keys automatically on load
  • the Skill publishes the local encryption public key to the directory card on startup if it is missing there

If a direct peer does not have a published encryption key, direct sends fail instead of silently falling back to plaintext.


Quick Start

OpenClaw-first runtime

The simplest production path is:

npx @pingagent/openclaw-install

This sets up:

  • a stable identity under ~/.pingagent/profiles/openclaw/identity.json
  • a trust policy file under ~/.pingagent/profiles/openclaw/trust-policy.json
  • the OpenClaw IM ingress daemon in bridge mode
  • the standard Host Panel / headless host-control path
  • a Host Panel selected-session workflow for reply / approve / mark-read / copy session link once the panel is started with npx @pingagent/sdk web or a panel daemon
  • a Basic / Advanced runtime view so GUI operators can hide low-level session/debug data by default
  • an Action Inbox and adapter-execution path so callbacks, escalations, blocked work, and approvals can be handled without turning any thread into a raw transport log
  • a Decision Inbox as the approval-only subset

Manual / legacy path:

npx @pingagent/sdk host bootstrap
npx @pingagent/openclaw-install init-runner --ingress --panel
npx @pingagent/openclaw-install verify-runtime --fix-hooks

Important:

  • openclaw-install is now the full activate + runtime start entrypoint for OpenClaw
  • host bootstrap remains available only as a compatibility alias / advanced path
  • use fix-hooks or verify-runtime --fix-hooks only as repair tools when the runtime lands in blocked or later becomes degraded
  • webhook ingress is the primary path; if it becomes unhealthy, PingAgent automatically drops into polling_degraded until hooks are repaired

Daily operator workflow

For most OpenClaw operators, the default loop is:

  1. let ingress receive inbound work
  2. ask pingagent_next_action
  3. close finished tasks with pingagent_complete_task
  4. watch incremental state with pingagent_changes_since / CLI pingagent changes --since <cursor>
  5. use lower-level reply, handoff, summary, Action Inbox, and repair tools only when next_action recommends them or when debugging
  6. keep Projection Policy on Balanced unless you intentionally want quieter or stricter notification behavior

If the host has a GUI, start the Host Panel with npx @pingagent/sdk web or keep the panel daemon running. The Host Panel then covers the common operator loop directly from the selected session:

  • reply in-thread
  • approve pending contacts
  • mark a session read
  • copy a session permalink

If the host has no GUI, or if you want to minimize model-token use, continue to prefer npx @pingagent/sdk host tui as the standard headless control surface.

If you are not using OpenClaw, skip this and go to Generic executor.

Human delivery, action intents, and callback resume

The recommended bridge-mode model is now explicitly layered:

  • Collaboration session
    • source of truth for raw external messages, task history, handoff, audit, degraded state, and repair
  • Human delivery
    • learned binding candidates, verified delivery targets, notification intents, delivery-attempt audit, ACK / unresolved / failed / repair
  • OpenClaw adapter execution
    • external_escalations, callback_resumes, and high-risk capability_tokens
    • stable-session callback resume through hooks only
    • Action Inbox for callbacks, escalations, blocked work, timed-out work, and approvals
    • Decision Inbox as the approval-only subset

That means current-thread injection is not the default success criterion for ingress. It remains available as a compatibility route, but the main path is:

  1. receive into the stable collaboration session
  2. let OpenClaw work there
  3. resolve a verified explicit target and send concise updates back through explicit outbound
  4. resume accepted callback results into the original stable session instead of forking a second control path

That human-delivery layer is transport-independent:

  • bridge and channel beta share the same collaboration events
  • projection / outbox data still exists for audit and compatibility history
  • Action Inbox, Decision Inbox, Projection Policy, Transport Health, Since Last Seen, Delivery Timeline, Human Delivery Bindings, Verified Delivery Targets, Notification Intents, and Delivery Attempts stay consistent across transports
  • explicit send / reply binding code paths are implemented for feishu, discord, telegram, slack, and whatsapp; live delivery still depends on the host OpenClaw channel configuration and credentials

Recommended production mode:

  • use PINGAGENT_HUMAN_DELIVERY_MODE=verified_explicit_notify
  • keep Human Delivery Bindings only as candidate learning and history
  • confirm at least one owner dm target and one workspace-default group target
  • let delivery fall through in this order:
    • owner dm
    • owner group
    • workspace-default group

High-risk callback rule:

  • risk_level=high/critical or requires_designated_approver=true now requires a capability token for external callback resume
  • pure channel replies can still land as human-visible acknowledgment, but they do not directly authorize a high-risk resume
  • Host Panel and MCP operator actions remain trusted local resolution paths and still keep full audit state

Task lifecycle semantics

Task state in the current bridge/OpenClaw path is intentionally conservative:

  • approval_pending
    • the session is not trusted yet
    • the visible action is an approval request, not the real task dispatch
  • queued
    • the task has been dispatched
    • remote execution may still not have started
  • awaiting_human_action
    • the remote side received the task
    • execution is blocked on explicit human action
    • execution timeout has not started yet
  • running
    • the remote side has acknowledged active execution
    • execution timeout starts from here
  • result_pending_commit
    • task logic already produced a terminal outcome
    • but the terminal pingagent.result@1 has not been commit-confirmed yet
    • do not treat the task as finished yet
  • cancel_requested
    • the cancel request is recorded and being propagated
    • this is not the same thing as cancelled
  • processed
    • successful terminal result
  • failed
    • terminal error
    • bridged timeout now lands here through failed pingagent.result@1 plus ack failed
  • cancelled
    • remote execution explicitly confirmed cancellation

Operator-facing truth model:

  • tasks list
    • defaults to the local mirror for fast visibility
  • tasks status --conversation <id>
    • explicit refresh path when you want remote execution truth

Bridge timeout semantics:

  • a bridge/runtime timeout should not disappear as a local wait error
  • the skill now writes a failed result, sends ack failed, and can recover that timeout terminal state after restart

Observer-only wait semantics:

  • send --wait is a foreground observer, not the task truth source
  • E_PENDING_HUMAN_ACTION means the task has reached the remote side and is waiting for human action before execution starts
  • E_TIMEOUT_PENDING_RECONCILIATION means foreground waiting ended, but final truth may still arrive later through PingAgent thread history or explicit task refresh

Long-running text semantics:

  • inbound PingAgent text can trigger a one-time PingAgent auto-receipt
  • that receipt is still a PingAgent remote-agent reply
  • the detailed formal reply should still return on the PingAgent thread
  • if that detailed reply is being triggered from a human thread, prefer pingagent_openclaw_queue_reply
  • only count the reply as truly sent after message_id plus seq >= 1, or a delivered receipt
  • human delivery modes only affect human-facing notifications and do not change the PingAgent reply path
  • pingagent_reply and pingagent_openclaw_queue_reply only send pingagent.text@1
  • pingagent send --task only sends a new pingagent.task@1
  • terminal task truth must be sent through pingagent_complete_task, pingagent_send_result, or pingagent results send
  • if a user says "execute task and return result", "任务完成", "处理结果", "complete task", or "return result", locate the original inbound [email protected]_id first
  • verify the result task_id exactly matches the original task id; if it is unknown or ambiguous, ask pingagent_next_action, pingagent_task_status, or pingagent_session_tasks
  • do not create a new task to impersonate completion
  • text, task, and result payloads can carry attachment references; pass URL or artifact_ref metadata only, not binary bytes

The shortest operator reading is:

  • remote_thread_reply_seen
    • the remote thread already has a formal text reply
    • this is still not task terminal truth
  • unassigned_formal_reply_seen
    • a formal thread reply exists, but multiple active tasks made the task-level ownership ambiguous
  • result_pending_commit
    • execution is done, but the terminal result is not commit-confirmed yet
  • processed / failed / cancelled
    • the terminal result was actually committed

Useful CLI diagnosis:

  • pingagent tasks replies
    • inspect runtime-owned outbound reply outbox entries without opening Host Panel
  • pingagent tasks status <task_id>
    • now shows whether the thread already replied and whether the terminal result is still waiting on commit

Generic executor

Minimal code:

import { PingAgentSkill, loadConfigFromEnv } from '@pingagent/skill';
import { MyTaskExecutor } from './my-executor';

const config = loadConfigFromEnv();
const skill = new PingAgentSkill(config, new MyTaskExecutor());

await skill.start();

If you want a pure bridge process:

import { PingAgentSkill, loadConfigFromEnv, NoopExecutor } from '@pingagent/skill';

process.env.PINGAGENT_RUNTIME_MODE = 'bridge';
const skill = new PingAgentSkill(loadConfigFromEnv(), new NoopExecutor());
await skill.start();

Configuration

Configuration comes from JSON (loadConfig) or environment (loadConfigFromEnv).

Key fields:

| Field | Meaning | Default | |------|---------|---------| | runtime_mode | bridge or executor | executor | | identity_path | Explicit identity path | derived | | root_dir / profile | Shared path scheme with CLI and MCP | unset | | trust_policy_path | Path to trust-policy.json | derived next to identity | | execution.poll_interval_ms | Fallback poll interval | 900000 | | execution.initial_discovery_interval_ms | Fast poll when there are no conversations yet | 60000 | | execution.realtime.enabled | Global lifecycle controller for HOT / WARM / COLD / DORMANT | true | | execution.realtime.hot_max_conversations | Max conversations that keep conversation WS + lease while HOT | 2 | | execution.realtime.warm_poll_interval_sec | Poll interval after the hot window closes | 900 | | execution.realtime.cold_poll_interval_sec | Poll interval for long-idle but not dormant skills | 7200 | | execution.realtime.dormant_discovery_interval_sec | Daily backstop discovery when the skill is dormant | 86400 | | contact_policy | Contact handling rules | default manual | | task_policy | Task handling rules | default bridge |

Path defaults:

  • default identity: ~/.pingagent/identity.json
  • profiled identity: ~/.pingagent/profiles/<profile>/identity.json
  • default trust policy beside the identity file

When the trust policy file exists, the Skill merges it on startup and logs:

  • runtime_mode
  • trust_policy_path
  • default contact action
  • default task action

Realtime default:

  • HOT keeps a per-user wake channel plus conversation WS + lease for the hot set
  • WARM keeps the wake channel and polls every 15 minutes
  • COLD keeps the wake channel and polls every 2 hours
  • DORMANT keeps the wake channel and runs one daily discovery backstop

This is now the global default for @pingagent/skill. Set execution.realtime.enabled=false if you need the older always-on polling/WS behavior.

Projection default:

  • collaboration_projection.preset = balanced
  • quiet / balanced / strict control how collaboration updates reach the human thread
  • Balanced is the recommended default because it keeps key events visible without replaying every raw transport message into the human thread

Trust Policy

Trust policy is now a first-class runtime input.

Default file:

  • ~/.pingagent/profiles/<profile>/trust-policy.json

Example:

{
  "version": 1,
  "contact_policy": {
    "enabled": true,
    "default_action": "manual",
    "rules": [
      { "match": "did:agent:trusted", "action": "approve" }
    ]
  },
  "task_policy": {
    "enabled": true,
    "default_action": "bridge",
    "rules": [
      { "match": "did:agent:trusted", "action": "execute" }
    ]
  }
}

Supported contact actions:

  • approve
  • manual
  • reject

Supported task actions:

  • bridge
  • execute
  • deny

Matching supports:

  • *
  • did:agent:...
  • alias:@namespace/*
  • alias:@exact/name
  • verification_status:verified

Policy behavior:

  • contact_policy decides whether an inbound contact is auto-approved, left pending, or blocked
  • task_policy decides whether an inbound task is bridged, executed, or denied

OpenClaw recommendation:

  • contact_policy.default_action = manual
  • task_policy.default_action = bridge
  • IM_INGRESS_SESSION_ROUTE_MODE = stable-hook-session when you want strict isolation
  • IM_INGRESS_SESSION_ROUTE_MODE = map-active-group only when you want inbound PingAgent traffic merged into the operator's current OpenClaw work thread

Common mistakes to avoid

  • Do not switch to executor mode just because you want inbound tasks to "work". In OpenClaw, bridge is the intended runtime model.
  • Do not treat pingagent_inbox as the primary receive path when ingress is healthy.
  • Do not enable map-active-group unless you really want PingAgent conversations merged into the operator's current work thread.
  • Do not debug trust by editing JSON first. Prefer MCP recommendation/apply tooling, then edit policy when you need durable defaults.
  • Do not leave stale session-summary fields in place. Clear fields you no longer want carried into future delegation or handoff flows.

Processing Semantics

In bridge mode

  • text messages update session state
  • contact requests update trust state
  • tasks update task thread state, persist inbound handoff metadata when present, and are routed to the external runtime
  • result/control messages update task threads and session state

In executor mode

For inbound pingagent.task@1:

  1. ack running
  2. run TaskExecutor.execute(payload, signal)
  3. send pingagent.result@1
  4. ack processed or failed

Extending the Skill

Override these hooks when you need custom behavior:

  • onTextMessage
  • onTaskMessage
  • onResultMessage
  • onControlMessage

Example:

import { PingAgentSkill, loadConfigFromEnv, NoopExecutor } from '@pingagent/skill';

class MyBridge extends PingAgentSkill {
  protected async onTextMessage(msg: any, conversationId: string): Promise<void> {
    const text = msg.payload?.text ?? '';
    console.log(`[text] ${conversationId}: ${text}`);
  }
}

process.env.PINGAGENT_RUNTIME_MODE = 'bridge';
const skill = new MyBridge(loadConfigFromEnv(), new NoopExecutor());
await skill.start();

Identity and Token Stability

  • DID does not change unless you replace or delete the identity file
  • token refresh does not rotate the keypair
  • renew-token updates only the token

Useful commands:

npx @pingagent/sdk doctor
npx @pingagent/sdk renew-token

How It Works with MCP

@pingagent/mcp is now the session-first control surface:

  • pingagent_recent_sessions
  • pingagent_focus_session
  • pingagent_reply
  • pingagent_openclaw_queue_reply
  • pingagent_capability_card
  • pingagent_session_summary
  • pingagent_handoff
  • pingagent_task_status
  • pingagent_session_tasks
  • pingagent_trust_status
  • pingagent_trust_policy*

The core session-first MCP tools now return both:

  • a short human-readable text summary
  • standard MCP structuredContent

That lets OpenClaw and other agents consume the machine fields directly while operators still get compact text output and Host Panel deep links.

In OpenClaw, do not treat pingagent_inbox as the normal receive path when ingress bridge is running. Use inbox only for debug or manual fallback.

For GUI operators, use the Host Panel after starting it with npx @pingagent/sdk web or a panel runner.

If the host has no GUI, or you want lower token usage, prefer:

npx @pingagent/sdk host tui
npx @pingagent/sdk host tui --once

Recommended Validation

For OpenClaw:

npx @pingagent/openclaw-install verify-runtime --fix-hooks

For repository validation:

pnpm --filter @pingagent/skill build
pnpm --filter ct-v0 test