{"record":{"id":"bc4bae284f063ef5","repo":"paperclipai/paperclip","slug":"agent-authorization-required","errorCode":"agent_authorization_required","errorMessage":"A dedicated agent authorization is required","messagePattern":"A dedicated agent authorization is required","errorType":"http","errorClass":"ToolGatewayHttpError","httpStatus":409,"severity":"error","filePath":"server/src/services/tool-gateway.ts","lineNumber":4480,"sourceCode":"        )\n      ) {\n        throw new ToolGatewayHttpError(\n          403,\n          \"The acting user is not in this grant's audience\",\n          \"grant_audience_denied\",\n          {\n            connectionId: connection.id,\n            grantId: grant.id,\n            actingUserId,\n          },\n        );\n      }\n      return grant;\n    };\n\n    if (connection.credentialPolicy === \"per_agent\") {\n      if (!session.agentId) {\n        throw new ToolGatewayHttpError(\n          409,\n          \"A dedicated agent authorization is required\",\n          \"agent_authorization_required\",\n          {\n            connectionId: connection.id,\n          },\n        );\n      }\n      const [agentGrant] = await db\n        .select()\n        .from(connectionGrants)\n        .where(\n          and(\n            eq(connectionGrants.companyId, connection.companyId),\n            eq(connectionGrants.connectionId, connection.id),\n            eq(connectionGrants.kind, \"agent\"),\n            eq(connectionGrants.subjectAgentId, session.agentId),\n            eq(connectionGrants.status, \"active\"),","sourceCodeStart":4462,"sourceCodeEnd":4498,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/tool-gateway.ts#L4462-L4498","documentation":"Thrown when a connection uses the per_agent credential policy but the calling session has no agentId. Per-agent connections require each agent to use its own dedicated grant; a session without an agent identity cannot select any grant, so a 409 is raised.","triggerScenarios":"resolveConnectionGrant sees connection.credentialPolicy === 'per_agent' and session.agentId is undefined — e.g. a board/user-context session or a system job invoking an agent-only connection.","commonSituations":"Testing a per-agent connection from the board UI (no agent context); running the connection through a script/CLI without agent credentials; misconfiguring a shared connection as per_agent when it should be shared/company policy.","solutions":["Invoke the connection from an agent session that has an agentId","Change the connection's credentialPolicy to a shared policy if agent-dedicated grants are not needed","Authorize an agent grant for the calling agent if policy is correct but the session is right","Check which session type is being used — board operator sessions cannot use per-agent connections"],"exampleFix":"// before\nconst session = await createBoardSession(companyId); // no agentId\ncallTool(session, perAgentConnId, p); // 409\n// after\nconst session = await createAgentSession({ companyId, agentId });\ncallTool(session, perAgentConnId, p);","handlingStrategy":"validation","validationCode":"if (connection.credentialPolicy === \"per_agent\" && !session.agentId) {\n  throw new Error(\"per_agent connection requires an agent session\");\n}","typeGuard":"function isAgentSession(s: Session): s is Session & { agentId: string } {\n  return typeof (s as { agentId?: string }).agentId === \"string\";\n}","tryCatchPattern":"try { await gateway.callTool(session, connId, p); }\ncatch (e) {\n  if (e.code === \"agent_authorization_required\") await runAgentAuthorizationFlow(connId, session.agentId);\n  else throw e;\n}","preventionTips":["Check credentialPolicy before choosing the session type for a tool call","Use shared policy connections for board/operator ad-hoc testing","Document that per_agent connections are agent-only","Route board-initiated calls through a designated service agent"],"tags":["authorization","connector","agent","configuration"],"backgroundTag":"authentication-required","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}