@absol-labs/agent 0.1.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/LICENSE +21 -0
- package/README.md +196 -0
- package/dist/discovery/registry.d.ts +68 -0
- package/dist/discovery/registry.d.ts.map +1 -0
- package/dist/discovery/registry.js +148 -0
- package/dist/discovery/registry.js.map +1 -0
- package/dist/frameworks/agentkit.d.ts +158 -0
- package/dist/frameworks/agentkit.d.ts.map +1 -0
- package/dist/frameworks/agentkit.js +339 -0
- package/dist/frameworks/agentkit.js.map +1 -0
- package/dist/frameworks/crewai.d.ts +19 -0
- package/dist/frameworks/crewai.d.ts.map +1 -0
- package/dist/frameworks/crewai.js +73 -0
- package/dist/frameworks/crewai.js.map +1 -0
- package/dist/frameworks/eliza.d.ts +393 -0
- package/dist/frameworks/eliza.d.ts.map +1 -0
- package/dist/frameworks/eliza.js +542 -0
- package/dist/frameworks/eliza.js.map +1 -0
- package/dist/frameworks/langchain.d.ts +31 -0
- package/dist/frameworks/langchain.d.ts.map +1 -0
- package/dist/frameworks/langchain.js +206 -0
- package/dist/frameworks/langchain.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/mandates/env.d.ts +51 -0
- package/dist/mandates/env.d.ts.map +1 -0
- package/dist/mandates/env.js +148 -0
- package/dist/mandates/env.js.map +1 -0
- package/dist/mandates/mandate.d.ts +214 -0
- package/dist/mandates/mandate.d.ts.map +1 -0
- package/dist/mandates/mandate.js +172 -0
- package/dist/mandates/mandate.js.map +1 -0
- package/dist/mcp/http-server.d.ts +2 -0
- package/dist/mcp/http-server.d.ts.map +1 -0
- package/dist/mcp/http-server.js +32 -0
- package/dist/mcp/http-server.js.map +1 -0
- package/dist/mcp/http.d.ts +114 -0
- package/dist/mcp/http.d.ts.map +1 -0
- package/dist/mcp/http.js +428 -0
- package/dist/mcp/http.js.map +1 -0
- package/dist/mcp/server.d.ts +119 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +679 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/stdio.d.ts +2 -0
- package/dist/mcp/stdio.d.ts.map +1 -0
- package/dist/mcp/stdio.js +6 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/sdk/client.d.ts +78 -0
- package/dist/sdk/client.d.ts.map +1 -0
- package/dist/sdk/client.js +99 -0
- package/dist/sdk/client.js.map +1 -0
- package/dist/wallet/provider.d.ts +51 -0
- package/dist/wallet/provider.d.ts.map +1 -0
- package/dist/wallet/provider.js +107 -0
- package/dist/wallet/provider.js.map +1 -0
- package/dist/x402/facilitator.d.ts +315 -0
- package/dist/x402/facilitator.d.ts.map +1 -0
- package/dist/x402/facilitator.js +194 -0
- package/dist/x402/facilitator.js.map +1 -0
- package/dist/zktls/reclaim.d.ts +137 -0
- package/dist/zktls/reclaim.d.ts.map +1 -0
- package/dist/zktls/reclaim.js +245 -0
- package/dist/zktls/reclaim.js.map +1 -0
- package/package.json +86 -0
- package/src/discovery/registry.ts +255 -0
- package/src/frameworks/agentkit.ts +537 -0
- package/src/frameworks/crewai.ts +102 -0
- package/src/frameworks/eliza.ts +776 -0
- package/src/frameworks/langchain.ts +325 -0
- package/src/index.ts +179 -0
- package/src/mandates/env.ts +222 -0
- package/src/mandates/mandate.ts +280 -0
- package/src/mcp/http-server.ts +38 -0
- package/src/mcp/http.ts +620 -0
- package/src/mcp/server.ts +1006 -0
- package/src/mcp/stdio.ts +8 -0
- package/src/sdk/client.ts +222 -0
- package/src/wallet/provider.ts +197 -0
- package/src/x402/facilitator.ts +336 -0
- package/src/zktls/reclaim.ts +424 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Absol Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# @absol-labs/agent
|
|
2
|
+
|
|
3
|
+
The **Metrik agent layer** — how AI agents hire and pay for verified services through
|
|
4
|
+
Metrik, safely. This is the **go-to-market wedge** and the investor headline:
|
|
5
|
+
_verified, per-second, conditional payments for autonomous agents, built on x402._
|
|
6
|
+
The layer is operator/infra-agnostic by design: _"x402 proves the payment, Metrik
|
|
7
|
+
proves the delivery."_
|
|
8
|
+
|
|
9
|
+
Built on [`@absol-labs/sdk`](https://github.com/Absol-Labs/streamproof-sdk); it turns
|
|
10
|
+
the protocol into something an agent can actually use.
|
|
11
|
+
|
|
12
|
+
> **New here?** [`docs/quickstart.md`](./docs/quickstart.md) — hire a verified,
|
|
13
|
+
> auto-refunding service in under 10 minutes (install → wallet → mandate → hire →
|
|
14
|
+
> monitor → settle), with copy-pasteable examples for all four integration surfaces.
|
|
15
|
+
|
|
16
|
+
> **Why agents are the wedge** + the full agent journey:
|
|
17
|
+
> [`product-strategy.md`](https://github.com/Absol-Labs/streamproof-protocol/blob/main/docs/product-strategy.md)
|
|
18
|
+
> and [`production-flow.md`](https://github.com/Absol-Labs/streamproof-protocol/blob/main/docs/production-flow.md)
|
|
19
|
+
> (Journey 2 — Atlas). The agent's own zkTLS delivery proof is **L4** in
|
|
20
|
+
> [`verification-model.md`](https://github.com/Absol-Labs/streamproof-protocol/blob/main/docs/verification-model.md).
|
|
21
|
+
> The explicit agent-layer security review lives in
|
|
22
|
+
> [docs/threat-model.md](./docs/threat-model.md).
|
|
23
|
+
|
|
24
|
+
## What's here
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
src/
|
|
28
|
+
mandates/ spend mandates — per-stream/total/rate/duration caps + operator
|
|
29
|
+
allowlists. The "agents can't run away with the wallet" guarantee.
|
|
30
|
+
sdk/ mandate-gated wrapper over @absol-labs/sdk for open/status/claim/reclaim.
|
|
31
|
+
x402/ Metrik as an x402 verified-streaming payment scheme / facilitator.
|
|
32
|
+
mcp/ an MCP server exposing hire/monitor/reclaim as agent tools.
|
|
33
|
+
docs/
|
|
34
|
+
quickstart.md zero → hired verified service in <10 min (start here).
|
|
35
|
+
agent-layer.md the product design + investor narrative.
|
|
36
|
+
crewai.md CrewAI's official MCP integration path for Metrik tools.
|
|
37
|
+
eliza.md ElizaOS plugin/actions for hire/status/reclaim.
|
|
38
|
+
threat-model.md the explicit autonomous-spend / key-custody review.
|
|
39
|
+
langchain.md the LangChain tool adapter and example loop.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## The four pieces
|
|
43
|
+
|
|
44
|
+
1. **x402 integration** — an agent hits a `402`, gets back a _verified-streaming_
|
|
45
|
+
payment requirement, and opens a stream instead of a one-shot payment. Reuses
|
|
46
|
+
the `402` negotiation surface and opens the on-chain stream through the SDK.
|
|
47
|
+
2. **MCP server** — exposes "hire verified compute / get status / reclaim" as MCP
|
|
48
|
+
tools so any MCP agent (Claude, etc.) transacts natively. When Reclaim creds are
|
|
49
|
+
configured, it also exposes `prove_https_response` for public-response zkTLS proofs
|
|
50
|
+
tied to a tracked stream.
|
|
51
|
+
3. **Framework tools** — LangChain, ElizaOS, and CrewAI now sit on top of the same
|
|
52
|
+
mandate-gated client. CrewAI consumes the existing MCP lane via its official MCP
|
|
53
|
+
integration; ElizaOS gets a direct plugin/action surface.
|
|
54
|
+
4. **Spend mandates** — owner-signed EIP-712 budget/intent guardrails (AP2-style):
|
|
55
|
+
caps and allowlists enforced before any fund-moving action, with expiry and
|
|
56
|
+
local revocation checks.
|
|
57
|
+
5. **zkTLS delivery proofs (L4)** — the agent can now produce a Reclaim-backed proof
|
|
58
|
+
of the exact HTTPS response it consumed, bound to buyer/stream context and intended
|
|
59
|
+
to complement, not replace, oracle L1 evidence.
|
|
60
|
+
|
|
61
|
+
Current real chain surface:
|
|
62
|
+
|
|
63
|
+
- `VerifiedStreamAgentClient` wraps `@absol-labs/sdk` for `open`, `status`, `claim`,
|
|
64
|
+
`close`, and `reclaim`.
|
|
65
|
+
- All autonomous fund-moving helpers (`openVerifiedStream()`, `claimStream()`,
|
|
66
|
+
`closeStream()`, `reclaimStream()`) enforce signed-mandate verification first and
|
|
67
|
+
hard-stop on denial.
|
|
68
|
+
- `VerifiedStreamX402Facilitator` turns an HTTP `402` challenge into a real verified
|
|
69
|
+
stream open on Base Sepolia.
|
|
70
|
+
- `createVerifiedStreamMcpServer()` exposes real MCP tools for `hire_verified_service`,
|
|
71
|
+
`check_stream_status`, `reclaim_unspent`, and `list_streams`.
|
|
72
|
+
- `ReclaimConsumerProofService` generates a verifiable zkTLS proof of a consumed HTTPS
|
|
73
|
+
response, hashing the exact request/match/redaction policy before local verification.
|
|
74
|
+
- `VerifiedStreamX402Facilitator.proveConsumedHttpsResponse()` binds that proof to the
|
|
75
|
+
same buyer/mandate context that opened the stream.
|
|
76
|
+
- If Reclaim env vars are configured, `createVerifiedStreamMcpServer()` also exposes
|
|
77
|
+
`prove_https_response` for tracked streams. The MCP tool intentionally excludes secret
|
|
78
|
+
headers/cookies so credentials do not pass through model-visible tool arguments.
|
|
79
|
+
- `createLangChainVerifiedStreamTools()` exposes the same hire/status/reclaim flow as
|
|
80
|
+
LangChain tools, including a `shouldStop` status signal for paused streams.
|
|
81
|
+
- `createMetrikElizaPlugin()` (alias `metrikElizaPlugin`) exposes the hire/status/reclaim/close
|
|
82
|
+
flow as an ElizaOS plugin — canonical `HIRE_VERIFIED_SERVICE`, `CHECK_STREAM_STATUS`,
|
|
83
|
+
`RECLAIM_UNSPENT`, and `CLOSE_STREAM` actions with structured results and fail-closed
|
|
84
|
+
payload parsing. See [`examples/metrik-character.ts`](examples/metrik-character.ts).
|
|
85
|
+
- `createCrewAiVerifiedStreamMcpConfig()` emits a CrewAI `MCPServerStdio` config for
|
|
86
|
+
the existing mandate-gated MCP server, with a tool filter limited to verified-stream
|
|
87
|
+
operations.
|
|
88
|
+
- `resolveAgentWallet()` accepts either an injected viem signer or a provisioned
|
|
89
|
+
Coinbase CDP Server Wallet v2 account, then feeds that signer into the existing
|
|
90
|
+
agent/SDK path without ever exporting a private key.
|
|
91
|
+
- Model A is infra-agnostic: a stream targets a seller payout wallet + `serviceRef`
|
|
92
|
+
only (no service-network field). Settlement is single-chain on Base Sepolia.
|
|
93
|
+
|
|
94
|
+
## Wallet modes
|
|
95
|
+
|
|
96
|
+
The agent layer now supports two wallet sources:
|
|
97
|
+
|
|
98
|
+
- injected viem account via `METRIK_AGENT_PRIVATE_KEY`
|
|
99
|
+
- Coinbase CDP Server Wallet v2 via `CDP_API_KEY_ID`, `CDP_API_KEY_SECRET`,
|
|
100
|
+
`CDP_WALLET_SECRET`, and `METRIK_AGENT_CDP_OWNER_NAME`
|
|
101
|
+
|
|
102
|
+
CDP mode uses Coinbase-managed remote signing. Metrik never reads or exports the
|
|
103
|
+
wallet private key. If `METRIK_AGENT_CDP_CREATE_SMART_ACCOUNT=true`, the agent also
|
|
104
|
+
provisions a per-agent ERC-4337 smart account owned by that CDP wallet for the later
|
|
105
|
+
gas-abstraction path.
|
|
106
|
+
|
|
107
|
+
## MCP server
|
|
108
|
+
|
|
109
|
+
The MCP server runs over stdio and reads its settlement config from env. It never
|
|
110
|
+
asks for a raw key in a tool argument.
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
cp .env.example .env
|
|
114
|
+
pnpm mcp:stdio
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Env surface:
|
|
118
|
+
|
|
119
|
+
- `METRIK_AGENT_RPC_URL`
|
|
120
|
+
- `METRIK_AGENT_ESCROW`
|
|
121
|
+
- `METRIK_AGENT_USDC`
|
|
122
|
+
- `METRIK_AGENT_PRIVATE_KEY` (optional injected signer mode)
|
|
123
|
+
- `CDP_API_KEY_ID`
|
|
124
|
+
- `CDP_API_KEY_SECRET`
|
|
125
|
+
- `CDP_WALLET_SECRET`
|
|
126
|
+
- `METRIK_AGENT_CDP_OWNER_NAME`
|
|
127
|
+
- `METRIK_AGENT_CDP_SMART_ACCOUNT_NAME`
|
|
128
|
+
- `METRIK_AGENT_CDP_CREATE_SMART_ACCOUNT`
|
|
129
|
+
- `METRIK_AGENT_CHAIN_ID` (`84532` in Phase 2)
|
|
130
|
+
- `METRIK_AGENT_CHAIN_NAME`
|
|
131
|
+
- `METRIK_AGENT_MCP_STATE_FILE` (optional JSON registry for `list_streams`)
|
|
132
|
+
- `RECLAIM_APP_ID` (optional, enables zkTLS proof generation)
|
|
133
|
+
- `RECLAIM_APP_SECRET` (optional, enables zkTLS proof generation)
|
|
134
|
+
- `METRIK_AGENT_RECLAIM_LOGS` (optional, defaults to `false`)
|
|
135
|
+
|
|
136
|
+
## zkTLS / Reclaim (L4)
|
|
137
|
+
|
|
138
|
+
Use the programmatic proof service or the x402 facilitator when the consumed request
|
|
139
|
+
needs private headers/cookies. Use the MCP tool only for public request inputs; it
|
|
140
|
+
looks up stream context locally and avoids sending secrets through the model/tool layer.
|
|
141
|
+
|
|
142
|
+
Every proof is verified locally against the exact URL/method/body/match/redaction
|
|
143
|
+
policy the agent declared. This is an **L4 delivery signal** only: the verifier should
|
|
144
|
+
cross-check it with L1/oracle observations before any settlement decision.
|
|
145
|
+
|
|
146
|
+
## End-to-end journey (hire -> stream -> settle)
|
|
147
|
+
|
|
148
|
+
The whole loop is proven end to end against a local node in
|
|
149
|
+
[`test/e2e.int.test.ts`](test/e2e.int.test.ts) and scripted for integrators in
|
|
150
|
+
[`examples/hire-stream-settle.ts`](examples/hire-stream-settle.ts):
|
|
151
|
+
|
|
152
|
+
1. **Wallet** — a non-custodial injected-key viem account (credential-free; swap
|
|
153
|
+
in a Coinbase CDP wallet via `createWalletBackedAgentClient({ cdp: ... })`).
|
|
154
|
+
2. **Mandate** — the owner signs an EIP-712 spend mandate (caps + operator
|
|
155
|
+
allowlist); every buyer-side fund move is mandate-gated and fail-closed.
|
|
156
|
+
3. **Hire** — the x402 facilitator turns a `402` challenge into an escrowed
|
|
157
|
+
`openStream` on the hardened `StreamEscrow`.
|
|
158
|
+
4. **Verify** — an M-of-N oracle quorum submits real EIP-712 `Delivered`
|
|
159
|
+
attestations; USDC accrues only for verified seconds (`checkedAt <=
|
|
160
|
+
block.timestamp` is enforced on-chain).
|
|
161
|
+
5. **Settle** — the operator claims its earned USDC net of the protocol fee, the
|
|
162
|
+
buyer closes and reclaims the unspent balance, a terminal `SlaReceiptIssued`
|
|
163
|
+
event is emitted, and every cent conserves exactly.
|
|
164
|
+
|
|
165
|
+
The test also covers the **failure branch**: two failed checks auto-pause the
|
|
166
|
+
stream, the buyer reclaims, and the operator can still claim only what it earned
|
|
167
|
+
before the outage — buyer-favouring by construction.
|
|
168
|
+
|
|
169
|
+
Run the example (needs Foundry `anvil`):
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
anvil --silent &
|
|
173
|
+
pnpm tsx examples/hire-stream-settle.ts
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
> The SLA receipt carries the raw material for on-chain reputation
|
|
177
|
+
> (`verifiedSeconds`, `accrued`, `finalStatus`, `consecutiveFailures`). Feeding it
|
|
178
|
+
> into `@absol-labs/shared`'s `slaReceiptRecordFromEvent` + `aggregateReputation`
|
|
179
|
+
> (protocol#38) is a one-liner once the installed `@absol-labs/shared` is bumped to
|
|
180
|
+
> the version that exports them (the pinned `0.3.0` does not yet).
|
|
181
|
+
|
|
182
|
+
## Develop
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
corepack enable && corepack prepare pnpm@9.15.0 --activate
|
|
186
|
+
pnpm install
|
|
187
|
+
pnpm typecheck
|
|
188
|
+
pnpm test
|
|
189
|
+
pnpm build
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
> The x402 facilitator, zkTLS proof path, signed-mandate engine, MCP server, and
|
|
193
|
+
> framework adapters are all real and tested in-repo. The `*.int.test.ts`
|
|
194
|
+
> integration suites deploy the hardened `StreamEscrow` on a throwaway `anvil`
|
|
195
|
+
> node and self-skip cleanly when `anvil` is not on `PATH`, so default CI stays
|
|
196
|
+
> green.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service discovery for the Metrik verified-service marketplace.
|
|
3
|
+
*
|
|
4
|
+
* Before this module every agent surface (SDK, MCP, framework tools) assumed the
|
|
5
|
+
* caller already knew a seller's `operator` + `serviceRef`. There was no way to
|
|
6
|
+
* DISCOVER a service. {@link discoverServices} closes that gap: it reads the same
|
|
7
|
+
* Supabase `listings` registry the oracle reads and returns typed, VERIFIED
|
|
8
|
+
* listings an agent can hire directly.
|
|
9
|
+
*
|
|
10
|
+
* ## Fail-closed trust model
|
|
11
|
+
* The security-critical envelope lives entirely inside each row's `signed_binding`
|
|
12
|
+
* (`{ binding, signature, serviceRef, targetMetadata }`). The flat `service_ref` /
|
|
13
|
+
* `operator` / `public_url` columns are UNSIGNED denormalised copies for querying
|
|
14
|
+
* only — never trusted. A row is DROPPED (and logged) unless BOTH hold:
|
|
15
|
+
* 1. its EIP-712 signature recovers to `binding.operator`; and
|
|
16
|
+
* 2. `deriveServiceRef(binding)` equals the envelope's own `serviceRef`.
|
|
17
|
+
* `discoverServices` therefore NEVER returns an unverifiable listing.
|
|
18
|
+
*
|
|
19
|
+
* The unsigned `category` column is carried through as informational metadata only
|
|
20
|
+
* (used for the optional client-side category filter); it is never part of the
|
|
21
|
+
* trust decision.
|
|
22
|
+
*/
|
|
23
|
+
/** A verified, hireable service listing. `serviceRef`/`operator`/`publicUrl` are
|
|
24
|
+
* derived from the SIGNED binding, not the unsigned flat columns. */
|
|
25
|
+
export interface ServiceListing {
|
|
26
|
+
readonly serviceRef: `0x${string}`;
|
|
27
|
+
readonly operator: `0x${string}`;
|
|
28
|
+
readonly publicUrl: string;
|
|
29
|
+
/** Unsigned informational category from the listings row (may be absent). */
|
|
30
|
+
readonly category: string | null;
|
|
31
|
+
/** Optional signed operator-supplied target metadata (e.g. resolver hints). */
|
|
32
|
+
readonly targetMetadata?: Record<string, string>;
|
|
33
|
+
}
|
|
34
|
+
export interface DiscoverServicesOptions {
|
|
35
|
+
/** Registry endpoint. Defaults to {@link DEFAULT_METRIK_REGISTRY_URL} (env override:
|
|
36
|
+
* `METRIK_AGENT_REGISTRY_URL`). Pass the full PostgREST `?select=...&order=...` URL. */
|
|
37
|
+
readonly registryUrl?: string;
|
|
38
|
+
/** PostgREST apikey (Supabase anon key). Env override: `METRIK_AGENT_REGISTRY_APIKEY`.
|
|
39
|
+
* Sent as both the `apikey` header and `Authorization: Bearer`. */
|
|
40
|
+
readonly apiKey?: string;
|
|
41
|
+
/** Optional client-side filter on the unsigned `category` column. */
|
|
42
|
+
readonly category?: string;
|
|
43
|
+
/** Optional cap on the number of verified listings returned. */
|
|
44
|
+
readonly limit?: number;
|
|
45
|
+
/** Injected fetch (tests / custom transports). Defaults to `globalThis.fetch`. */
|
|
46
|
+
readonly fetch?: typeof fetch;
|
|
47
|
+
/** Request timeout in milliseconds. Defaults to 5000. */
|
|
48
|
+
readonly timeoutMs?: number;
|
|
49
|
+
/** Warning sink for dropped rows / registry failures. Defaults to `console`. */
|
|
50
|
+
readonly logger?: {
|
|
51
|
+
warn: (...args: unknown[]) => void;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Default Metrik listings registry (Supabase PostgREST). Selects the columns the
|
|
56
|
+
* oracle and the agent both need and orders newest-first.
|
|
57
|
+
*/
|
|
58
|
+
export declare const DEFAULT_METRIK_REGISTRY_URL = "https://pzvnacjolaipeobmptsb.supabase.co/rest/v1/listings?select=service_ref,operator,public_url,category,signed_binding&order=created_at.desc";
|
|
59
|
+
/**
|
|
60
|
+
* Discover verified services from the Metrik listings registry.
|
|
61
|
+
*
|
|
62
|
+
* Fail-closed: any row whose signed binding is malformed, whose signature does not
|
|
63
|
+
* recover to its operator, or whose `serviceRef` does not match `deriveServiceRef`
|
|
64
|
+
* is dropped and logged. Degrades gracefully: any network/registry failure returns
|
|
65
|
+
* `[]` (with a logged warning) rather than throwing to the caller.
|
|
66
|
+
*/
|
|
67
|
+
export declare function discoverServices(opts?: DiscoverServicesOptions): Promise<ServiceListing[]>;
|
|
68
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/discovery/registry.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;qEACqE;AACrE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,KAAK,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,uBAAuB;IACtC;4FACwF;IACxF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;uEACmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;KAAE,CAAC;CAC1D;AAED;;;GAGG;AACH,eAAO,MAAM,2BAA2B,mJAC0G,CAAC;AAoCnJ;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,cAAc,EAAE,CAAC,CA4C3B"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { deriveServiceRef, recoverServiceBindingSigner, serviceBindingSchema, } from "@absol-labs/shared";
|
|
2
|
+
import { isHex } from "viem";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
/**
|
|
5
|
+
* Default Metrik listings registry (Supabase PostgREST). Selects the columns the
|
|
6
|
+
* oracle and the agent both need and orders newest-first.
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_METRIK_REGISTRY_URL = "https://pzvnacjolaipeobmptsb.supabase.co/rest/v1/listings?select=service_ref,operator,public_url,category,signed_binding&order=created_at.desc";
|
|
9
|
+
const DEFAULT_TIMEOUT_MS = 5_000;
|
|
10
|
+
const signature65HexSchema = z
|
|
11
|
+
.string()
|
|
12
|
+
.refine((value) => isHex(value, { strict: true }) && value.length === 132, "must be a 65-byte hex signature");
|
|
13
|
+
const bytes32HexSchema = z
|
|
14
|
+
.string()
|
|
15
|
+
.refine((value) => isHex(value, { strict: true }) && value.length === 66, "must be bytes32 hex");
|
|
16
|
+
/** The signed envelope inside a listings row. Mirrors the oracle's ingest schema
|
|
17
|
+
* (includes the optional operator-supplied `targetMetadata`). */
|
|
18
|
+
const signedBindingRecordSchema = z.object({
|
|
19
|
+
serviceRef: bytes32HexSchema,
|
|
20
|
+
binding: serviceBindingSchema,
|
|
21
|
+
signature: signature65HexSchema,
|
|
22
|
+
targetMetadata: z.record(z.string()).optional(),
|
|
23
|
+
});
|
|
24
|
+
/** A Supabase `listings` row. Only `signed_binding` is trusted; `category` is
|
|
25
|
+
* carried through as unsigned informational metadata. Unknown columns are ignored. */
|
|
26
|
+
const listingRowSchema = z
|
|
27
|
+
.object({
|
|
28
|
+
category: z.string().nullish(),
|
|
29
|
+
signed_binding: signedBindingRecordSchema,
|
|
30
|
+
})
|
|
31
|
+
.passthrough();
|
|
32
|
+
/**
|
|
33
|
+
* Discover verified services from the Metrik listings registry.
|
|
34
|
+
*
|
|
35
|
+
* Fail-closed: any row whose signed binding is malformed, whose signature does not
|
|
36
|
+
* recover to its operator, or whose `serviceRef` does not match `deriveServiceRef`
|
|
37
|
+
* is dropped and logged. Degrades gracefully: any network/registry failure returns
|
|
38
|
+
* `[]` (with a logged warning) rather than throwing to the caller.
|
|
39
|
+
*/
|
|
40
|
+
export async function discoverServices(opts = {}) {
|
|
41
|
+
const logger = opts.logger ?? console;
|
|
42
|
+
const registryUrl = opts.registryUrl ??
|
|
43
|
+
process.env.METRIK_AGENT_REGISTRY_URL ??
|
|
44
|
+
DEFAULT_METRIK_REGISTRY_URL;
|
|
45
|
+
const apiKey = opts.apiKey ?? process.env.METRIK_AGENT_REGISTRY_APIKEY;
|
|
46
|
+
const fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
47
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
48
|
+
if (typeof fetchImpl !== "function") {
|
|
49
|
+
logger.warn("metrik discovery: no fetch implementation available; returning no listings");
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
let rows;
|
|
53
|
+
try {
|
|
54
|
+
rows = await fetchListingRows(fetchImpl, registryUrl, apiKey, timeoutMs);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
// Fail-safe / buyer-favouring: a down or unreachable registry must never throw
|
|
58
|
+
// into the agent's hire flow — it degrades to "no services discovered".
|
|
59
|
+
logger.warn(`metrik discovery: listings registry unreachable (${errorMessage(error)}); returning no listings`);
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
const listings = [];
|
|
63
|
+
for (const [index, row] of rows.entries()) {
|
|
64
|
+
const listing = await verifyRow(row, index, logger);
|
|
65
|
+
if (listing === null) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (opts.category !== undefined && listing.category !== opts.category) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
listings.push(listing);
|
|
72
|
+
if (opts.limit !== undefined && listings.length >= opts.limit) {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return listings;
|
|
77
|
+
}
|
|
78
|
+
async function fetchListingRows(fetchImpl, url, apiKey, timeoutMs) {
|
|
79
|
+
const controller = new AbortController();
|
|
80
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
81
|
+
try {
|
|
82
|
+
const headers = {};
|
|
83
|
+
if (apiKey !== undefined && apiKey.length > 0) {
|
|
84
|
+
headers.apikey = apiKey;
|
|
85
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
86
|
+
}
|
|
87
|
+
const response = await fetchImpl(url, {
|
|
88
|
+
signal: controller.signal,
|
|
89
|
+
...(Object.keys(headers).length === 0 ? {} : { headers }),
|
|
90
|
+
});
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
throw new Error(`listings registry responded with status ${response.status}`);
|
|
93
|
+
}
|
|
94
|
+
const body = await response.json();
|
|
95
|
+
if (!Array.isArray(body)) {
|
|
96
|
+
throw new Error("listings registry response was not a JSON array");
|
|
97
|
+
}
|
|
98
|
+
return body;
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
clearTimeout(timeout);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Verify one raw registry row into a {@link ServiceListing}, or `null` if it fails
|
|
106
|
+
* the fail-closed checks. Never throws.
|
|
107
|
+
*/
|
|
108
|
+
async function verifyRow(row, index, logger) {
|
|
109
|
+
const parsed = listingRowSchema.safeParse(row);
|
|
110
|
+
if (!parsed.success) {
|
|
111
|
+
logger.warn(`metrik discovery: row ${index} dropped — invalid listing envelope (${parsed.error.issues[0]?.message ?? "schema error"})`);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const { signed_binding: record, category } = parsed.data;
|
|
115
|
+
let signer;
|
|
116
|
+
try {
|
|
117
|
+
signer = (await recoverServiceBindingSigner(record.binding, record.signature));
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
logger.warn(`metrik discovery: row ${index} dropped — signature recovery threw (${errorMessage(error)})`);
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
if (signer === null || !eqHex(signer, record.binding.operator)) {
|
|
124
|
+
logger.warn(`metrik discovery: row ${index} dropped — signature does not recover to operator (recovered ${signer ?? "null"})`);
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const derivedRef = deriveServiceRef(record.binding);
|
|
128
|
+
if (!eqHex(derivedRef, record.serviceRef)) {
|
|
129
|
+
logger.warn(`metrik discovery: row ${index} dropped — serviceRef ${record.serviceRef} does not match derived ${derivedRef}`);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
serviceRef: derivedRef,
|
|
134
|
+
operator: record.binding.operator,
|
|
135
|
+
publicUrl: record.binding.publicUrl,
|
|
136
|
+
category: category ?? null,
|
|
137
|
+
...(record.targetMetadata === undefined
|
|
138
|
+
? {}
|
|
139
|
+
: { targetMetadata: record.targetMetadata }),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function eqHex(a, b) {
|
|
143
|
+
return a.toLowerCase() === b.toLowerCase();
|
|
144
|
+
}
|
|
145
|
+
function errorMessage(error) {
|
|
146
|
+
return error instanceof Error ? error.message : String(error);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/discovery/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import type { HireComputeResult, StreamProofClientConfig } from "@absol-labs/sdk";
|
|
3
|
+
import { ActionProvider, WalletProvider, type Network } from "@coinbase/agentkit";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { type DiscoverServicesOptions, type ServiceListing } from "../discovery/registry.js";
|
|
6
|
+
import { type SignedSpendMandate } from "../mandates/mandate.js";
|
|
7
|
+
import { type AgentSdkClientFactory, type MandateAuthorizedStreamActionInput, type OpenVerifiedStreamInput, type ReclaimAuthorizedStreamInput, type ReclaimVerifiedStreamResult, type StreamProofTransactionResult, type StreamStatusView } from "../sdk/client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Base Sepolia is the only settlement network Metrik supports today (Model A,
|
|
10
|
+
* single-chain USDC on Base). Every action fails closed on any other network.
|
|
11
|
+
*/
|
|
12
|
+
export declare const METRIK_BASE_SEPOLIA_CHAIN_ID = 84532;
|
|
13
|
+
export declare const discoverServicesSchema: z.ZodObject<{
|
|
14
|
+
category: z.ZodOptional<z.ZodString>;
|
|
15
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
16
|
+
}, "strip", z.ZodTypeAny, {
|
|
17
|
+
category?: string | undefined;
|
|
18
|
+
limit?: number | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
category?: string | undefined;
|
|
21
|
+
limit?: number | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export declare const hireVerifiedServiceSchema: z.ZodObject<{
|
|
24
|
+
operator: z.ZodEffects<z.ZodString, `0x${string}`, string>;
|
|
25
|
+
serviceRef: z.ZodEffects<z.ZodString, string, string>;
|
|
26
|
+
budgetUsdc: z.ZodEffects<z.ZodString, string, unknown>;
|
|
27
|
+
ratePerSecondUsdc: z.ZodEffects<z.ZodString, string, unknown>;
|
|
28
|
+
durationSeconds: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
publicUrl: z.ZodOptional<z.ZodString>;
|
|
30
|
+
}, "strip", z.ZodTypeAny, {
|
|
31
|
+
operator: `0x${string}`;
|
|
32
|
+
serviceRef: string;
|
|
33
|
+
ratePerSecondUsdc: string;
|
|
34
|
+
budgetUsdc: string;
|
|
35
|
+
publicUrl?: string | undefined;
|
|
36
|
+
durationSeconds?: number | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
operator: string;
|
|
39
|
+
serviceRef: string;
|
|
40
|
+
ratePerSecondUsdc?: unknown;
|
|
41
|
+
publicUrl?: string | undefined;
|
|
42
|
+
budgetUsdc?: unknown;
|
|
43
|
+
durationSeconds?: number | undefined;
|
|
44
|
+
}>;
|
|
45
|
+
export declare const checkStreamStatusSchema: z.ZodObject<{
|
|
46
|
+
streamId: z.ZodEffects<z.ZodString, string, string>;
|
|
47
|
+
}, "strip", z.ZodTypeAny, {
|
|
48
|
+
streamId: string;
|
|
49
|
+
}, {
|
|
50
|
+
streamId: string;
|
|
51
|
+
}>;
|
|
52
|
+
export declare const reclaimUnspentSchema: z.ZodObject<{
|
|
53
|
+
streamId: z.ZodEffects<z.ZodString, string, string>;
|
|
54
|
+
closeFirst: z.ZodOptional<z.ZodBoolean>;
|
|
55
|
+
}, "strip", z.ZodTypeAny, {
|
|
56
|
+
streamId: string;
|
|
57
|
+
closeFirst?: boolean | undefined;
|
|
58
|
+
}, {
|
|
59
|
+
streamId: string;
|
|
60
|
+
closeFirst?: boolean | undefined;
|
|
61
|
+
}>;
|
|
62
|
+
export declare const closeStreamSchema: z.ZodObject<{
|
|
63
|
+
streamId: z.ZodEffects<z.ZodString, string, string>;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
streamId: string;
|
|
66
|
+
}, {
|
|
67
|
+
streamId: string;
|
|
68
|
+
}>;
|
|
69
|
+
/**
|
|
70
|
+
* Resolves the mutable, per-owner mandate accounting the guard needs: how much
|
|
71
|
+
* of the total cap has already been spent, and which mandate ids are revoked.
|
|
72
|
+
*/
|
|
73
|
+
export interface MetrikMandateStateResolver {
|
|
74
|
+
getSpentSoFarUsdc(owner: `0x${string}`): Promise<bigint>;
|
|
75
|
+
getRevokedMandateIds(owner: `0x${string}`): Promise<readonly `0x${string}`[]>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The subset of the Metrik SDK the action provider drives. `VerifiedStreamAgentClient`
|
|
79
|
+
* satisfies this structurally; tests inject a lightweight double so the provider
|
|
80
|
+
* is exercisable with no CDP creds and no RPC.
|
|
81
|
+
*/
|
|
82
|
+
export interface MetrikAgentKitClient {
|
|
83
|
+
openVerifiedStream(input: OpenVerifiedStreamInput): Promise<HireComputeResult>;
|
|
84
|
+
getStreamStatus(streamId: `0x${string}`): Promise<StreamStatusView>;
|
|
85
|
+
reclaimStream(input: ReclaimAuthorizedStreamInput): Promise<ReclaimVerifiedStreamResult>;
|
|
86
|
+
closeStream(input: MandateAuthorizedStreamActionInput): Promise<StreamProofTransactionResult>;
|
|
87
|
+
}
|
|
88
|
+
export interface MetrikActionProviderConfig {
|
|
89
|
+
/**
|
|
90
|
+
* The owner-signed spend mandate that bounds every hire (per-stream + total
|
|
91
|
+
* budget, rate, duration, allowed operators). Configured once at the
|
|
92
|
+
* agent's construction — the LLM never supplies or edits it.
|
|
93
|
+
*/
|
|
94
|
+
readonly signedMandate: SignedSpendMandate;
|
|
95
|
+
/** Settlement chain id. Defaults to Base Sepolia (84532); any other value fails closed. */
|
|
96
|
+
readonly chainId?: number;
|
|
97
|
+
/** Injected Metrik client (test path). Mutually exclusive with `sdkConfig`. */
|
|
98
|
+
readonly agentClient?: MetrikAgentKitClient;
|
|
99
|
+
/**
|
|
100
|
+
* Metrik SDK config (escrow address, chain, rpc, signing account) used to
|
|
101
|
+
* BUILD a `VerifiedStreamAgentClient` when no `agentClient` is injected. The
|
|
102
|
+
* signing account comes from the CDP wallet in `createMetrikAgentKit`.
|
|
103
|
+
*/
|
|
104
|
+
readonly sdkConfig?: StreamProofClientConfig;
|
|
105
|
+
/** Optional SDK client factory override, forwarded to the built client. */
|
|
106
|
+
readonly createSdkClient?: AgentSdkClientFactory;
|
|
107
|
+
/** Mandate accounting source. Defaults to fresh state (0 spent, none revoked). */
|
|
108
|
+
readonly mandateStateResolver?: Partial<MetrikMandateStateResolver>;
|
|
109
|
+
/** Clock injection for deterministic tests. Defaults to wall-clock seconds. */
|
|
110
|
+
readonly now?: () => number;
|
|
111
|
+
/**
|
|
112
|
+
* Discovery driver for the `discover_services` action. Defaults to the live
|
|
113
|
+
* registry-backed `discoverServices`; tests inject a double.
|
|
114
|
+
*/
|
|
115
|
+
readonly discoverServices?: (opts?: DiscoverServicesOptions) => Promise<ServiceListing[]>;
|
|
116
|
+
}
|
|
117
|
+
export declare class MetrikActionProviderConfigError extends Error {
|
|
118
|
+
constructor(message: string);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Coinbase AgentKit action provider that lets any AgentKit-based agent hire and
|
|
122
|
+
* pay third-party services through Metrik's verified USDC escrow. Every action
|
|
123
|
+
* is fail-closed and buyer-favoring; a hire is refused before any transaction if
|
|
124
|
+
* it would breach the configured spend mandate.
|
|
125
|
+
*/
|
|
126
|
+
export declare class MetrikActionProvider extends ActionProvider<WalletProvider> {
|
|
127
|
+
#private;
|
|
128
|
+
constructor(config: MetrikActionProviderConfig);
|
|
129
|
+
discoverServices(_walletProvider: WalletProvider, args: z.infer<typeof discoverServicesSchema>): Promise<string>;
|
|
130
|
+
hireVerifiedService(walletProvider: WalletProvider, args: z.infer<typeof hireVerifiedServiceSchema>): Promise<string>;
|
|
131
|
+
checkStreamStatus(walletProvider: WalletProvider, args: z.infer<typeof checkStreamStatusSchema>): Promise<string>;
|
|
132
|
+
reclaimUnspent(walletProvider: WalletProvider, args: z.infer<typeof reclaimUnspentSchema>): Promise<string>;
|
|
133
|
+
closeStream(walletProvider: WalletProvider, args: z.infer<typeof closeStreamSchema>): Promise<string>;
|
|
134
|
+
supportsNetwork(network: Network): boolean;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Factory mirroring AgentKit's `xxxActionProvider()` convention.
|
|
138
|
+
*/
|
|
139
|
+
export declare function metrikActionProvider(config: MetrikActionProviderConfig): MetrikActionProvider;
|
|
140
|
+
export interface CreateMetrikAgentKitOptions {
|
|
141
|
+
/**
|
|
142
|
+
* A concrete AgentKit wallet provider (e.g. `CdpEvmWalletProvider` or
|
|
143
|
+
* `CdpSmartWalletProvider`) built from the CDP creds. Constructing it reaches
|
|
144
|
+
* CDP and therefore needs live creds at runtime; the action provider itself is
|
|
145
|
+
* independently unit-testable without any creds.
|
|
146
|
+
*/
|
|
147
|
+
readonly walletProvider: WalletProvider;
|
|
148
|
+
readonly metrik: MetrikActionProviderConfig;
|
|
149
|
+
/** Additional AgentKit action providers to compose alongside Metrik. */
|
|
150
|
+
readonly additionalActionProviders?: readonly ActionProvider[];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Convenience that composes Metrik into an AgentKit instance alongside the CDP
|
|
154
|
+
* wallet provider. From the returned `AgentKit` you can expose Metrik natively
|
|
155
|
+
* via `getLangChainTools`, `getVercelAITools`, or the AgentKit MCP server.
|
|
156
|
+
*/
|
|
157
|
+
export declare function createMetrikAgentKit(options: CreateMetrikAgentKitOptions): Promise<import("@coinbase/agentkit").AgentKit>;
|
|
158
|
+
//# sourceMappingURL=agentkit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentkit.d.ts","sourceRoot":"","sources":["../../src/frameworks/agentkit.ts"],"names":[],"mappings":"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"}
|