Clarify OpenClaw claimed API key handling

This commit is contained in:
Dotta
2026-03-06 11:21:55 -06:00
parent cec372f9bb
commit f56901b473
4 changed files with 15 additions and 1 deletions

View File

@@ -146,6 +146,7 @@ type WakePayload = {
};
function buildWakeText(payload: WakePayload, paperclipEnv: Record<string, string>): string {
const claimedApiKeyPath = "~/.openclaw/workspace/paperclip-claimed-api-key.json";
const orderedKeys = [
"PAPERCLIP_RUN_ID",
"PAPERCLIP_AGENT_ID",
@@ -171,6 +172,9 @@ function buildWakeText(payload: WakePayload, paperclipEnv: Record<string, string
"",
"Set these values in your run context:",
...envLines,
`PAPERCLIP_API_KEY=<token from ${claimedApiKeyPath}>`,
"",
`Load PAPERCLIP_API_KEY from ${claimedApiKeyPath} (the token you saved after claim-api-key).`,
"",
`task_id=${payload.taskId ?? ""}`,
`issue_id=${payload.issueId ?? ""}`,

View File

@@ -49,6 +49,9 @@ describe("buildInviteOnboardingTextDocument", () => {
expect(text).toContain("You MUST include agentDefaultsPayload.headers.x-openclaw-auth");
expect(text).toContain("will fail with 401 Unauthorized");
expect(text).toContain("set the first reachable candidate as agentDefaultsPayload.paperclipApiUrl");
expect(text).toContain("~/.openclaw/workspace/paperclip-claimed-api-key.json");
expect(text).toContain("PAPERCLIP_API_KEY");
expect(text).toContain("saved token field");
});
it("includes loopback diagnostics for authenticated/private onboarding", () => {

View File

@@ -196,6 +196,8 @@ describe("openclaw adapter execute", () => {
expect(text).toContain("PAPERCLIP_TASK_ID=task-123");
expect(text).toContain("PAPERCLIP_WAKE_REASON=issue_assigned");
expect(text).toContain("PAPERCLIP_LINKED_ISSUE_IDS=issue-123");
expect(text).toContain("PAPERCLIP_API_KEY=<token from ~/.openclaw/workspace/paperclip-claimed-api-key.json>");
expect(text).toContain("Load PAPERCLIP_API_KEY from ~/.openclaw/workspace/paperclip-claimed-api-key.json");
});
it("uses paperclipApiUrl override when provided", async () => {
@@ -379,6 +381,7 @@ describe("openclaw adapter execute", () => {
expect(body.model).toBe("openclaw");
expect(typeof body.input).toBe("string");
expect(String(body.input)).toContain("PAPERCLIP_RUN_ID=run-123");
expect(String(body.input)).toContain("PAPERCLIP_API_KEY=<token from ~/.openclaw/workspace/paperclip-claimed-api-key.json>");
expect(body.metadata).toBeTypeOf("object");
expect((body.metadata as Record<string, unknown>).PAPERCLIP_RUN_ID).toBe("run-123");
expect(body.text).toBeUndefined();

View File

@@ -662,7 +662,7 @@ function buildInviteOnboardingManifest(
invite: toInviteSummaryResponse(req, token, invite),
onboarding: {
instructions:
"Join as an OpenClaw agent, save your one-time claim secret, wait for board approval, then claim your API key and install the Paperclip skill before starting heartbeat loops. You MUST include agentDefaultsPayload.headers.x-openclaw-auth in your join request so Paperclip can authenticate callback requests.",
"Join as an OpenClaw agent, save your one-time claim secret, wait for board approval, then claim your API key. Save the claim response token to ~/.openclaw/workspace/paperclip-claimed-api-key.json and load PAPERCLIP_API_KEY from that file before starting heartbeat loops. You MUST include agentDefaultsPayload.headers.x-openclaw-auth in your join request so Paperclip can authenticate callback requests.",
inviteMessage: extractInviteMessage(invite),
recommendedAdapterType: "openclaw",
requiredFields: {
@@ -805,6 +805,10 @@ export function buildInviteOnboardingTextDocument(
' "claimSecret": "<one-time-claim-secret>"',
"}",
"",
"On successful claim, save the full JSON response to:",
"- ~/.openclaw/workspace/paperclip-claimed-api-key.json",
"Then set PAPERCLIP_API_KEY from the saved token field for every heartbeat run.",
"",
"Important:",
"- claim secrets expire",
"- claim secrets are single-use",