fix(openclaw-gateway): make claimedApiKeyPath configurable per agent

The openclaw_gateway adapter hardcodes the Paperclip API key path to
~/.openclaw/workspace/paperclip-claimed-api-key.json in buildWakeText().
In multi-agent OpenClaw deployments, each agent has its own workspace
with its own key file. The hardcoded path forces all agents to share
one key, breaking agent identity isolation.

Add a claimedApiKeyPath field to the adapter config (with UI input)
that allows operators to set a per-agent path. Falls back to the
current default when unset — zero behavior change for existing
deployments.

Fixes #930
This commit is contained in:
Wes Belt
2026-04-03 11:25:58 -04:00
parent 2ac40aba56
commit 8e42c6cdac
2 changed files with 19 additions and 3 deletions
@@ -313,6 +313,12 @@ function resolvePaperclipApiUrlOverride(value: unknown): string | null {
}
}
const DEFAULT_CLAIMED_API_KEY_PATH = "~/.openclaw/workspace/paperclip-claimed-api-key.json";
function resolveClaimedApiKeyPath(value: unknown): string {
return nonEmpty(value) ?? DEFAULT_CLAIMED_API_KEY_PATH;
}
function buildPaperclipEnvForWake(ctx: AdapterExecutionContext, wakePayload: WakePayload): Record<string, string> {
const paperclipApiUrlOverride = resolvePaperclipApiUrlOverride(ctx.config.paperclipApiUrl);
const paperclipEnv: Record<string, string> = {
@@ -335,8 +341,7 @@ function buildPaperclipEnvForWake(ctx: AdapterExecutionContext, wakePayload: Wak
return paperclipEnv;
}
function buildWakeText(payload: WakePayload, paperclipEnv: Record<string, string>): string {
const claimedApiKeyPath = "~/.openclaw/workspace/paperclip-claimed-api-key.json";
function buildWakeText(payload: WakePayload, paperclipEnv: Record<string, string>, claimedApiKeyPath: string): string {
const orderedKeys = [
"PAPERCLIP_RUN_ID",
"PAPERCLIP_AGENT_ID",
@@ -1053,7 +1058,8 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
const wakePayload = buildWakePayload(ctx);
const paperclipEnv = buildPaperclipEnvForWake(ctx, wakePayload);
const wakeText = buildWakeText(wakePayload, paperclipEnv);
const claimedApiKeyPath = resolveClaimedApiKeyPath(ctx.config.claimedApiKeyPath);
const wakeText = buildWakeText(wakePayload, paperclipEnv, claimedApiKeyPath);
const sessionKeyStrategy = normalizeSessionKeyStrategy(ctx.config.sessionKeyStrategy);
const configuredSessionKey = nonEmpty(ctx.config.sessionKey);
@@ -150,6 +150,16 @@ export function OpenClawGatewayConfigFields({
/>
</Field>
<Field label="Claimed API key path">
<DraftInput
value={eff("adapterConfig", "claimedApiKeyPath", String(config.claimedApiKeyPath ?? ""))}
onCommit={(v) => mark("adapterConfig", "claimedApiKeyPath", v || undefined)}
immediate
className={inputClass}
placeholder="~/.openclaw/workspace/paperclip-claimed-api-key.json"
/>
</Field>
<Field label="Session strategy">
<select
value={sessionStrategy}