{"record":{"id":"918e934ffdc36072","repo":"paperclipai/paperclip","slug":"agent-can-only-invoke-itself","errorCode":null,"errorMessage":"Agent can only invoke itself","messagePattern":"Agent can only invoke itself","errorType":"http","errorClass":null,"httpStatus":403,"severity":"error","filePath":"server/src/routes/agents.ts","lineNumber":4802,"sourceCode":"      },\n    });\n\n    res.json(result.bundle);\n  });\n\n  router.patch(\"/agents/:id\", validate(updateAgentSchema), async (req, res) => {\n    const id = req.params.id as string;\n    const existing = await getAccessibleResource(req, res, svc.getById(id), \"Agent not found\");\n    if (!existing) return;\n\n    if (hasOwn(req.body as object, \"permissions\")) {\n      res.status(422).json({ error: \"Use /api/agents/:id/permissions for permission changes\" });\n      return;\n    }\n\n    const patchData = { ...(req.body as Record<string, unknown>) };\n    const replaceAdapterConfig = patchData.replaceAdapterConfig === true;\n    delete patchData.replaceAdapterConfig;\n    // The apply-existing flag is not an agent column. The server binds the fixed\n    // reference to the owner stored value with no login round trip. Remove it\n    // from the patch so it never reaches the update values.\n    const applyStoredClaudeLogin = patchData.applyStoredClaudeLogin === true;\n    delete patchData.applyStoredClaudeLogin;\n    if (hasOwn(patchData, \"adapterConfig\")) {\n      const adapterConfig = asRecord(patchData.adapterConfig);\n      if (!adapterConfig) {\n        res.status(422).json({ error: \"adapterConfig must be an object\" });\n        return;\n      }\n      assertNoAgentAdapterConfigMutation(req, adapterConfig);\n      const changingInstructionsConfig = adapterConfigTouchesInstructionsConfig(adapterConfig);\n      if (changingInstructionsConfig) {\n        await assertCanManageInstructionsPath(req, existing);\n      }\n      patchData.adapterConfig = adapterConfig;\n    }","sourceCodeStart":4784,"sourceCodeEnd":4820,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/routes/agents.ts#L4784-L4820","documentation":"Self-invocation guard in the wakeup route helper: the caller authenticated as an agent but addressed a different agent's id. Agents may only trigger their own heartbeats/wakeups, so the cross-agent invocation is refused with 403.","triggerScenarios":"Thrown at server/src/routes/agents.ts:4257 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Invoke the agent using its own API key; agents cannot invoke other agents via this route."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}