@agent-pulse/openclaw-skill 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # @agent-pulse/openclaw-skill
2
+
3
+ OpenClaw skill integration for [AgentPulse SDK](https://www.npmjs.com/package/@agent-pulse/sdk) gating. Provides liveness-based gate checks for incoming and outgoing agent requests.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @agent-pulse/openclaw-skill @agent-pulse/sdk
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { startup, withGate, getGateStatus } from "@agent-pulse/openclaw-skill";
15
+
16
+ // Initialize gate from skill YAML config
17
+ const result = await startup({
18
+ enabled: true,
19
+ mode: "strict", // "strict" | "warn" | "log"
20
+ threshold: "24h", // liveness threshold
21
+ chainId: 84532, // Base Sepolia (default)
22
+ });
23
+
24
+ if (result.success && result.gate) {
25
+ // Gate an incoming request
26
+ const allowed = await result.gate.gateIncoming("0x...");
27
+
28
+ // Or use the middleware wrapper
29
+ const protectedAction = withGate(async (ctx, input) => {
30
+ // your action logic
31
+ });
32
+ }
33
+ ```
34
+
35
+ ## Gate Modes
36
+
37
+ | Mode | On Reject | On Error |
38
+ |----------|---------------------|---------------------|
39
+ | `strict` | Throws error (403) | Throws error (500) |
40
+ | `warn` | Logs warning | Logs, allows |
41
+ | `log` | Telemetry only | Silent, allows |
42
+
43
+ ## Links
44
+
45
+ - [AgentPulse SDK](https://www.npmjs.com/package/@agent-pulse/sdk)
46
+ - [Repository](https://github.com/consensus-hq/agent-pulse)
47
+
48
+ ## License
49
+
50
+ MIT
package/SKILL.md ADDED
@@ -0,0 +1,148 @@
1
+ # OpenClaw Skill - AgentPulse Gate Integration
2
+
3
+ This OpenClaw skill integrates the AgentPulse SDK for bidirectional gating of agent interactions. It provides liveness verification before allowing skill actions to proceed.
4
+
5
+ ## Overview
6
+
7
+ The AgentPulse Gate skill enables OpenClaw agents to:
8
+
9
+ 1. **Verify agent liveness** before processing incoming requests
10
+ 2. **Check target agent status** before making outgoing calls
11
+ 3. **Enforce gating policies** based on configurable modes
12
+ 4. **Surface gate status** in orchestrator queries
13
+
14
+ ## Configuration
15
+
16
+ Add a `gate` block to your skill YAML configuration:
17
+
18
+ ```yaml
19
+ gate:
20
+ enabled: true
21
+ mode: strict # strict | warn | log
22
+ threshold: 24h # duration string (e.g., 30m, 1h, 24h, 7d)
23
+ chainId: 84532 # optional: Base Sepolia (default) or 8453 for Base Mainnet
24
+ rpcUrl: https://... # optional: custom RPC endpoint
25
+ ```
26
+
27
+ ### Gate Modes
28
+
29
+ | Mode | Behavior |
30
+ |------|----------|
31
+ | `strict` | Reject requests from/to dead agents with hard error |
32
+ | `warn` | Allow all requests, log warnings for dead agents |
33
+ | `log` | Passive telemetry only, no enforcement |
34
+
35
+ ### Threshold Format
36
+
37
+ The `threshold` field accepts duration strings:
38
+ - `30m` - 30 minutes
39
+ - `1h` - 1 hour
40
+ - `24h` - 24 hours
41
+ - `1d` - 1 day
42
+ - `7d` - 7 days
43
+
44
+ ## Skill Startup Hook
45
+
46
+ The skill automatically initializes the AgentPulse SDK on startup:
47
+
48
+ 1. Reads gate configuration from skill YAML
49
+ 2. Validates configuration against `gate-schema.json`
50
+ 3. Initializes AgentPulseClient with provided settings
51
+ 4. Creates AgentPulseGate instance with configured mode
52
+ 5. **Gate failure is surfaced** - if RPC is unreachable, skill errors per mode
53
+
54
+ ### Mode Mapping
55
+
56
+ | Mode | Gate Configuration |
57
+ |------|-------------------|
58
+ | `strict` | `gateIncoming` + `gateOutgoing` with hard reject |
59
+ | `warn` | Gates enabled, warnings logged, requests proceed |
60
+ | `log` | Passive telemetry, all requests proceed |
61
+
62
+ ## Gate Activation Order
63
+
64
+ ```
65
+ 1. Skill Startup
66
+ └── Initialize AgentPulse SDK
67
+ └── Fail loudly if RPC unreachable (strict/warn)
68
+
69
+ 2. Incoming Request
70
+ └── gateIncoming(requesterAddr)
71
+ ├── strict: reject if dead → throw error
72
+ ├── warn: log warning if dead → proceed
73
+ └── log: log status → proceed
74
+
75
+ 3. Execute Skill Action/Evaluator
76
+
77
+ 4. Outgoing Request (if applicable)
78
+ └── gateOutgoing(targetAddr)
79
+ └── Same behavior as incoming
80
+ ```
81
+
82
+ ## Status Output
83
+
84
+ The skill adds a `gate` section to skill status for orchestrator queries:
85
+
86
+ ```json
87
+ {
88
+ "gate": {
89
+ "enabled": true,
90
+ "mode": "strict",
91
+ "threshold": "24h",
92
+ "status": "active",
93
+ "lastCheck": 1707254400,
94
+ "agentsChecked": 42,
95
+ "agentsRejected": 3
96
+ }
97
+ }
98
+ ```
99
+
100
+ ## API
101
+
102
+ ### `gateIncoming(requesterAddr: Address): Promise<boolean>`
103
+
104
+ Check if an incoming request from `requesterAddr` should be allowed.
105
+
106
+ - Returns `true` if allowed
107
+ - Throws `AgentPulseError` in strict mode if agent is dead
108
+ - Logs and returns `true` in warn/log modes
109
+
110
+ ### `gateOutgoing(targetAddr: Address): Promise<boolean>`
111
+
112
+ Check if an outgoing request to `targetAddr` should be allowed.
113
+
114
+ - Same behavior as `gateIncoming`
115
+
116
+ ### `getGateStatus(): GateStatus`
117
+
118
+ Get current gate status for monitoring.
119
+
120
+ ## CLI Commands
121
+
122
+ The skill provides shell scripts for CLI interaction with the AgentPulse protocol:
123
+
124
+ | Command | Usage | Description |
125
+ |---------|-------|-------------|
126
+ | `attest.sh` | `./attest.sh <addr> <outcome> [--task-id <id>]` | Submit a peer attestation |
127
+ | `reputation.sh` | `./reputation.sh <addr> [--format json]` | Show composite reputation score and stats |
128
+ | `check.sh` | `./check.sh <addr> --min-score <n>` | Verify if an agent meets a reputation threshold |
129
+ | `attestations.sh` | `./attestations.sh <addr> --received\|--given` | List historical attestations |
130
+
131
+ Note: In the final distribution, these are aliased to `agent-pulse <command>`.
132
+
133
+ ## Error Handling
134
+
135
+ If the AgentPulse SDK fails to initialize (bad RPC, network issues):
136
+
137
+ - **strict mode**: Skill startup fails with error
138
+ - **warn mode**: Warning logged, skill continues without gating
139
+ - **log mode**: Silent failure, passive mode disabled
140
+
141
+ ## Integration Example
142
+
143
+ See `example-gated-skill.yaml` for complete configuration examples.
144
+
145
+ ## Dependencies
146
+
147
+ - `@agent-pulse/sdk` - AgentPulse protocol SDK
148
+ - `viem` - Ethereum interactions
@@ -0,0 +1,75 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://agent-pulse.io/schemas/openclaw-gate.json",
4
+ "title": "OpenClaw AgentPulse Gate Configuration",
5
+ "description": "Schema for the gate block in OpenClaw skill YAML configurations",
6
+ "type": "object",
7
+ "properties": {
8
+ "enabled": {
9
+ "type": "boolean",
10
+ "description": "Whether gating is enabled for this skill",
11
+ "default": false
12
+ },
13
+ "mode": {
14
+ "type": "string",
15
+ "enum": ["strict", "warn", "log"],
16
+ "description": "Gating mode: strict (reject dead agents), warn (allow with warning), log (passive telemetry only)",
17
+ "default": "strict"
18
+ },
19
+ "threshold": {
20
+ "type": "string",
21
+ "description": "Duration string specifying the maximum time since last pulse (e.g., '24h', '1d', '30m')",
22
+ "pattern": "^[0-9]+[smhdw]$",
23
+ "examples": ["24h", "1d", "30m", "7d"]
24
+ },
25
+ "rpcUrl": {
26
+ "type": "string",
27
+ "format": "uri",
28
+ "description": "Optional RPC URL for AgentPulse SDK connection. Uses default if not specified."
29
+ },
30
+ "chainId": {
31
+ "type": "integer",
32
+ "description": "Chain ID for the AgentPulse protocol (default: 84532 for Base Sepolia)",
33
+ "default": 84532
34
+ },
35
+ "contracts": {
36
+ "type": "object",
37
+ "description": "Optional contract address overrides",
38
+ "properties": {
39
+ "pulseToken": {
40
+ "type": "string",
41
+ "pattern": "^0x[a-fA-F0-9]{40}$",
42
+ "description": "PULSE token contract address"
43
+ },
44
+ "pulseRegistry": {
45
+ "type": "string",
46
+ "pattern": "^0x[a-fA-F0-9]{40}$",
47
+ "description": "PulseRegistry contract address"
48
+ }
49
+ }
50
+ }
51
+ },
52
+ "required": ["enabled"],
53
+ "if": {
54
+ "properties": {
55
+ "enabled": { "const": true }
56
+ }
57
+ },
58
+ "then": {
59
+ "required": ["mode", "threshold"]
60
+ },
61
+ "additionalProperties": false,
62
+ "examples": [
63
+ {
64
+ "enabled": true,
65
+ "mode": "strict",
66
+ "threshold": "24h"
67
+ },
68
+ {
69
+ "enabled": true,
70
+ "mode": "warn",
71
+ "threshold": "12h",
72
+ "chainId": 8453
73
+ }
74
+ ]
75
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * OpenClaw Skill - AgentPulse Gate Integration
3
+ *
4
+ * Main implementation of the OpenClaw skill framework integration.
5
+ * Provides startup hook, gate activation, and status reporting.
6
+ *
7
+ * @module openclaw-skill
8
+ */
9
+ import { type Address } from "viem";
10
+ import { AgentPulseGate } from "@agent-pulse/sdk";
11
+ import type { GateConfig, ParsedThreshold, GateRuntimeStatus, GateStats, GateStatusOutput, OpenClawGate as IOpenClawGate, SkillStartupResult } from "./types.js";
12
+ /**
13
+ * Validate gate configuration against JSON Schema
14
+ */
15
+ export declare function validateGateConfig(config: unknown): config is GateConfig;
16
+ /**
17
+ * Parse duration string to seconds
18
+ * @param threshold - Duration string (e.g., "24h", "30m")
19
+ * @returns Parsed threshold or null if invalid
20
+ */
21
+ export declare function parseThreshold(threshold: string): ParsedThreshold | null;
22
+ /**
23
+ * OpenClaw Gate implementation wrapping AgentPulse SDK
24
+ */
25
+ declare class OpenClawGate implements IOpenClawGate {
26
+ private gate;
27
+ private config;
28
+ private _status;
29
+ private _stats;
30
+ constructor(gate: AgentPulseGate, config: GateConfig);
31
+ /**
32
+ * Gate an incoming request
33
+ * @param requesterAddr - Address of the requesting agent
34
+ * @returns true if allowed, throws in strict mode if rejected
35
+ */
36
+ gateIncoming(requesterAddr: Address): Promise<boolean>;
37
+ /**
38
+ * Gate an outgoing request
39
+ * @param targetAddr - Address of the target agent
40
+ * @returns true if allowed, throws in strict mode if rejected
41
+ */
42
+ gateOutgoing(targetAddr: Address): Promise<boolean>;
43
+ /**
44
+ * Internal check implementation
45
+ */
46
+ private performCheck;
47
+ /**
48
+ * Get current gate status
49
+ */
50
+ getStatus(): GateRuntimeStatus;
51
+ /**
52
+ * Get gate statistics
53
+ */
54
+ getStats(): GateStats;
55
+ /**
56
+ * Get full status output for orchestrator queries
57
+ */
58
+ getStatusOutput(): GateStatusOutput;
59
+ }
60
+ /**
61
+ * Skill startup hook - initializes AgentPulse SDK
62
+ *
63
+ * This MUST be called before any skill action/evaluator runs.
64
+ * Gate initialization failure is surfaced based on mode:
65
+ * - strict: Throws error, skill startup fails
66
+ * - warn: Logs warning, continues without gating
67
+ * - log: Silent, continues without gating
68
+ *
69
+ * @param config - Gate configuration from skill YAML
70
+ * @returns Skill startup result with gate instance
71
+ */
72
+ export declare function startup(config: unknown): Promise<SkillStartupResult>;
73
+ /**
74
+ * Middleware that activates gate BEFORE any skill action/evaluator
75
+ *
76
+ * Usage in skill definition:
77
+ * ```typescript
78
+ * actions: {
79
+ * myAction: withGate((ctx, input) => { ... })
80
+ * }
81
+ * ```
82
+ */
83
+ export declare function withGate<TInput, TOutput>(action: (ctx: {
84
+ gate?: IOpenClawGate;
85
+ }, input: TInput) => Promise<TOutput>, options?: {
86
+ direction?: "incoming" | "outgoing";
87
+ address?: Address;
88
+ }): (ctx: {
89
+ gate?: IOpenClawGate;
90
+ }, input: TInput & {
91
+ from?: Address;
92
+ to?: Address;
93
+ }) => Promise<TOutput>;
94
+ /**
95
+ * Get gate status for orchestrator queries
96
+ * @param gate - Gate instance (if initialized)
97
+ * @returns Gate status output
98
+ */
99
+ export declare function getGateStatus(gate?: IOpenClawGate): GateStatusOutput | null;
100
+ export { OpenClawGate };
101
+ export type { GateConfig, GateStatusOutput, SkillStartupResult };
102
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAa,MAAM,MAAM,CAAC;AAC/C,OAAO,EAEL,cAAc,EAIf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EAChB,YAAY,IAAI,aAAa,EAC7B,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAwBpB;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,UAAU,CAIxE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAaxE;AAMD;;GAEG;AACH,cAAM,YAAa,YAAW,aAAa;IACzC,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,MAAM,CAAY;gBAEd,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU;IAsBpD;;;;OAIG;IACG,YAAY,CAAC,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAI5D;;;;OAIG;IACG,YAAY,CAAC,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAIzD;;OAEG;YACW,YAAY;IA+D1B;;OAEG;IACH,SAAS,IAAI,iBAAiB;IAI9B;;OAEG;IACH,QAAQ,IAAI,SAAS;IAIrB;;OAEG;IACH,eAAe,IAAI,gBAAgB;CAepC;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAsK1E;AAMD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,OAAO,EACtC,MAAM,EAAE,CAAC,GAAG,EAAE;IAAE,IAAI,CAAC,EAAE,aAAa,CAAA;CAAE,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAC1E,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,IAEtD,KAAK;IAAE,IAAI,CAAC,EAAE,aAAa,CAAA;CAAE,EAAE,OAAO,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAA;CAAE,KAAG,OAAO,CAAC,OAAO,CAAC,CAgBjH;AAMD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,gBAAgB,GAAG,IAAI,CA2B3E;AAMD,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC"}