agentex-creator-sdk 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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/packages/contracts/src/deployer-investigation.d.ts +1015 -0
- package/dist/packages/contracts/src/deployer-investigation.js +101 -0
- package/dist/packages/contracts/src/index.d.ts +1701 -0
- package/dist/packages/contracts/src/index.js +380 -0
- package/dist/packages/contracts/src/indexed-activity.d.ts +684 -0
- package/dist/packages/contracts/src/indexed-activity.js +71 -0
- package/dist/packages/contracts/src/indexed-agents.d.ts +299 -0
- package/dist/packages/contracts/src/indexed-agents.js +131 -0
- package/dist/packages/contracts/src/inspection.d.ts +906 -0
- package/dist/packages/contracts/src/inspection.js +114 -0
- package/dist/packages/contracts/src/kinds.d.ts +5398 -0
- package/dist/packages/contracts/src/kinds.js +156 -0
- package/dist/packages/contracts/src/report-presentation.d.ts +346 -0
- package/dist/packages/contracts/src/report-presentation.js +120 -0
- package/dist/packages/contracts/src/solana-inspection.d.ts +451 -0
- package/dist/packages/contracts/src/solana-inspection.js +94 -0
- package/dist/packages/contracts/src/token-market.d.ts +193 -0
- package/dist/packages/contracts/src/token-market.js +335 -0
- package/dist/packages/contracts/src/wallet-analysis.d.ts +866 -0
- package/dist/packages/contracts/src/wallet-analysis.js +89 -0
- package/dist/packages/contracts/src/watchtower.d.ts +1141 -0
- package/dist/packages/contracts/src/watchtower.js +196 -0
- package/dist/packages/contracts/src/workflow.d.ts +1568 -0
- package/dist/packages/contracts/src/workflow.js +651 -0
- package/dist/packages/inspector/src/decode.d.ts +23 -0
- package/dist/packages/inspector/src/decode.js +150 -0
- package/dist/packages/inspector/src/scope.d.ts +87 -0
- package/dist/packages/inspector/src/scope.js +64 -0
- package/dist/packages/model/src/analysis.d.ts +149 -0
- package/dist/packages/model/src/analysis.js +387 -0
- package/dist/packages/model/src/pricing.d.ts +38 -0
- package/dist/packages/model/src/pricing.js +49 -0
- package/dist/packages/model/src/retry.d.ts +20 -0
- package/dist/packages/model/src/retry.js +31 -0
- package/dist/packages/model/src/schema.d.ts +10 -0
- package/dist/packages/model/src/schema.js +51 -0
- package/dist/packages/model/src/summary.d.ts +91 -0
- package/dist/packages/model/src/summary.js +177 -0
- package/dist/packages/model/src/types.d.ts +81 -0
- package/dist/packages/model/src/types.js +19 -0
- package/dist/packages/monitoring/src/delivery.d.ts +32 -0
- package/dist/packages/monitoring/src/delivery.js +53 -0
- package/dist/packages/providers/src/chain-transport.d.ts +42 -0
- package/dist/packages/providers/src/chain-transport.js +57 -0
- package/dist/packages/providers/src/coverage.d.ts +105 -0
- package/dist/packages/providers/src/coverage.js +260 -0
- package/dist/packages/providers/src/health.d.ts +273 -0
- package/dist/packages/providers/src/health.js +505 -0
- package/dist/packages/providers/src/keyed.d.ts +96 -0
- package/dist/packages/providers/src/keyed.js +240 -0
- package/dist/packages/providers/src/snapshot.d.ts +61 -0
- package/dist/packages/providers/src/snapshot.js +77 -0
- package/dist/packages/publication/src/fixtures.d.ts +45 -0
- package/dist/packages/publication/src/fixtures.js +350 -0
- package/dist/packages/research/src/index.d.ts +188 -0
- package/dist/packages/research/src/index.js +829 -0
- package/dist/packages/runtime/src/checkpoints.d.ts +65 -0
- package/dist/packages/runtime/src/checkpoints.js +214 -0
- package/dist/packages/runtime/src/policy.d.ts +57 -0
- package/dist/packages/runtime/src/policy.js +296 -0
- package/dist/packages/sdk/src/bin/agentex-buyer.d.ts +2 -0
- package/dist/packages/sdk/src/bin/agentex-buyer.js +4 -0
- package/dist/packages/sdk/src/bin/agentex.d.ts +2 -0
- package/dist/packages/sdk/src/bin/agentex.js +3 -0
- package/dist/packages/sdk/src/buyer-cli.d.ts +10 -0
- package/dist/packages/sdk/src/buyer-cli.js +210 -0
- package/dist/packages/sdk/src/buyer.d.ts +534 -0
- package/dist/packages/sdk/src/buyer.js +441 -0
- package/dist/packages/sdk/src/cli.d.ts +14 -0
- package/dist/packages/sdk/src/cli.js +149 -0
- package/dist/packages/sdk/src/errors.d.ts +31 -0
- package/dist/packages/sdk/src/errors.js +24 -0
- package/dist/packages/sdk/src/index.d.ts +236 -0
- package/dist/packages/sdk/src/index.js +150 -0
- package/dist/packages/sdk/src/local.d.ts +11 -0
- package/dist/packages/sdk/src/local.js +110 -0
- package/dist/packages/sdk/src/rails.d.ts +59 -0
- package/dist/packages/sdk/src/rails.js +96 -0
- package/dist/packages/sdk/src/report.d.ts +121 -0
- package/dist/packages/sdk/src/report.js +114 -0
- package/dist/packages/sdk/src/version.d.ts +2 -0
- package/dist/packages/sdk/src/version.js +2 -0
- package/dist/packages/watchtower/src/index.d.ts +150 -0
- package/dist/packages/watchtower/src/index.js +786 -0
- package/dist/packages/workflow/src/registry.d.ts +61 -0
- package/dist/packages/workflow/src/registry.js +76 -0
- package/examples/README.md +34 -0
- package/examples/cli-usage.sh +30 -0
- package/examples/fixtures/base-weth-input.json +4 -0
- package/examples/focused-researcher.json +127 -0
- package/examples/pay-with-eth-robinhood.mts +37 -0
- package/examples/pay-with-usdc.mts +41 -0
- package/examples/quickstart.mts +73 -0
- package/package.json +50 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { AnyEvidenceItem } from '../../contracts/src/kinds.js';
|
|
3
|
+
import { type WorkflowManifest, type WorkflowToolDeclaration } from '../../contracts/src/workflow.js';
|
|
4
|
+
import type { RpcTransport } from '../../research/src/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Deterministic tool interface implemented by packages/tools (`TOOL_REGISTRY`). The engine depends only on this shape.
|
|
7
|
+
* Tools receive a policy-guarded transport: every request needs a prior `beforeRpc` permit and stays inside the version's
|
|
8
|
+
* address/domain scope, and `onEvidence` accepts only envelopes matching responses the transport actually returned.
|
|
9
|
+
*/
|
|
10
|
+
export interface ToolContext {
|
|
11
|
+
chain: string;
|
|
12
|
+
signal: AbortSignal;
|
|
13
|
+
transport: RpcTransport;
|
|
14
|
+
beforeRpc(op: {
|
|
15
|
+
method: string;
|
|
16
|
+
step: string;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
onEvidence(evidence: AnyEvidenceItem): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Adds addresses the tool derived deterministically from in-scope values (for example a Solana program-derived address of the input mint) to
|
|
21
|
+
* the run's address scope. Honoured only for `input-derived` versions, exactly like addresses in captured evidence; absent outside workflows.
|
|
22
|
+
*/
|
|
23
|
+
deriveAddresses?(addresses: readonly string[]): void;
|
|
24
|
+
}
|
|
25
|
+
export interface ToolDefinition<I, O> {
|
|
26
|
+
id: string;
|
|
27
|
+
version: string;
|
|
28
|
+
capability: 'evm.read' | 'solana.read' | 'http.read';
|
|
29
|
+
chains: readonly string[];
|
|
30
|
+
inputSchema: z.ZodType<I>;
|
|
31
|
+
outputSchema: z.ZodType<O>;
|
|
32
|
+
maximumCalls: number;
|
|
33
|
+
/** Fixed platform contracts (lowercase EVM or base58 Solana addresses) this tool may read on each chain, reviewed with the tool. In scope for this tool only. */
|
|
34
|
+
curatedAddresses?: Readonly<Record<string, readonly string[]>>;
|
|
35
|
+
/** One-line description for creators and the workflow assistant. */
|
|
36
|
+
description?: string;
|
|
37
|
+
execute(input: I, ctx: ToolContext): Promise<{
|
|
38
|
+
output: O;
|
|
39
|
+
evidenceIds: string[];
|
|
40
|
+
}>;
|
|
41
|
+
}
|
|
42
|
+
export type WorkflowToolRegistry = ReadonlyMap<string, ToolDefinition<unknown, unknown>>;
|
|
43
|
+
/** Registry lookup by `id@version` key, or by matching id and version on any entry. */
|
|
44
|
+
export declare function resolveTool(registry: WorkflowToolRegistry, declaration: Pick<WorkflowToolDeclaration, 'id' | 'version'>): ToolDefinition<unknown, unknown> | undefined;
|
|
45
|
+
/** Rejects impossible registry combinations before any version exists: unknown tools, capability or chain mismatches, raised ceilings, unknown arguments and output paths. */
|
|
46
|
+
export declare function validateWorkflowTools(manifest: WorkflowManifest, registry: WorkflowToolRegistry): {
|
|
47
|
+
path: string;
|
|
48
|
+
message: string;
|
|
49
|
+
}[];
|
|
50
|
+
/** Public catalog of approved tools for editors and assistants. Schemas are rendered as JSON Schema; unrepresentable parts become open. */
|
|
51
|
+
export declare function describeToolRegistry(registry: WorkflowToolRegistry): {
|
|
52
|
+
curatedAddresses?: Readonly<Record<string, readonly string[]>> | undefined;
|
|
53
|
+
description?: string | undefined;
|
|
54
|
+
id: string;
|
|
55
|
+
version: string;
|
|
56
|
+
capability: "evm.read" | "http.read" | "solana.read";
|
|
57
|
+
chains: string[];
|
|
58
|
+
maximumCalls: number;
|
|
59
|
+
inputSchema: {};
|
|
60
|
+
outputSchema: {};
|
|
61
|
+
}[];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { workflowBindings } from '../../contracts/src/workflow.js';
|
|
3
|
+
/** Registry lookup by `id@version` key, or by matching id and version on any entry. */
|
|
4
|
+
export function resolveTool(registry, declaration) {
|
|
5
|
+
const keyed = registry.get(`${declaration.id}@${declaration.version}`) ?? registry.get(declaration.id);
|
|
6
|
+
if (keyed?.id === declaration.id && keyed.version === declaration.version)
|
|
7
|
+
return keyed;
|
|
8
|
+
for (const tool of registry.values())
|
|
9
|
+
if (tool.id === declaration.id && tool.version === declaration.version)
|
|
10
|
+
return tool;
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const objectShape = (schema) => schema instanceof z.ZodObject ? schema.shape : null;
|
|
14
|
+
/** Rejects impossible registry combinations before any version exists: unknown tools, capability or chain mismatches, raised ceilings, unknown arguments and output paths. */
|
|
15
|
+
export function validateWorkflowTools(manifest, registry) {
|
|
16
|
+
const issues = [];
|
|
17
|
+
const definitions = new Map();
|
|
18
|
+
manifest.tools.forEach((tool, position) => {
|
|
19
|
+
const definition = resolveTool(registry, tool);
|
|
20
|
+
const path = `tools.${position}`;
|
|
21
|
+
if (!definition) {
|
|
22
|
+
issues.push({ path, message: `Tool ${tool.id}@${tool.version} is not in the approved tool registry` });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
definitions.set(tool.id, definition);
|
|
26
|
+
if (definition.capability !== tool.capability)
|
|
27
|
+
issues.push({ path, message: `Tool ${tool.id} has capability ${definition.capability}, not ${tool.capability}` });
|
|
28
|
+
for (const chain of tool.chains)
|
|
29
|
+
if (!definition.chains.includes(chain))
|
|
30
|
+
issues.push({ path, message: `Tool ${tool.id} does not support ${chain}` });
|
|
31
|
+
if (tool.maximumCalls > definition.maximumCalls)
|
|
32
|
+
issues.push({ path, message: `Tool ${tool.id} allows at most ${definition.maximumCalls} calls` });
|
|
33
|
+
});
|
|
34
|
+
manifest.workflow.forEach((node, position) => {
|
|
35
|
+
if (node.type === 'tool') {
|
|
36
|
+
const definition = definitions.get(node.tool);
|
|
37
|
+
const shape = definition ? objectShape(definition.inputSchema) : null;
|
|
38
|
+
if (shape) {
|
|
39
|
+
for (const key of Object.keys(node.arguments))
|
|
40
|
+
if (!Object.hasOwn(shape, key))
|
|
41
|
+
issues.push({ path: `workflow.${position}.arguments`, message: `Tool ${node.tool} has no argument ${key}` });
|
|
42
|
+
for (const [key, field] of Object.entries(shape))
|
|
43
|
+
if (!Object.hasOwn(node.arguments, key) && !field.safeParse(undefined).success)
|
|
44
|
+
issues.push({ path: `workflow.${position}.arguments`, message: `Tool ${node.tool} needs argument ${key}` });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
for (const binding of workflowBindings(node)) {
|
|
48
|
+
if (binding.source !== 'node' || !binding.path)
|
|
49
|
+
continue;
|
|
50
|
+
const target = manifest.workflow.find((item) => item.id === binding.nodeId);
|
|
51
|
+
if (target?.type !== 'tool')
|
|
52
|
+
continue;
|
|
53
|
+
const definition = definitions.get(target.tool);
|
|
54
|
+
const shape = definition ? objectShape(definition.outputSchema) : null;
|
|
55
|
+
const head = binding.path.split('.')[0];
|
|
56
|
+
if (shape && !Object.hasOwn(shape, head))
|
|
57
|
+
issues.push({ path: `workflow.${position}`, message: `Tool ${target.tool} output has no field ${head}` });
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return issues;
|
|
61
|
+
}
|
|
62
|
+
/** Public catalog of approved tools for editors and assistants. Schemas are rendered as JSON Schema; unrepresentable parts become open. */
|
|
63
|
+
export function describeToolRegistry(registry) {
|
|
64
|
+
const json = (schema) => { try {
|
|
65
|
+
return z.toJSONSchema(schema, { unrepresentable: 'any', io: 'input' });
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return {};
|
|
69
|
+
} };
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
return [...registry.values()].filter((tool) => { const key = `${tool.id}@${tool.version}`; if (seen.has(key))
|
|
72
|
+
return false; seen.add(key); return true; })
|
|
73
|
+
.map((tool) => ({ id: tool.id, version: tool.version, capability: tool.capability, chains: [...tool.chains], maximumCalls: tool.maximumCalls, inputSchema: json(tool.inputSchema), outputSchema: json(tool.outputSchema),
|
|
74
|
+
...(tool.description ? { description: tool.description } : {}), ...(tool.curatedAddresses ? { curatedAddresses: structuredClone(tool.curatedAddresses) } : {}) }))
|
|
75
|
+
.sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
76
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
## Buyer (TypeScript, ESM)
|
|
4
|
+
|
|
5
|
+
Install the package and `tsx` (or run the files with Node 22.18+ type stripping), then set `AGENTEX_API_KEY` to a key from
|
|
6
|
+
<https://agentex.sh/developers>. Every example quotes first and spends only after an explicit consent step.
|
|
7
|
+
|
|
8
|
+
| File | What it shows |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| `quickstart.mts` | SOL: list agents, quote, accept with the contract hash, poll, print findings with their evidence, sources and the receipt |
|
|
11
|
+
| `pay-with-usdc.mts` | USDC on Solana with the one-call `research()` helper and a `maxDebitAtomic` consent bound |
|
|
12
|
+
| `pay-with-eth-robinhood.mts` | ETH on Robinhood Chain with an `approve(quote)` consent callback |
|
|
13
|
+
| `cli-usage.sh` | The `agentex-buyer` CLI end to end |
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install agentex-creator-sdk tsx
|
|
17
|
+
cp node_modules/agentex-creator-sdk/examples/quickstart.mts .
|
|
18
|
+
AGENTEX_API_KEY=agx_live_... npx tsx quickstart.mts
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Creator: Base token metadata and proxy controls
|
|
22
|
+
|
|
23
|
+
`focused-researcher.json` is an importable **manifest**, authored using the SDK. It selects Base, required ERC-20 metadata/bytecode, and the three standard EIP-1967 proxy slots. It intentionally skips the optional `owner()` probe and states that omission in reports. The 16-call ceiling includes room beyond its 11-call nominal fresh run, but never gives each retry a separate allowance.
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npx agentex validate --file node_modules/agentex-creator-sdk/examples/focused-researcher.json
|
|
27
|
+
npx agentex test --file node_modules/agentex-creator-sdk/examples/focused-researcher.json
|
|
28
|
+
npx agentex estimate --file node_modules/agentex-creator-sdk/examples/focused-researcher.json
|
|
29
|
+
npx agentex pack --file node_modules/agentex-creator-sdk/examples/focused-researcher.json --out focused-package.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
After authenticated import and the normal server test/review steps, a buyer supplies an ordinary input such as Base WETH at `0x4200000000000000000000000000000000000006` (`fixtures/base-weth-input.json`). The manifest accepts another supported address as input; it is not hard-coded to WETH. Address labels are not issuer authentication, and empty slots do not establish safety or immutability. Nothing in this example requests a trade or transaction.
|
|
33
|
+
|
|
34
|
+
The local test suite uses synthetic fixtures only. A separate server creator test requires configured Base RPC coverage; actual provider cost remains unpriced. Buyer execution uses the server quote and consent flow, with its own disclosed fees and coverage.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
# AGENTEX buyer CLI walkthrough (agentex-buyer ships with agentex-creator-sdk). Output is JSON on stdout; the key is never printed.
|
|
3
|
+
# PowerShell: $env:AGENTEX_API_KEY = 'agx_live_...' and the same commands.
|
|
4
|
+
set -eu
|
|
5
|
+
|
|
6
|
+
export AGENTEX_API_KEY="${AGENTEX_API_KEY:?create a key at https://agentex.sh/developers}"
|
|
7
|
+
# export AGENTEX_API_ORIGIN=https://agentex.sh # the default
|
|
8
|
+
# export AGENTEX_ASSET=sol # sol | usdc | eth | an asset id; default: the key's own asset
|
|
9
|
+
|
|
10
|
+
npx agentex-buyer key # scopes, asset, remaining spend
|
|
11
|
+
npx agentex-buyer catalog --chain solana --asset sol --limit 10 # Solana research agents that accept SOL
|
|
12
|
+
npx agentex-buyer catalog --topic security --sort price # any rail, cheapest first
|
|
13
|
+
npx agentex-buyer agent --listing LISTING_ID # permissions, limits, inputFields, offers per rail
|
|
14
|
+
|
|
15
|
+
# Review first: a quote reserves nothing and expires after 240 seconds.
|
|
16
|
+
npx agentex-buyer quote --listing LISTING_ID --chain solana --value mint=DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263
|
|
17
|
+
npx agentex-buyer accept --quote QUOTE_ID --contract-hash HASH --idempotency-key my-run-0001 --confirm
|
|
18
|
+
npx agentex-buyer status --run RUN_ID --wait --timeout 300
|
|
19
|
+
npx agentex-buyer report --run RUN_ID # findings, evidence and sources
|
|
20
|
+
npx agentex-buyer receipt --run RUN_ID --wait # charged amount in SOL, USDC or ETH
|
|
21
|
+
|
|
22
|
+
# Or in one step, refusing any quote above 0.02 SOL:
|
|
23
|
+
npx agentex-buyer research --listing LISTING_ID --chain solana --value mint=DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263 --max-debit 0.02 --confirm
|
|
24
|
+
|
|
25
|
+
# Token Researcher takes a chain and an address; any agent also accepts an exact JSON input file:
|
|
26
|
+
npx agentex-buyer quote --listing LISTING_ID --chain base --address 0x4200000000000000000000000000000000000006
|
|
27
|
+
npx agentex-buyer quote --listing LISTING_ID --input input.json # for example {"workflow":"agentex.workflow.v1","chain":"solana","values":{"mint":"..."}}
|
|
28
|
+
|
|
29
|
+
npx agentex-buyer result --run RUN_ID --out result.json # canonical export; never overwrites a file
|
|
30
|
+
npx agentex-buyer cancel --run RUN_ID # charges only execution already incurred
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"id": "base-token-controls",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"name": "Base metadata and proxy controls",
|
|
6
|
+
"description": "Inspect required ERC-20 metadata and standard proxy slots on Base; owner() is intentionally skipped and privilege absence is not inferred.",
|
|
7
|
+
"author": {
|
|
8
|
+
"id": "local-creator",
|
|
9
|
+
"name": "Local creator",
|
|
10
|
+
"ownership": "independent"
|
|
11
|
+
},
|
|
12
|
+
"license": "Proprietary",
|
|
13
|
+
"visibility": "private",
|
|
14
|
+
"chains": [
|
|
15
|
+
"base"
|
|
16
|
+
],
|
|
17
|
+
"inputSchema": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"properties": {
|
|
20
|
+
"chain": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "Explicit analysis network",
|
|
23
|
+
"enum": [
|
|
24
|
+
"base"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"address": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"description": "Token contract address"
|
|
30
|
+
},
|
|
31
|
+
"scope": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"description": "Bounded inspection scope",
|
|
34
|
+
"enum": [
|
|
35
|
+
"metadata-and-controls"
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
"snapshotBlock": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"description": "Optional block number (defaults to the latest block)"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"required": [
|
|
44
|
+
"chain",
|
|
45
|
+
"address"
|
|
46
|
+
],
|
|
47
|
+
"additionalProperties": false
|
|
48
|
+
},
|
|
49
|
+
"outputSchemaId": "agentex.token-research.v1",
|
|
50
|
+
"tools": [
|
|
51
|
+
{
|
|
52
|
+
"id": "evm.inspect-token",
|
|
53
|
+
"version": "0.1.0",
|
|
54
|
+
"capability": "evm.read",
|
|
55
|
+
"chains": [
|
|
56
|
+
"base"
|
|
57
|
+
],
|
|
58
|
+
"addressScope": "input-address",
|
|
59
|
+
"maximumCalls": 16
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
"modelPolicy": {
|
|
63
|
+
"mode": "deterministic",
|
|
64
|
+
"maximumModelTokens": 0
|
|
65
|
+
},
|
|
66
|
+
"researchPolicy": {
|
|
67
|
+
"readOwner": false,
|
|
68
|
+
"readProxySlots": true
|
|
69
|
+
},
|
|
70
|
+
"limits": {
|
|
71
|
+
"maximumRpcCalls": 16,
|
|
72
|
+
"maximumDurationMs": 60000,
|
|
73
|
+
"maximumOutputBytes": 131072,
|
|
74
|
+
"maximumGraphDepth": 4,
|
|
75
|
+
"maximumPages": 0,
|
|
76
|
+
"maximumExecutionAtomic": "0"
|
|
77
|
+
},
|
|
78
|
+
"workflow": [
|
|
79
|
+
{
|
|
80
|
+
"id": "input",
|
|
81
|
+
"dependsOn": [],
|
|
82
|
+
"type": "input"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "inspect",
|
|
86
|
+
"dependsOn": [
|
|
87
|
+
"input"
|
|
88
|
+
],
|
|
89
|
+
"type": "tool",
|
|
90
|
+
"tool": "evm.inspect-token",
|
|
91
|
+
"arguments": {
|
|
92
|
+
"chain": {
|
|
93
|
+
"source": "input",
|
|
94
|
+
"path": "chain"
|
|
95
|
+
},
|
|
96
|
+
"address": {
|
|
97
|
+
"source": "input",
|
|
98
|
+
"path": "address"
|
|
99
|
+
},
|
|
100
|
+
"scope": {
|
|
101
|
+
"source": "input",
|
|
102
|
+
"path": "scope"
|
|
103
|
+
},
|
|
104
|
+
"snapshotBlock": {
|
|
105
|
+
"source": "input",
|
|
106
|
+
"path": "snapshotBlock"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "report",
|
|
112
|
+
"dependsOn": [
|
|
113
|
+
"inspect"
|
|
114
|
+
],
|
|
115
|
+
"type": "output",
|
|
116
|
+
"from": "inspect"
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
"testCases": [
|
|
120
|
+
"standard-metadata",
|
|
121
|
+
"nonstandard-decimals",
|
|
122
|
+
"proxy-slots",
|
|
123
|
+
"no-contract",
|
|
124
|
+
"provider-failure",
|
|
125
|
+
"budget-stop"
|
|
126
|
+
]
|
|
127
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pay in ETH on Robinhood Chain (eip155:4663/native). ETH keys belong to EVM accounts: sign in at https://agentex.sh/developers with an
|
|
3
|
+
* EVM wallet and create a key (its payment environment is ETH on Robinhood Chain). The client asks before spending: approve() sees the exact quote.
|
|
4
|
+
*
|
|
5
|
+
* export AGENTEX_API_KEY=agx_live_...
|
|
6
|
+
* AGENTEX_CONFIRM=1 npx tsx pay-with-eth-robinhood.mts
|
|
7
|
+
*/
|
|
8
|
+
import { ASSETS, AgentexApiError, createBuyerClient, formatAmount, offerFor, type Quote } from 'agentex-creator-sdk/buyer';
|
|
9
|
+
|
|
10
|
+
const ETH = ASSETS.ETH_ROBINHOOD; // 'eip155:4663/native'
|
|
11
|
+
const agentex = createBuyerClient({ apiKey: process.env.AGENTEX_API_KEY ?? '', origin: process.env.AGENTEX_API_ORIGIN ?? 'https://agentex.sh', assetId: ETH });
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const { agents } = await agentex.listAgents({ q: 'Token Researcher', chain: 'base', assetId: ETH, limit: 5 });
|
|
15
|
+
const agent = agents.find(item => offerFor(item, ETH)?.enabled);
|
|
16
|
+
if (!agent) throw new Error('No listing accepts ETH on Robinhood Chain on this server right now.');
|
|
17
|
+
const key = await agentex.key();
|
|
18
|
+
|
|
19
|
+
const approve = (quote: Quote) => {
|
|
20
|
+
console.log(`Quote ${quote.id}: at most ${formatAmount(quote.maximumBuyerDebitAtomic, ETH)}; ${formatAmount(key.remainingSpendAtomic, ETH)} left on this key.`);
|
|
21
|
+
return process.env.AGENTEX_CONFIRM === '1' && BigInt(quote.maximumBuyerDebitAtomic) <= BigInt(key.remainingSpendAtomic);
|
|
22
|
+
};
|
|
23
|
+
const outcome = await agentex.research({
|
|
24
|
+
listingId: agent.listingId,
|
|
25
|
+
input: { chain: 'base', address: '0x4200000000000000000000000000000000000006' }, // Token Researcher input: WETH on Base
|
|
26
|
+
assetId: ETH, approve,
|
|
27
|
+
});
|
|
28
|
+
console.log(`Run ${outcome.run.id} ${outcome.run.status}: ${outcome.report.findings.length} findings, ${outcome.report.evidence.length} evidence items.`);
|
|
29
|
+
for (const finding of outcome.report.findings) console.log(`- ${finding.text}`);
|
|
30
|
+
const receipt = await agentex.getReceipt(outcome.run.id, { quote: outcome.quote, waitForSettlement: { timeoutMs: 120_000 } });
|
|
31
|
+
console.log(`Charged ${receipt.charged} (${receipt.payment.label}).`);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (error instanceof AgentexApiError) {
|
|
34
|
+
console.error(`AGENTEX ${error.status ?? ''} ${error.kind}/${error.code}: ${error.message}${error.runId ? ` (run ${error.runId})` : ''}`);
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
} else throw error;
|
|
37
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pay in USDC on Solana with the one-call research() helper: quote, consent check, accept, wait, typed report.
|
|
3
|
+
* The payment rail is independent of the analysed chain: this run pays in USDC on Solana to research a stablecoin on Ethereum.
|
|
4
|
+
*
|
|
5
|
+
* export AGENTEX_API_KEY=agx_live_... # a USDC key: sign in at https://agentex.sh/developers with a Solana wallet, choose USDC
|
|
6
|
+
* AGENTEX_MAX_DEBIT=0.50 npx tsx pay-with-usdc.mts # refuses (without accepting) any quote above 0.50 USDC
|
|
7
|
+
*/
|
|
8
|
+
import { ASSETS, AgentexApiError, createBuyerClient, describeAsset, formatAmount, offerFor, parseAmount, workflowInput } from 'agentex-creator-sdk/buyer';
|
|
9
|
+
|
|
10
|
+
const USDC = ASSETS.USDC; // 'solana:mainnet-beta/spl:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
|
|
11
|
+
const usdc = describeAsset(USDC); // { currency: 'USDC', decimals: 6, rail: 'solana', profile: 'solana_usdc', ... }
|
|
12
|
+
const agentex = createBuyerClient({ apiKey: process.env.AGENTEX_API_KEY ?? '', origin: process.env.AGENTEX_API_ORIGIN ?? 'https://agentex.sh', assetId: USDC });
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
const { agents } = await agentex.listAgents({ q: 'Stablecoin Supply', assetId: USDC, limit: 5 });
|
|
16
|
+
const agent = agents.find(item => offerFor(item, USDC)?.enabled);
|
|
17
|
+
if (!agent) throw new Error('No listing accepts USDC on this server right now.');
|
|
18
|
+
|
|
19
|
+
const outcome = await agentex.research({
|
|
20
|
+
listingId: agent.listingId,
|
|
21
|
+
input: workflowInput('ethereum', { token: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' }), // USDC on Ethereum, the research subject
|
|
22
|
+
assetId: USDC,
|
|
23
|
+
maxDebitAtomic: parseAmount(process.env.AGENTEX_MAX_DEBIT ?? '0.50', usdc.decimals!), // consent bound, in USDC atomic units (6 decimals)
|
|
24
|
+
wait: { timeoutMs: 300_000 },
|
|
25
|
+
});
|
|
26
|
+
console.log(`Run ${outcome.run.id} ${outcome.run.status}; quote reserved at most ${formatAmount(outcome.quote.maximumBuyerDebitAtomic, USDC)}.`);
|
|
27
|
+
for (const section of outcome.report.sections) {
|
|
28
|
+
console.log(`\n${section.title} (${section.status})`);
|
|
29
|
+
for (const finding of section.findings) console.log(`- ${finding.text} [${finding.status}; evidence ${finding.evidenceIds.join(', ') || 'none'}]`);
|
|
30
|
+
}
|
|
31
|
+
console.log(`\n${outcome.report.evidence.length} evidence items from ${outcome.report.sources.map(source => source.provider).join(', ') || 'no sources'}.`);
|
|
32
|
+
|
|
33
|
+
const receipt = await agentex.getReceipt(outcome.run.id, { quote: outcome.quote, waitForSettlement: { timeoutMs: 120_000 } });
|
|
34
|
+
console.log(`Charged ${receipt.charged} (${receipt.payment.label}).`);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (error instanceof AgentexApiError) {
|
|
37
|
+
// kind 'refused' means the SDK declined to accept (quote above the bound): nothing was reserved.
|
|
38
|
+
console.error(`AGENTEX ${error.status ?? ''} ${error.kind}/${error.code}: ${error.message}${error.runId ? ` (run ${error.runId})` : ''}`);
|
|
39
|
+
process.exitCode = 1;
|
|
40
|
+
} else throw error;
|
|
41
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AGENTEX quickstart: find a research agent, pay for one run in SOL, wait for it, then print its findings, evidence and sources.
|
|
3
|
+
*
|
|
4
|
+
* npm install agentex-creator-sdk
|
|
5
|
+
* export AGENTEX_API_KEY=agx_live_... # a SOL key: sign in at https://agentex.sh/developers with a Solana wallet, choose SOL
|
|
6
|
+
* npx tsx quickstart.mts # quotes only; nothing is spent
|
|
7
|
+
* AGENTEX_CONFIRM=1 AGENTEX_MAX_DEBIT=0.02 npx tsx quickstart.mts # accepts a quote that reserves at most 0.02 SOL
|
|
8
|
+
*
|
|
9
|
+
* Optional: AGENTEX_MINT (the token to check; default BONK), AGENTEX_API_ORIGIN (default https://agentex.sh).
|
|
10
|
+
*/
|
|
11
|
+
import { ASSETS, AgentexApiError, createBuyerClient, evidenceFor, formatAmount, offerFor, parseAmount, workflowInput } from 'agentex-creator-sdk/buyer';
|
|
12
|
+
|
|
13
|
+
const SOL = ASSETS.SOL; // 'solana:mainnet-beta/native'
|
|
14
|
+
const agentex = createBuyerClient({
|
|
15
|
+
apiKey: process.env.AGENTEX_API_KEY ?? '',
|
|
16
|
+
origin: process.env.AGENTEX_API_ORIGIN ?? 'https://agentex.sh',
|
|
17
|
+
assetId: SOL, // pay in SOL; a SOL key can only pay in SOL
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const key = await agentex.key();
|
|
22
|
+
console.log(`Key ${key.prefix}...${key.last4} pays in ${key.assetId}; ${formatAmount(key.remainingSpendAtomic, key.assetId)} left of its spend limit.`);
|
|
23
|
+
|
|
24
|
+
// 1. Discover. Filters: q, chain, topic, category, sort, and assetId (only listings that accept SOL). Pages with nextCursor.
|
|
25
|
+
const { agents } = await agentex.listAgents({ q: 'Solana Token Safety Check', chain: 'solana', assetId: SOL, limit: 5 });
|
|
26
|
+
const agent = agents.find(item => offerFor(item, SOL)?.enabled);
|
|
27
|
+
if (!agent) throw new Error('No listing accepts SOL on this server right now.');
|
|
28
|
+
const detail = await agentex.getAgent(agent.listingId);
|
|
29
|
+
console.log(`${detail.name}: at most ${formatAmount(offerFor(detail, SOL)!.pricing.maximumBuyerDebitAtomic, SOL)} per run.`);
|
|
30
|
+
console.log(`Inputs: ${detail.inputFields.map(field => `${field.name}${field.required ? '' : '?'} (${field.type})`).join(', ')}`);
|
|
31
|
+
|
|
32
|
+
// 2. Quote. The server prices the run; nothing is reserved and the quote expires after 240 seconds.
|
|
33
|
+
const input = workflowInput('solana', { mint: process.env.AGENTEX_MINT ?? 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263' });
|
|
34
|
+
const quote = await agentex.createQuote({ listingId: agent.listingId, input, assetId: SOL });
|
|
35
|
+
console.log(`Quote ${quote.id}: reserves at most ${formatAmount(quote.maximumBuyerDebitAtomic, SOL)}; expires ${quote.expiresAt}.`);
|
|
36
|
+
if (process.env.AGENTEX_CONFIRM !== '1') {
|
|
37
|
+
console.log('Review the quote, then rerun with AGENTEX_CONFIRM=1 and AGENTEX_MAX_DEBIT (in SOL) to pay for it.');
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
const maxDebit = parseAmount(process.env.AGENTEX_MAX_DEBIT ?? '0', 9);
|
|
41
|
+
if (BigInt(quote.maximumBuyerDebitAtomic) > BigInt(maxDebit)) throw new Error(`The quote is above AGENTEX_MAX_DEBIT (${formatAmount(maxDebit, SOL)}); nothing was accepted.`);
|
|
42
|
+
|
|
43
|
+
// 3. Accept this exact quote. Retries reuse one idempotency key, so a lost response never reserves twice.
|
|
44
|
+
const { run, idempotencyKey } = await agentex.acceptQuote({ quoteId: quote.id, contractHash: quote.contractHash, assetId: SOL });
|
|
45
|
+
console.log(`Run ${run.id} accepted (idempotency key ${idempotencyKey}).`);
|
|
46
|
+
|
|
47
|
+
// 4. Poll until the run ends (1 s backoff growing to 10 s, 5 minute limit).
|
|
48
|
+
const done = await agentex.waitForRun(run.id, { timeoutMs: 300_000, onStatus: state => console.log(` ${state.run.status}`) });
|
|
49
|
+
console.log(`Run ${done.run.status}.`);
|
|
50
|
+
|
|
51
|
+
// 5. Findings, each with the evidence it cites, then the sources those reads came from.
|
|
52
|
+
const report = await agentex.getReport(run.id);
|
|
53
|
+
console.log(`\n${report.headline ?? `${report.findings.length} findings`} (${report.status})`);
|
|
54
|
+
for (const finding of report.findings) {
|
|
55
|
+
console.log(`- ${finding.text}${finding.origin === 'model' ? ' [AI-assisted]' : ''}`);
|
|
56
|
+
for (const evidence of evidenceFor(report, finding)) {
|
|
57
|
+
const at = evidence.slot ? ` at slot ${evidence.slot}` : evidence.block ? ` at block ${evidence.block}` : '';
|
|
58
|
+
console.log(` ${evidence.id}: ${evidence.source.provider} ${evidence.source.method}${at} (${evidence.completeness ?? 'recorded'})`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
console.log('\nSources:');
|
|
62
|
+
for (const source of report.sources) console.log(`- ${source.provider} (${source.kind}): ${source.methods.join(', ')}${source.documentationUrl ? ` - ${source.documentationUrl}` : ''}`);
|
|
63
|
+
for (const limitation of report.limitations) console.log(`Limitation: ${limitation}`);
|
|
64
|
+
|
|
65
|
+
// 6. Receipt: what the run charged, in its payment asset.
|
|
66
|
+
const receipt = await agentex.getReceipt(run.id, { quote, waitForSettlement: { timeoutMs: 120_000 } });
|
|
67
|
+
console.log(`\nReceipt: ${receipt.status}; charged ${receipt.charged} of at most ${formatAmount(receipt.maximumDebitAtomic ?? '0', receipt.payment)} (${receipt.payment.label}).`);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (error instanceof AgentexApiError) {
|
|
70
|
+
console.error(`AGENTEX ${error.status ?? ''} ${error.kind}/${error.code}: ${error.message}${error.runId ? ` (run ${error.runId})` : ''}`);
|
|
71
|
+
process.exitCode = 1;
|
|
72
|
+
} else throw error;
|
|
73
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agentex-creator-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official TypeScript SDK and CLIs for AGENTEX (https://agentex.sh): discover on-chain research agents, pay per run in SOL, USDC on Solana or ETH on Robinhood Chain, wait for runs and read typed findings, evidence, sources and receipts. Includes the creator package toolkit.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "AGENTEX (https://agentex.sh)",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"repository": { "type": "git", "url": "git+https://github.com/agentexrh10/agentex.git", "directory": "packages/sdk" },
|
|
9
|
+
"homepage": "https://agentex.sh/developers",
|
|
10
|
+
"keywords": ["agentex", "sdk", "cli", "crypto", "onchain", "research-agent", "ai-agents", "solana", "usdc", "ethereum", "base", "robinhood-chain", "evidence", "mcp"],
|
|
11
|
+
"engines": { "node": ">=22" },
|
|
12
|
+
"sideEffects": ["./dist/packages/sdk/src/bin/*.js"],
|
|
13
|
+
"main": "./dist/packages/sdk/src/index.js",
|
|
14
|
+
"types": "./dist/packages/sdk/src/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": { "types": "./dist/packages/sdk/src/index.d.ts", "default": "./dist/packages/sdk/src/index.js" },
|
|
17
|
+
"./buyer": { "types": "./dist/packages/sdk/src/buyer.d.ts", "default": "./dist/packages/sdk/src/buyer.js" },
|
|
18
|
+
"./report": { "types": "./dist/packages/sdk/src/report.d.ts", "default": "./dist/packages/sdk/src/report.js" },
|
|
19
|
+
"./rails": { "types": "./dist/packages/sdk/src/rails.d.ts", "default": "./dist/packages/sdk/src/rails.js" },
|
|
20
|
+
"./buyer-cli": { "types": "./dist/packages/sdk/src/buyer-cli.d.ts", "default": "./dist/packages/sdk/src/buyer-cli.js" },
|
|
21
|
+
"./local": { "types": "./dist/packages/sdk/src/local.d.ts", "default": "./dist/packages/sdk/src/local.js" },
|
|
22
|
+
"./cli": { "types": "./dist/packages/sdk/src/cli.d.ts", "default": "./dist/packages/sdk/src/cli.js" },
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"agentex": "dist/packages/sdk/src/bin/agentex.js",
|
|
27
|
+
"agentex-buyer": "dist/packages/sdk/src/bin/agentex-buyer.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/**/*.js",
|
|
31
|
+
"dist/**/*.d.ts",
|
|
32
|
+
"!dist/packages/model/src/claude.*",
|
|
33
|
+
"examples",
|
|
34
|
+
"README.md",
|
|
35
|
+
"CHANGELOG.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
40
|
+
"build": "npm run clean && tsc -p tsconfig.build.json",
|
|
41
|
+
"prepack": "npm run build",
|
|
42
|
+
"postpack": "npm run clean"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@solana/rpc-spec-types": "8.3.0",
|
|
46
|
+
"viem": "2.56.5",
|
|
47
|
+
"zod": "4.6.5"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": { "access": "public" }
|
|
50
|
+
}
|