Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Recommended path:
1. Connect a wallet in the staging Gateway Dashboard.
2. Get or issue an Agent Key and export it as `SYNAPSE_AGENT_KEY`.
3. Set `SYNAPSE_ENV=staging`.
4. Use free services first, or fund staging balance with MockUSDC before paid test calls.
4. Use the free first-party `svc_synapse_echo` smoke service first, or fund staging balance with MockUSDC before paid test calls.
5. Run one fixed-price API invoke and one token-metered LLM invoke.
6. Read the invocation receipt and verify settlement metadata.

Expand All @@ -55,7 +55,7 @@ Developers should pass staging before any future production migration. Productio

| Goal | Use |
|---|---|
| Connect SynapseNetwork to an agent framework such as Cursor, Claude Desktop, or LangChain | Official MCP server: `@synapse-network/mcp-server` with `SYNAPSE_AGENT_KEY=agt_xxx` |
| Connect SynapseNetwork to an agent framework such as Cursor, Claude Desktop, or LangChain | Official MCP server: `@synapse-network-ai/mcp-server` with `SYNAPSE_AGENT_KEY=agt_xxx` |
| Write application code that invokes services directly | This SDK with `SynapseClient` |
| Issue Agent Keys or publish provider APIs | Advanced owner/provider APIs: `SynapseAuth` and `auth.provider()` |

Expand Down Expand Up @@ -118,6 +118,7 @@ All five SDKs expose the same public capability families: agent runtime, owner w
## Examples By SDK

All runnable examples default to staging and read `SYNAPSE_AGENT_KEY`.
The fixed-price smoke examples first call `svc_synapse_echo`, then fall back to another free fixed-price service if echo is unavailable.

| SDK | Free fixed-price smoke | LLM smoke | Full E2E |
|---|---|---|---|
Expand Down Expand Up @@ -156,12 +157,12 @@ from synapse_client import SynapseClient

client = SynapseClient()

services = client.search("free", limit=10)
services = client.search("svc_synapse_echo", limit=10)
service = services[0]

result = client.invoke(
service.service_id,
{"prompt": "hello"},
{"message": "hello from Synapse SDK smoke", "metadata": {"scenario": "quickstart"}},
cost_usdc=str(service.price_usdc),
idempotency_key="agent-job-001",
)
Expand All @@ -180,12 +181,14 @@ Step 1: get your Agent Key from the Synapse Gateway Dashboard.

Step 2: pass the key to the SDK.

The npm organization is `synapse-network-ai`; use the `@synapse-network-ai/*` scope for official packages.

```bash
npm install @synapse-network/sdk
npm install @synapse-network-ai/sdk
```

```ts
import { SynapseClient } from "@synapse-network/sdk";
import { SynapseClient } from "@synapse-network-ai/sdk";

const agentKey = process.env.SYNAPSE_AGENT_KEY;
if (!agentKey) {
Expand All @@ -197,14 +200,14 @@ const client = new SynapseClient({
environment: "staging",
});

const services = await client.search("free", {
const services = await client.search("svc_synapse_echo", {
limit: 10,
});
const service = services[0];

const result = await client.invoke(
service.serviceId ?? service.id!,
{ prompt: "hello" },
{ message: "hello from Synapse SDK smoke", metadata: { scenario: "quickstart" } },
{
costUsdc: String(service.pricing?.amount ?? "0"),
idempotencyKey: "agent-job-001",
Expand Down Expand Up @@ -267,7 +270,7 @@ TypeScript:

```ts
import { Wallet } from "ethers";
import { SynapseAuth } from "@synapse-network/sdk";
import { SynapseAuth } from "@synapse-network-ai/sdk";

const wallet = new Wallet(process.env.OWNER_PRIVATE_KEY!);
const auth = SynapseAuth.fromWallet(wallet, { environment: "staging" });
Expand Down Expand Up @@ -306,7 +309,7 @@ TypeScript:

```ts
import { Wallet } from "ethers";
import { SynapseAuth } from "@synapse-network/sdk";
import { SynapseAuth } from "@synapse-network-ai/sdk";

const auth = SynapseAuth.fromWallet(new Wallet(process.env.OWNER_PRIVATE_KEY!), {
environment: "staging",
Expand Down
12 changes: 7 additions & 5 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ SynapseNetwork 让 Agent 可以发现服务、通过 gateway 调用服务,并

| 目标 | 使用 |
|---|---|
| 把 SynapseNetwork 接入 Cursor、Claude Desktop、LangChain 等 Agent framework | 官方 MCP server:`@synapse-network/mcp-server`,设置 `SYNAPSE_AGENT_KEY=agt_xxx` |
| 把 SynapseNetwork 接入 Cursor、Claude Desktop、LangChain 等 Agent framework | 官方 MCP server:`@synapse-network-ai/mcp-server`,设置 `SYNAPSE_AGENT_KEY=agt_xxx` |
| 在应用代码里直接调用服务 | 本 SDK 的 `SynapseClient` |
| 签发 Agent Key 或发布 Provider API | 高级 owner/provider API:`SynapseAuth` 和 `auth.provider()` |

Expand Down Expand Up @@ -178,12 +178,14 @@ print(receipt.invocation_id, receipt.status, receipt.charged_usdc)

步骤 2:把 key 传给 SDK。

npm 组织是 `synapse-network-ai`;官方包统一使用 `@synapse-network-ai/*` scope。

```bash
npm install @synapse-network/sdk
npm install @synapse-network-ai/sdk
```

```ts
import { SynapseClient } from "@synapse-network/sdk";
import { SynapseClient } from "@synapse-network-ai/sdk";

const agentKey = process.env.SYNAPSE_AGENT_KEY;
if (!agentKey) {
Expand Down Expand Up @@ -265,7 +267,7 @@ TypeScript:

```ts
import { Wallet } from "ethers";
import { SynapseAuth } from "@synapse-network/sdk";
import { SynapseAuth } from "@synapse-network-ai/sdk";

const wallet = new Wallet(process.env.OWNER_PRIVATE_KEY!);
const auth = SynapseAuth.fromWallet(wallet, { environment: "staging" });
Expand Down Expand Up @@ -304,7 +306,7 @@ TypeScript:

```ts
import { Wallet } from "ethers";
import { SynapseAuth } from "@synapse-network/sdk";
import { SynapseAuth } from "@synapse-network-ai/sdk";

const auth = SynapseAuth.fromWallet(new Wallet(process.env.OWNER_PRIVATE_KEY!), {
environment: "staging",
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export SYNAPSE_AGENT_KEY=agt_xxx

| Goal | Use |
|---|---|
| Connect an agent framework such as Cursor, Claude Desktop, or LangChain | `@synapse-network/mcp-server` |
| Connect an agent framework such as Cursor, Claude Desktop, or LangChain | `@synapse-network-ai/mcp-server` |
| Write application code that invokes services directly | `SynapseClient` |
| Issue agent credentials or manage provider services | `SynapseAuth` and `auth.provider()` |

Expand Down
5 changes: 4 additions & 1 deletion docs/ops/sdk-release-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@ This runbook covers SynapseNetwork SDK package publishing. SDKs are **published*
| Language | Package | Registry | Publish notes |
| --- | --- | --- | --- |
| Python | `synapse-client` | PyPI | Optional TestPyPI dry-run before public release. |
| TypeScript | `@synapse-network/sdk` | npm | Use npm dist-tags such as `preview`, `next`, or `latest`. |
| TypeScript | `@synapse-network-ai/sdk` | npm | Use npm dist-tags such as `preview`, `next`, or `latest`. |
| Go | `github.com/SynapseNetworkAI/Synapse-Network-Sdk/go` | Go module via GitHub | Because the module is in `/go`, tags must use `go/vX.Y.Z`. |
| Java | `ai.synapsenetwork:synapse-network-sdk` | Maven Central | If Central is not ready, publish preview artifacts to GitHub Packages Maven. |
| .NET | `SynapseNetwork.Sdk` | NuGet.org | Use NuGet package versions and never overwrite an existing version. |
| All | GitHub Release | GitHub | One release page per train with links to all language packages. |

The npm organization is `synapse-network-ai`: https://www.npmjs.com/org/synapse-network-ai.
Do not publish or document packages under the occupied legacy npm scope.

## Preflight

Run the full SDK quality gate:
Expand Down
4 changes: 2 additions & 2 deletions docs/sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ bash scripts/e2e/sdk_parity_e2e.sh --env local

This does not reintroduce a public local environment preset. The local target is only an explicit URL override for test automation. The script may install missing local toolchains; .NET is pinned to SDK 8.0 under `$HOME/.synapse-network-sdk-e2e/dotnet` if needed.

By default the fixed-price path only auto-selects a free fixed-price API service. If staging has no such service, set `SYNAPSE_E2E_FIXED_SERVICE_ID`, `SYNAPSE_E2E_FIXED_COST_USDC`, and `SYNAPSE_E2E_FIXED_PAYLOAD_JSON` explicitly.
By default the fixed-price path first selects the Synapse first-party smoke service `svc_synapse_echo`, then falls back to any free fixed-price API service. If staging has neither, set `SYNAPSE_E2E_FIXED_SERVICE_ID`, `SYNAPSE_E2E_FIXED_COST_USDC`, and `SYNAPSE_E2E_FIXED_PAYLOAD_JSON` explicitly.

## Staging Docs

Expand Down Expand Up @@ -139,7 +139,7 @@ Runtime calls should include:

1. `request_id` / request header for gateway log correlation.
2. `idempotency_key` / `idempotencyKey` to avoid duplicate charges or duplicate execution.
3. For fixed-price APIs, pass `cost_usdc` / `costUsdc` from latest discovery price. If price changes, the gateway rejects the call and the caller should rediscover.
3. For fixed-price APIs, pass `cost_usdc` / `costUsdc` from latest discovery price. Smoke examples default to `svc_synapse_echo`, a free first-party echo service that returns the JSON object payload unchanged. If price changes, the gateway rejects the call and the caller should rediscover.
4. For token-metered LLM services, call `invoke_llm()` / `invokeLlm()` with optional `max_cost_usdc` / `maxCostUsdc`; final Provider `usage` drives the actual charge.

## Common Failures
Expand Down
4 changes: 2 additions & 2 deletions docs/sdk/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ bash scripts/e2e/sdk_parity_e2e.sh --env local

这不会恢复公开的 local environment preset;local 只是测试自动化里的显式 URL override。缺少本地工具链时可自动安装;.NET 会按项目 baseline 安装 SDK 8.0 到 `$HOME/.synapse-network-sdk-e2e/dotnet`。

默认 fixed-price 路径只会自动选择免费的 fixed-price API 服务。如果 staging 没有这类服务,需要显式设置 `SYNAPSE_E2E_FIXED_SERVICE_ID`、`SYNAPSE_E2E_FIXED_COST_USDC` 和 `SYNAPSE_E2E_FIXED_PAYLOAD_JSON`。
默认 fixed-price 路径会先选择 Synapse 第一方 smoke 服务 `svc_synapse_echo`,找不到时再 fallback 到免费的 fixed-price API 服务。如果 staging 两者都没有,需要显式设置 `SYNAPSE_E2E_FIXED_SERVICE_ID`、`SYNAPSE_E2E_FIXED_COST_USDC` 和 `SYNAPSE_E2E_FIXED_PAYLOAD_JSON`。

## Staging 产品文档

Expand Down Expand Up @@ -139,7 +139,7 @@ TypeScript:

1. `request_id` / request header,用于串联 gateway 日志。
2. `idempotency_key` / `idempotencyKey`,用于避免重复扣费或重复执行。
3. 普通 fixed-price API 传 `cost_usdc` / `costUsdc`,来自最新 discovery price。若价格变化,gateway 会拒绝本次调用,调用方应重新 discovery。
3. 普通 fixed-price API 传 `cost_usdc` / `costUsdc`,来自最新 discovery price。Smoke examples 默认调用免费的第一方 `svc_synapse_echo`,它会原样返回 JSON object payload。若价格变化,gateway 会拒绝本次调用,调用方应重新 discovery。
4. 按 token 计费的 LLM 服务调用 `invoke_llm()` / `invokeLlm()`,可选传 `max_cost_usdc` / `maxCostUsdc`;最终按 Provider 返回的 `usage` 精准扣费。

## 常见故障
Expand Down
8 changes: 6 additions & 2 deletions docs/sdk/dotnet_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ var client = new SynapseClient(new SynapseClientOptions
Environment = "staging",
});

var services = await client.SearchAsync("free", new SearchOptions { Limit = 10 });
var services = await client.SearchAsync("svc_synapse_echo", new SearchOptions { Limit = 10 });
var service = services[0];
var price = service.Pricing?.GetProperty("amount").GetString() ?? "0";

var result = await client.InvokeAsync(
service.ServiceId ?? service.Id!,
new Dictionary<string, object?> { ["prompt"] = "hello" },
new Dictionary<string, object?>
{
["message"] = "hello from Synapse SDK smoke",
["metadata"] = new Dictionary<string, object?> { ["scenario"] = "quickstart" },
},
new InvokeOptions { CostUsdc = price });

Console.WriteLine($"{result.InvocationId} {result.Status} {result.ChargedUsdc}");
Expand Down
7 changes: 5 additions & 2 deletions docs/sdk/go_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func main() {
panic(err)
}

services, err := client.Search(context.Background(), "free", synapse.SearchOptions{Limit: 10})
services, err := client.Search(context.Background(), "svc_synapse_echo", synapse.SearchOptions{Limit: 10})
if err != nil {
panic(err)
}
Expand All @@ -41,7 +41,10 @@ func main() {
result, err := client.Invoke(
context.Background(),
service.ServiceID,
map[string]any{"prompt": "hello"},
map[string]any{
"message": "hello from Synapse SDK smoke",
"metadata": map[string]any{"scenario": "quickstart"},
},
synapse.InvokeOptions{CostUSDC: fmt.Sprint(service.Pricing["amount"])},
)
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions docs/sdk/java_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ import java.util.Map;
SynapseClient client = new SynapseClient(
SynapseClient.options(System.getenv("SYNAPSE_AGENT_KEY")).environment("staging"));

var services = client.search("free", new SynapseClient.SearchOptions());
var services = client.search("svc_synapse_echo", new SynapseClient.SearchOptions());
var service = services.get(0);

SynapseClient.InvokeOptions options = new SynapseClient.InvokeOptions();
options.costUsdc = service.pricing().path("amount").asText("0");

var result = client.invoke(service.serviceId(), Map.of("prompt", "hello"), options);
var result = client.invoke(
service.serviceId(),
Map.of("message", "hello from Synapse SDK smoke", "metadata", Map.of("scenario", "quickstart")),
options);
System.out.println(result.invocationId() + " " + result.status() + " " + result.chargedUsdc());
```

Expand Down
2 changes: 1 addition & 1 deletion docs/sdk/python_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ print(result.synapse.charged_usdc, result.synapse.released_usdc)

示例脚本位于 `python/examples`:

1. `free_service_smoke.py`:搜索免费 fixed-price API service、invoke、读取 receipt。
1. `free_service_smoke.py`:优先调用第一方 `svc_synapse_echo`,找不到时搜索免费 fixed-price API service、invoke、读取 receipt。
2. `llm_smoke.py`:调用 token-metered LLM,不发送 fixed-price cost。
3. `e2e.py`:完整真实 Gateway 验证并输出 JSON lines。
4. `provider_staging_onboarding.py`:使用 `SynapseAuth` + `auth.provider()` 在 staging 注册 provider service。
Expand Down
5 changes: 3 additions & 2 deletions docs/sdk/typescript_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Staging 接入建议先完成:

```ts
import { Wallet } from "ethers";
import { SynapseAuth } from "@synapse-network/sdk";
import { SynapseAuth } from "@synapse-network-ai/sdk";

const wallet = new Wallet(process.env.OWNER_PRIVATE_KEY!);
const auth = SynapseAuth.fromWallet(wallet, {
Expand Down Expand Up @@ -147,7 +147,7 @@ SDK 继续兼容 `limit/offset` 入参,并映射为:
示例:

```ts
import { SynapseClient } from "@synapse-network/sdk";
import { SynapseClient } from "@synapse-network-ai/sdk";

const client = new SynapseClient({
credential: issued.token,
Expand Down Expand Up @@ -221,6 +221,7 @@ console.log(result.synapse?.chargedUsdc, result.synapse?.releasedUsdc);
## TypeScript Examples

Runnable examples live under `typescript/examples`:
`example:free` first calls `svc_synapse_echo`, then falls back to another free fixed-price API service if echo is unavailable.

```bash
cd /Users/cliff/workspace/agent/Synapse-Network-Sdk
Expand Down
2 changes: 1 addition & 1 deletion docs/sdk/typescript_provider_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

```ts
import { Wallet } from "ethers";
import { SynapseAuth } from "@synapse-network/sdk";
import { SynapseAuth } from "@synapse-network-ai/sdk";

const wallet = new Wallet(process.env.PROVIDER_PRIVATE_KEY!);

Expand Down
27 changes: 22 additions & 5 deletions dotnet/examples/e2e/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
using System.Text.Json;
using SynapseNetwork.Sdk;

const string DefaultFixedPayload = "{\"prompt\":\"hello\"}";
const string SynapseEchoServiceId = "svc_synapse_echo";
const string DefaultFixedPayload = "{\"message\":\"hello from Synapse SDK smoke\",\"metadata\":{\"scenario\":\"fixed-price\"}}";
const string DefaultLlmPayload = "{\"messages\":[{\"role\":\"user\",\"content\":\"hello\"}]}";

var credential = RequireEnv("SYNAPSE_AGENT_KEY");
Expand Down Expand Up @@ -110,14 +111,22 @@ static async Task<FixedServiceTarget> FixedTarget(SynapseClient client, Cancella
return new FixedServiceTarget(configuredServiceId.Trim(), cost.Trim(), payload);
}

var echoServices = await client.SearchAsync(SynapseEchoServiceId, new SearchOptions { Limit = 10 }, cancellationToken);
foreach (var service in echoServices)
{
var amount = PricingAmount(service);
if (string.Equals(service.ServiceId, SynapseEchoServiceId, StringComparison.Ordinal)
&& IsFreeFixedApiService(service, amount))
{
return new FixedServiceTarget(service.ServiceId, amount, payload);
}
}

var services = await client.SearchAsync("free", new SearchOptions { Limit = 25 }, cancellationToken);
foreach (var service in services)
{
var amount = PricingAmount(service);
if (!string.IsNullOrWhiteSpace(service.ServiceId)
&& string.Equals(service.ServiceKind, "api", StringComparison.OrdinalIgnoreCase)
&& string.Equals(service.PriceModel, "fixed", StringComparison.OrdinalIgnoreCase)
&& DecimalEquals(amount, "0"))
if (IsFreeFixedApiService(service, amount))
{
return new FixedServiceTarget(service.ServiceId, amount, payload);
}
Expand All @@ -126,6 +135,14 @@ static async Task<FixedServiceTarget> FixedTarget(SynapseClient client, Cancella
throw new InvalidOperationException("unreachable");
}

static bool IsFreeFixedApiService(ServiceRecord service, string amount)
{
return !string.IsNullOrWhiteSpace(service.ServiceId)
&& string.Equals(service.ServiceKind, "api", StringComparison.OrdinalIgnoreCase)
&& string.Equals(service.PriceModel, "fixed", StringComparison.OrdinalIgnoreCase)
&& DecimalEquals(amount, "0");
}

static async Task<InvocationResult> AwaitReceipt(SynapseClient client, string? invocationId, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(invocationId))
Expand Down
Loading
Loading