@inkeep/agents-work-apps 0.50.3 → 0.50.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/env.d.ts CHANGED
@@ -20,7 +20,7 @@ declare const envSchema: z.ZodObject<{
20
20
  warn: "warn";
21
21
  error: "error";
22
22
  }>>;
23
- INKEEP_AGENTS_RUN_DATABASE_URL: z.ZodString;
23
+ INKEEP_AGENTS_RUN_DATABASE_URL: z.ZodOptional<z.ZodString>;
24
24
  INKEEP_AGENTS_MANAGE_UI_URL: z.ZodOptional<z.ZodString>;
25
25
  GITHUB_APP_ID: z.ZodOptional<z.ZodString>;
26
26
  GITHUB_APP_PRIVATE_KEY: z.ZodOptional<z.ZodString>;
@@ -45,7 +45,7 @@ declare const env: {
45
45
  NODE_ENV: "development" | "production" | "test";
46
46
  ENVIRONMENT: "development" | "production" | "test" | "pentest";
47
47
  LOG_LEVEL: "trace" | "debug" | "info" | "warn" | "error";
48
- INKEEP_AGENTS_RUN_DATABASE_URL: string;
48
+ INKEEP_AGENTS_RUN_DATABASE_URL?: string | undefined;
49
49
  INKEEP_AGENTS_MANAGE_UI_URL?: string | undefined;
50
50
  GITHUB_APP_ID?: string | undefined;
51
51
  GITHUB_APP_PRIVATE_KEY?: string | undefined;
package/dist/env.js CHANGED
@@ -22,7 +22,7 @@ const envSchema = z.object({
22
22
  "warn",
23
23
  "error"
24
24
  ]).default("info").describe("Logging verbosity level"),
25
- INKEEP_AGENTS_RUN_DATABASE_URL: z.string().describe("PostgreSQL connection URL for the runtime database"),
25
+ INKEEP_AGENTS_RUN_DATABASE_URL: z.string().optional().describe("PostgreSQL connection URL for the runtime database. Required in production; tests use PGlite."),
26
26
  INKEEP_AGENTS_MANAGE_UI_URL: z.string().optional().describe("URL where the management UI is hosted"),
27
27
  GITHUB_APP_ID: z.string().optional().describe("GitHub App ID for GitHub integration"),
28
28
  GITHUB_APP_PRIVATE_KEY: z.string().optional().describe("GitHub App private key for authentication"),
@@ -1,7 +1,7 @@
1
- import * as hono1 from "hono";
1
+ import * as hono0 from "hono";
2
2
 
3
3
  //#region src/github/mcp/auth.d.ts
4
- declare const githubMcpAuth: () => hono1.MiddlewareHandler<{
4
+ declare const githubMcpAuth: () => hono0.MiddlewareHandler<{
5
5
  Variables: {
6
6
  toolId: string;
7
7
  };
@@ -1,11 +1,11 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types9 from "hono/types";
2
+ import * as hono_types5 from "hono/types";
3
3
 
4
4
  //#region src/github/mcp/index.d.ts
5
5
  declare const app: Hono<{
6
6
  Variables: {
7
7
  toolId: string;
8
8
  };
9
- }, hono_types9.BlankSchema, "/">;
9
+ }, hono_types5.BlankSchema, "/">;
10
10
  //#endregion
11
11
  export { app as default };
@@ -1,7 +1,7 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types3 from "hono/types";
2
+ import * as hono_types8 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/setup.d.ts
5
- declare const app: Hono<hono_types3.BlankEnv, hono_types3.BlankSchema, "/">;
5
+ declare const app: Hono<hono_types8.BlankEnv, hono_types8.BlankSchema, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,7 +1,7 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types5 from "hono/types";
2
+ import * as hono_types3 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/tokenExchange.d.ts
5
- declare const app: Hono<hono_types5.BlankEnv, hono_types5.BlankSchema, "/">;
5
+ declare const app: Hono<hono_types3.BlankEnv, hono_types3.BlankSchema, "/">;
6
6
  //#endregion
7
7
  export { app as default };
@@ -1,5 +1,5 @@
1
1
  import { Hono } from "hono";
2
- import * as hono_types7 from "hono/types";
2
+ import * as hono_types6 from "hono/types";
3
3
 
4
4
  //#region src/github/routes/webhooks.d.ts
5
5
  interface WebhookVerificationResult {
@@ -7,6 +7,6 @@ interface WebhookVerificationResult {
7
7
  error?: string;
8
8
  }
9
9
  declare function verifyWebhookSignature(payload: string, signature: string | undefined, secret: string): WebhookVerificationResult;
10
- declare const app: Hono<hono_types7.BlankEnv, hono_types7.BlankSchema, "/">;
10
+ declare const app: Hono<hono_types6.BlankEnv, hono_types6.BlankSchema, "/">;
11
11
  //#endregion
12
12
  export { WebhookVerificationResult, app as default, verifyWebhookSignature };
@@ -44,7 +44,8 @@ const ChannelAgentConfigSchema = z.object({
44
44
  projectId: z.string(),
45
45
  agentId: z.string(),
46
46
  agentName: z.string().optional(),
47
- projectName: z.string().optional()
47
+ projectName: z.string().optional(),
48
+ grantAccessToMembers: z.boolean().optional()
48
49
  });
49
50
  const WorkspaceSettingsSchema = z.object({ defaultAgent: ChannelAgentConfigSchema.optional() });
50
51
  app.openapi(createProtectedRoute({
@@ -360,7 +361,8 @@ app.openapi(createProtectedRoute({
360
361
  agentConfig: config ? {
361
362
  projectId: config.projectId,
362
363
  agentId: config.agentId,
363
- agentName: config.agentName || void 0
364
+ agentName: config.agentName || void 0,
365
+ grantAccessToMembers: config.grantAccessToMembers
364
366
  } : void 0
365
367
  };
366
368
  });
@@ -416,7 +418,8 @@ app.openapi(createProtectedRoute({
416
418
  agentConfig: config ? {
417
419
  projectId: config.projectId,
418
420
  agentId: config.agentId,
419
- agentName: config.agentName || void 0
421
+ agentName: config.agentName || void 0,
422
+ grantAccessToMembers: config.grantAccessToMembers
420
423
  } : void 0
421
424
  });
422
425
  });
@@ -471,6 +474,7 @@ app.openapi(createProtectedRoute({
471
474
  projectId: body.agentConfig.projectId,
472
475
  agentId: body.agentConfig.agentId,
473
476
  agentName: body.agentConfig.agentName,
477
+ grantAccessToMembers: body.agentConfig.grantAccessToMembers ?? true,
474
478
  enabled: true
475
479
  });
476
480
  logger.info({
@@ -557,6 +561,7 @@ app.openapi(createProtectedRoute({
557
561
  projectId: body.agentConfig.projectId,
558
562
  agentId: body.agentConfig.agentId,
559
563
  agentName: body.agentConfig.agentName,
564
+ grantAccessToMembers: body.agentConfig.grantAccessToMembers ?? true,
560
565
  enabled: true
561
566
  });
562
567
  updated++;
@@ -11,6 +11,7 @@ interface ResolvedAgentConfig {
11
11
  agentId: string;
12
12
  agentName?: string;
13
13
  source: 'channel' | 'workspace' | 'none';
14
+ grantAccessToMembers: boolean;
14
15
  }
15
16
  interface AgentResolutionParams {
16
17
  tenantId: string;
@@ -37,7 +37,8 @@ async function resolveEffectiveAgent(params) {
37
37
  projectId: channelConfig.projectId,
38
38
  agentId: channelConfig.agentId,
39
39
  agentName: channelConfig.agentName || void 0,
40
- source: "channel"
40
+ source: "channel",
41
+ grantAccessToMembers: channelConfig.grantAccessToMembers
41
42
  };
42
43
  }
43
44
  }
@@ -52,7 +53,8 @@ async function resolveEffectiveAgent(params) {
52
53
  projectId: workspaceConfig.projectId,
53
54
  agentId: workspaceConfig.agentId,
54
55
  agentName: workspaceConfig.agentName,
55
- source: "workspace"
56
+ source: "workspace",
57
+ grantAccessToMembers: workspaceConfig.grantAccessToMembers ?? true
56
58
  };
57
59
  }
58
60
  logger.debug({
@@ -78,7 +80,8 @@ async function getAgentConfigSources(params) {
78
80
  projectId: config.projectId,
79
81
  agentId: config.agentId,
80
82
  agentName: config.agentName || void 0,
81
- source: "channel"
83
+ source: "channel",
84
+ grantAccessToMembers: config.grantAccessToMembers
82
85
  };
83
86
  }
84
87
  const wsConfig = await getWorkspaceDefaultAgentFromNango(teamId);
@@ -86,7 +89,8 @@ async function getAgentConfigSources(params) {
86
89
  projectId: wsConfig.projectId,
87
90
  agentId: wsConfig.agentId,
88
91
  agentName: wsConfig.agentName,
89
- source: "workspace"
92
+ source: "workspace",
93
+ grantAccessToMembers: wsConfig.grantAccessToMembers ?? true
90
94
  };
91
95
  return {
92
96
  channelConfig,
@@ -6,7 +6,7 @@ import { resolveEffectiveAgent } from "../agent-resolution.js";
6
6
  import { SlackStrings } from "../../i18n/strings.js";
7
7
  import { createAlreadyLinkedMessage, createContextBlock, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage } from "../blocks/index.js";
8
8
  import { getSlackClient } from "../client.js";
9
- import { fetchAgentsForProject, fetchProjectsForTenant, getChannelAgentConfig, sendResponseUrlMessage } from "../events/utils.js";
9
+ import { extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, getChannelAgentConfig, sendResponseUrlMessage } from "../events/utils.js";
10
10
  import { buildAgentSelectorModal } from "../modals.js";
11
11
  import { deleteWorkAppSlackUserMapping, findWorkAppSlackUserMapping, findWorkAppSlackUserMappingBySlackUser, flushTraces, getInProcessFetch, getWaitUntil, signSlackLinkToken, signSlackUserToken } from "@inkeep/agents-core";
12
12
 
@@ -232,21 +232,27 @@ async function handleQuestionCommand(payload, question, _dashboardUrl, tenantId)
232
232
  id: resolvedAgent.agentId,
233
233
  name: resolvedAgent.agentName || null,
234
234
  projectId: resolvedAgent.projectId
235
- }, question, userTenantId).catch((error) => {
235
+ }, question, userTenantId, {
236
+ slackAuthorized: resolvedAgent.grantAccessToMembers,
237
+ slackAuthSource: resolvedAgent.source === "none" ? void 0 : resolvedAgent.source,
238
+ slackChannelId: payload.channelId,
239
+ slackAuthorizedProjectId: resolvedAgent.projectId
240
+ }).catch((error) => {
236
241
  logger.error({ error }, "Background execution promise rejected");
237
242
  }).finally(() => flushTraces());
238
243
  const waitUntil = await getWaitUntil();
239
244
  if (waitUntil) waitUntil(questionWork);
240
245
  return {};
241
246
  }
242
- async function executeAgentInBackground(payload, existingLink, targetAgent, question, tenantId) {
247
+ async function executeAgentInBackground(payload, existingLink, targetAgent, question, tenantId, channelAuth) {
243
248
  try {
244
249
  const slackUserToken = await signSlackUserToken({
245
250
  inkeepUserId: existingLink.inkeepUserId,
246
251
  tenantId,
247
252
  slackTeamId: payload.teamId,
248
253
  slackUserId: payload.userId,
249
- slackEnterpriseId: payload.enterpriseId
254
+ slackEnterpriseId: payload.enterpriseId,
255
+ ...channelAuth
250
256
  });
251
257
  const apiBaseUrl = env.INKEEP_AGENTS_API_URL || "http://localhost:3002";
252
258
  const controller = new AbortController();
@@ -295,9 +301,11 @@ async function executeAgentInBackground(payload, existingLink, targetAgent, ques
295
301
  agentId: targetAgent.id,
296
302
  projectId: targetAgent.projectId
297
303
  }, "Run API call failed");
304
+ const apiMessage = extractApiErrorMessage(errorText);
305
+ const errorMessage = apiMessage ? `*Error.* ${apiMessage}` : `Failed to run agent: ${response.status} ${response.statusText}`;
298
306
  await sendResponseUrlMessage(payload.responseUrl, {
299
307
  response_type: "ephemeral",
300
- text: `Failed to run agent: ${response.status} ${response.statusText}`
308
+ text: errorMessage
301
309
  });
302
310
  } else {
303
311
  const result = await response.json();
@@ -1,9 +1,10 @@
1
1
  import { env } from "../../../env.js";
2
2
  import { getLogger } from "../../../logger.js";
3
3
  import { findWorkspaceConnectionByTeamId } from "../nango.js";
4
+ import { resolveEffectiveAgent } from "../agent-resolution.js";
4
5
  import { SlackStrings } from "../../i18n/strings.js";
5
6
  import { getSlackChannelInfo, getSlackClient, getSlackUserInfo, postMessageInThread } from "../client.js";
6
- import { checkIfBotThread, classifyError, findCachedUserMapping, formatChannelContext, generateSlackConversationId, getThreadContext, getUserFriendlyErrorMessage, resolveChannelAgentConfig, timedOp } from "./utils.js";
7
+ import { checkIfBotThread, classifyError, findCachedUserMapping, formatChannelContext, generateSlackConversationId, getThreadContext, getUserFriendlyErrorMessage, timedOp } from "./utils.js";
7
8
  import { SLACK_SPAN_KEYS, SLACK_SPAN_NAMES, setSpanWithError, tracer } from "../../tracer.js";
8
9
  import { streamAgentResponse } from "./streaming.js";
9
10
  import { signSlackUserToken } from "@inkeep/agents-core";
@@ -86,7 +87,11 @@ async function handleAppMention(params) {
86
87
  const hasQuery = Boolean(text && text.trim().length > 0);
87
88
  let thinkingMessageTs;
88
89
  try {
89
- const { result: [agentConfig, existingLink] } = await timedOp(Promise.all([resolveChannelAgentConfig(teamId, channel, workspaceConnection), findCachedUserMapping(tenantId, slackUserId, teamId)]), {
90
+ const { result: [agentConfig, existingLink] } = await timedOp(Promise.all([resolveEffectiveAgent({
91
+ tenantId,
92
+ teamId,
93
+ channelId: channel
94
+ }), findCachedUserMapping(tenantId, slackUserId, teamId)]), {
90
95
  label: "agent config / user mapping lookup",
91
96
  context: {
92
97
  teamId,
@@ -109,6 +114,8 @@ async function handleAppMention(params) {
109
114
  }
110
115
  span.setAttribute(SLACK_SPAN_KEYS.AGENT_ID, agentConfig.agentId);
111
116
  span.setAttribute(SLACK_SPAN_KEYS.PROJECT_ID, agentConfig.projectId);
117
+ span.setAttribute(SLACK_SPAN_KEYS.AUTHORIZED, agentConfig.grantAccessToMembers);
118
+ span.setAttribute(SLACK_SPAN_KEYS.AUTH_SOURCE, agentConfig.source);
112
119
  const agentDisplayName = agentConfig.agentName || agentConfig.agentId;
113
120
  if (!existingLink) {
114
121
  logger.info({
@@ -180,7 +187,11 @@ async function handleAppMention(params) {
180
187
  inkeepUserId: existingLink.inkeepUserId,
181
188
  tenantId,
182
189
  slackTeamId: teamId,
183
- slackUserId
190
+ slackUserId,
191
+ slackAuthorized: agentConfig?.grantAccessToMembers ?? false,
192
+ slackAuthSource: agentConfig?.source === "none" ? void 0 : agentConfig?.source,
193
+ slackChannelId: channel,
194
+ slackAuthorizedProjectId: agentConfig?.projectId
184
195
  });
185
196
  thinkingMessageTs = (await slackClient.chat.postMessage({
186
197
  channel,
@@ -254,7 +265,11 @@ Respond naturally as if you're joining the conversation to help.`;
254
265
  inkeepUserId: existingLink.inkeepUserId,
255
266
  tenantId,
256
267
  slackTeamId: teamId,
257
- slackUserId
268
+ slackUserId,
269
+ slackAuthorized: agentConfig?.grantAccessToMembers ?? false,
270
+ slackAuthSource: agentConfig?.source === "none" ? void 0 : agentConfig?.source,
271
+ slackChannelId: channel,
272
+ slackAuthorizedProjectId: agentConfig?.projectId
258
273
  });
259
274
  thinkingMessageTs = (await slackClient.chat.postMessage({
260
275
  channel,
@@ -1,6 +1,6 @@
1
1
  import { InlineSelectorMetadata, handleAppMention } from "./app-mention.js";
2
2
  import { handleMessageShortcut, handleOpenAgentSelectorModal, handleOpenFollowUpModal } from "./block-actions.js";
3
3
  import { handleFollowUpSubmission, handleModalSubmission } from "./modal-submission.js";
4
- import { SlackErrorType, checkIfBotThread, classifyError, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
4
+ import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
5
5
  import { StreamResult, streamAgentResponse } from "./streaming.js";
6
- export { type InlineSelectorMetadata, SlackErrorType, type StreamResult, checkIfBotThread, classifyError, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, handleAppMention, handleFollowUpSubmission, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, markdownToMrkdwn, sendResponseUrlMessage, streamAgentResponse };
6
+ export { type InlineSelectorMetadata, SlackErrorType, type StreamResult, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, handleAppMention, handleFollowUpSubmission, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, markdownToMrkdwn, sendResponseUrlMessage, streamAgentResponse };
@@ -1,7 +1,7 @@
1
- import { SlackErrorType, checkIfBotThread, classifyError, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
1
+ import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
2
2
  import { streamAgentResponse } from "./streaming.js";
3
3
  import { handleAppMention } from "./app-mention.js";
4
4
  import { handleMessageShortcut, handleOpenAgentSelectorModal, handleOpenFollowUpModal } from "./block-actions.js";
5
5
  import { handleFollowUpSubmission, handleModalSubmission } from "./modal-submission.js";
6
6
 
7
- export { SlackErrorType, checkIfBotThread, classifyError, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, handleAppMention, handleFollowUpSubmission, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, markdownToMrkdwn, sendResponseUrlMessage, streamAgentResponse };
7
+ export { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, handleAppMention, handleFollowUpSubmission, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, markdownToMrkdwn, sendResponseUrlMessage, streamAgentResponse };
@@ -4,7 +4,7 @@ import { findWorkspaceConnectionByTeamId } from "../nango.js";
4
4
  import { SlackStrings } from "../../i18n/strings.js";
5
5
  import { buildConversationResponseBlocks } from "../blocks/index.js";
6
6
  import { getSlackClient } from "../client.js";
7
- import { classifyError, findCachedUserMapping, generateSlackConversationId, getThreadContext, getUserFriendlyErrorMessage, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
7
+ import { classifyError, extractApiErrorMessage, findCachedUserMapping, generateSlackConversationId, getThreadContext, getUserFriendlyErrorMessage, markdownToMrkdwn, sendResponseUrlMessage } from "./utils.js";
8
8
  import { SLACK_SPAN_KEYS, SLACK_SPAN_NAMES, setSpanWithError, tracer } from "../../tracer.js";
9
9
  import { getInProcessFetch, signSlackUserToken } from "@inkeep/agents-core";
10
10
 
@@ -54,6 +54,7 @@ async function handleModalSubmission(view) {
54
54
  }
55
55
  span.setAttribute(SLACK_SPAN_KEYS.AGENT_ID, agentId);
56
56
  span.setAttribute(SLACK_SPAN_KEYS.PROJECT_ID, projectId);
57
+ span.setAttribute(SLACK_SPAN_KEYS.AUTHORIZED, false);
57
58
  const tenantId = metadata.tenantId;
58
59
  const [workspaceConnection, existingLink] = await Promise.all([findWorkspaceConnectionByTeamId(metadata.teamId), findCachedUserMapping(tenantId, metadata.slackUserId, metadata.teamId)]);
59
60
  if (!workspaceConnection?.botToken) {
@@ -99,7 +100,8 @@ async function handleModalSubmission(view) {
99
100
  inkeepUserId: existingLink.inkeepUserId,
100
101
  tenantId,
101
102
  slackTeamId: metadata.teamId,
102
- slackUserId: metadata.slackUserId
103
+ slackUserId: metadata.slackUserId,
104
+ slackAuthorized: false
103
105
  });
104
106
  const conversationId = generateSlackConversationId({
105
107
  teamId: metadata.teamId,
@@ -200,6 +202,7 @@ async function handleFollowUpSubmission(view) {
200
202
  span.setAttribute(SLACK_SPAN_KEYS.AGENT_ID, agentId);
201
203
  span.setAttribute(SLACK_SPAN_KEYS.PROJECT_ID, projectId);
202
204
  span.setAttribute(SLACK_SPAN_KEYS.CONVERSATION_ID, conversationId);
205
+ span.setAttribute(SLACK_SPAN_KEYS.AUTHORIZED, false);
203
206
  const [workspaceConnection, existingLink] = await Promise.all([findWorkspaceConnectionByTeamId(teamId), findCachedUserMapping(tenantId, slackUserId, teamId)]);
204
207
  if (!workspaceConnection?.botToken) {
205
208
  logger.error({ teamId }, "No bot token for follow-up submission");
@@ -224,7 +227,8 @@ async function handleFollowUpSubmission(view) {
224
227
  inkeepUserId: existingLink.inkeepUserId,
225
228
  tenantId,
226
229
  slackTeamId: teamId,
227
- slackUserId
230
+ slackUserId,
231
+ slackAuthorized: false
228
232
  });
229
233
  const apiBaseUrl = env.INKEEP_AGENTS_API_URL || "http://localhost:3002";
230
234
  await slackClient.chat.postEphemeral({
@@ -348,11 +352,15 @@ async function callAgentApi(params) {
348
352
  isError: false
349
353
  };
350
354
  }
351
- const errorText = getUserFriendlyErrorMessage(classifyError(null, response.status), agentId);
355
+ const errorBody = await response.text().catch(() => "");
356
+ const apiMessage = extractApiErrorMessage(errorBody);
357
+ const errorType = classifyError(null, response.status);
358
+ const errorText = apiMessage ? `*Error.* ${apiMessage}` : getUserFriendlyErrorMessage(errorType, agentId);
352
359
  logger.warn({
353
360
  status: response.status,
354
361
  statusText: response.statusText,
355
- agentId
362
+ agentId,
363
+ errorBody
356
364
  }, "Agent API returned error");
357
365
  apiSpan.end();
358
366
  return {
@@ -1,7 +1,7 @@
1
1
  import { env } from "../../../env.js";
2
2
  import { getLogger } from "../../../logger.js";
3
3
  import { createContextBlock } from "../blocks/index.js";
4
- import { SlackErrorType, classifyError, getUserFriendlyErrorMessage } from "./utils.js";
4
+ import { SlackErrorType, classifyError, extractApiErrorMessage, getUserFriendlyErrorMessage } from "./utils.js";
5
5
  import { SLACK_SPAN_KEYS, SLACK_SPAN_NAMES, setSpanWithError, tracer } from "../../tracer.js";
6
6
  import { getInProcessFetch } from "@inkeep/agents-core";
7
7
 
@@ -129,8 +129,9 @@ async function streamAgentResponse(params) {
129
129
  status: response.status,
130
130
  errorBody
131
131
  }, "Agent streaming request failed");
132
+ const apiMessage = extractApiErrorMessage(errorBody);
132
133
  const errorType = classifyError(null, response.status);
133
- const errorMessage = getUserFriendlyErrorMessage(errorType, agentName);
134
+ const errorMessage = apiMessage ? `*Error.* ${apiMessage}` : getUserFriendlyErrorMessage(errorType, agentName);
134
135
  await slackClient.chat.postMessage({
135
136
  channel,
136
137
  thread_ts: threadTs,
@@ -50,6 +50,7 @@ declare function classifyError(error: unknown, httpStatus?: number): SlackErrorT
50
50
  /**
51
51
  * Get a user-friendly error message based on error type
52
52
  */
53
+ declare function extractApiErrorMessage(responseBody: string): string | null;
53
54
  declare function getUserFriendlyErrorMessage(errorType: SlackErrorType, agentName?: string): string;
54
55
  type ProjectOption = {
55
56
  id: string;
@@ -157,4 +158,4 @@ declare function formatChannelContext(channelInfo: {
157
158
  name?: string;
158
159
  } | null): string;
159
160
  //#endregion
160
- export { ProjectOption, SlackErrorType, checkIfBotThread, classifyError, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
161
+ export { ProjectOption, SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
@@ -94,6 +94,13 @@ function classifyError(error, httpStatus) {
94
94
  /**
95
95
  * Get a user-friendly error message based on error type
96
96
  */
97
+ function extractApiErrorMessage(responseBody) {
98
+ try {
99
+ const parsed = JSON.parse(responseBody);
100
+ if (typeof parsed.message === "string" && parsed.message.length > 0) return parsed.message;
101
+ } catch {}
102
+ return null;
103
+ }
97
104
  function getUserFriendlyErrorMessage(errorType, agentName) {
98
105
  const agent = agentName || "The agent";
99
106
  switch (errorType) {
@@ -402,4 +409,4 @@ function formatChannelContext(channelInfo) {
402
409
  }
403
410
 
404
411
  //#endregion
405
- export { SlackErrorType, checkIfBotThread, classifyError, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
412
+ export { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, formatChannelContext, formatChannelLabel, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, resolveChannelAgentConfig, sendResponseUrlMessage, timedOp };
@@ -8,9 +8,9 @@ import { InlineSelectorMetadata, handleAppMention } from "./events/app-mention.j
8
8
  import { handleMessageShortcut, handleOpenAgentSelectorModal, handleOpenFollowUpModal } from "./events/block-actions.js";
9
9
  import { handleFollowUpSubmission, handleModalSubmission } from "./events/modal-submission.js";
10
10
  import { AgentOption, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, FollowUpModalMetadata, ModalMetadata, buildAgentSelectorModal, buildFollowUpModal, buildMessageShortcutModal } from "./modals.js";
11
- import { SlackErrorType, checkIfBotThread, classifyError, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./events/utils.js";
11
+ import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./events/utils.js";
12
12
  import { StreamResult, streamAgentResponse } from "./events/streaming.js";
13
13
  import "./events/index.js";
14
14
  import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "./security.js";
15
15
  import { getBotTokenForTeam, setBotTokenForTeam } from "./workspace-tokens.js";
16
- export { AgentConfigSources, AgentOption, AgentResolutionParams, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, ContextBlockParams, DefaultAgentConfig, FollowUpButtonParams, FollowUpModalMetadata, InlineSelectorMetadata, ModalMetadata, ResolvedAgentConfig, SlackCommandPayload, SlackCommandResponse, SlackErrorType, SlackWorkspaceConnection, StreamResult, WorkspaceInstallData, buildAgentSelectorModal, buildConversationResponseBlocks, buildFollowUpButton, buildFollowUpModal, buildMessageShortcutModal, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleFollowUpSubmission, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleQuestionCommand, handleStatusCommand, handleUnlinkCommand, listWorkspaceInstallations, markdownToMrkdwn, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, verifySlackRequest };
16
+ export { AgentConfigSources, AgentOption, AgentResolutionParams, BuildAgentSelectorModalParams, BuildMessageShortcutModalParams, ContextBlockParams, DefaultAgentConfig, FollowUpButtonParams, FollowUpModalMetadata, InlineSelectorMetadata, ModalMetadata, ResolvedAgentConfig, SlackCommandPayload, SlackCommandResponse, SlackErrorType, SlackWorkspaceConnection, StreamResult, WorkspaceInstallData, buildAgentSelectorModal, buildConversationResponseBlocks, buildFollowUpButton, buildFollowUpModal, buildMessageShortcutModal, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleFollowUpSubmission, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleQuestionCommand, handleStatusCommand, handleUnlinkCommand, listWorkspaceInstallations, markdownToMrkdwn, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, verifySlackRequest };
@@ -2,7 +2,7 @@ import { clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createConn
2
2
  import { getAgentConfigSources, resolveEffectiveAgent } from "./agent-resolution.js";
3
3
  import { buildConversationResponseBlocks, buildFollowUpButton, createAlreadyLinkedMessage, createContextBlock, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage } from "./blocks/index.js";
4
4
  import { checkUserIsChannelMember, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackTeamInfo, getSlackUserInfo, postMessage, postMessageInThread, revokeSlackToken } from "./client.js";
5
- import { SlackErrorType, checkIfBotThread, classifyError, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./events/utils.js";
5
+ import { SlackErrorType, checkIfBotThread, classifyError, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, generateSlackConversationId, getChannelAgentConfig, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, markdownToMrkdwn, sendResponseUrlMessage } from "./events/utils.js";
6
6
  import { buildAgentSelectorModal, buildFollowUpModal, buildMessageShortcutModal } from "./modals.js";
7
7
  import { handleAgentPickerCommand, handleCommand, handleHelpCommand, handleLinkCommand, handleQuestionCommand, handleStatusCommand, handleUnlinkCommand } from "./commands/index.js";
8
8
  import { streamAgentResponse } from "./events/streaming.js";
@@ -13,4 +13,4 @@ import "./events/index.js";
13
13
  import { parseSlackCommandBody, parseSlackEventBody, verifySlackRequest } from "./security.js";
14
14
  import { getBotTokenForTeam, setBotTokenForTeam } from "./workspace-tokens.js";
15
15
 
16
- export { SlackErrorType, buildAgentSelectorModal, buildConversationResponseBlocks, buildFollowUpButton, buildFollowUpModal, buildMessageShortcutModal, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleFollowUpSubmission, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleQuestionCommand, handleStatusCommand, handleUnlinkCommand, listWorkspaceInstallations, markdownToMrkdwn, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, verifySlackRequest };
16
+ export { SlackErrorType, buildAgentSelectorModal, buildConversationResponseBlocks, buildFollowUpButton, buildFollowUpModal, buildMessageShortcutModal, checkIfBotThread, checkUserIsChannelMember, classifyError, clearWorkspaceConnectionCache, computeWorkspaceConnectionId, createAlreadyLinkedMessage, createConnectSession, createContextBlock, createErrorMessage, createJwtLinkMessage, createNotLinkedMessage, createStatusMessage, createUnlinkSuccessMessage, createUpdatedHelpMessage, deleteWorkspaceInstallation, extractApiErrorMessage, fetchAgentsForProject, fetchProjectsForTenant, findCachedUserMapping, findWorkspaceConnectionByTeamId, generateSlackConversationId, getAgentConfigSources, getBotTokenForTeam, getChannelAgentConfig, getConnectionAccessToken, getSlackChannelInfo, getSlackChannels, getSlackClient, getSlackIntegrationId, getSlackNango, getSlackTeamInfo, getSlackUserInfo, getThreadContext, getUserFriendlyErrorMessage, getWorkspaceDefaultAgent, getWorkspaceDefaultAgentFromNango, handleAgentPickerCommand, handleAppMention, handleCommand, handleFollowUpSubmission, handleHelpCommand, handleLinkCommand, handleMessageShortcut, handleModalSubmission, handleOpenAgentSelectorModal, handleOpenFollowUpModal, handleQuestionCommand, handleStatusCommand, handleUnlinkCommand, listWorkspaceInstallations, markdownToMrkdwn, parseSlackCommandBody, parseSlackEventBody, postMessage, postMessageInThread, resolveEffectiveAgent, revokeSlackToken, sendResponseUrlMessage, setBotTokenForTeam, setWorkspaceDefaultAgent, storeWorkspaceInstallation, streamAgentResponse, updateConnectionMetadata, verifySlackRequest };
@@ -18,6 +18,7 @@ interface DefaultAgentConfig {
18
18
  agentName?: string;
19
19
  projectId: string;
20
20
  projectName?: string;
21
+ grantAccessToMembers?: boolean;
21
22
  }
22
23
  interface SlackWorkspaceConnection {
23
24
  connectionId: string;
@@ -36,6 +36,8 @@ declare const SLACK_SPAN_KEYS: {
36
36
  readonly IS_IN_THREAD: "slack.is_in_thread";
37
37
  readonly STREAM_FINALIZATION_FAILED: "slack.stream_finalization_failed";
38
38
  readonly CONTENT_ALREADY_DELIVERED: "slack.content_already_delivered";
39
+ readonly AUTHORIZED: "slack.authorized";
40
+ readonly AUTH_SOURCE: "slack.auth_source";
39
41
  };
40
42
  type SlackOutcome = 'handled' | 'ignored_bot_message' | 'ignored_unknown_event' | 'ignored_no_action_match' | 'ignored_slack_retry' | 'url_verification' | 'validation_error' | 'signature_invalid' | 'error';
41
43
  //#endregion
@@ -34,7 +34,9 @@ const SLACK_SPAN_KEYS = {
34
34
  HAS_QUERY: "slack.has_query",
35
35
  IS_IN_THREAD: "slack.is_in_thread",
36
36
  STREAM_FINALIZATION_FAILED: "slack.stream_finalization_failed",
37
- CONTENT_ALREADY_DELIVERED: "slack.content_already_delivered"
37
+ CONTENT_ALREADY_DELIVERED: "slack.content_already_delivered",
38
+ AUTHORIZED: "slack.authorized",
39
+ AUTH_SOURCE: "slack.auth_source"
38
40
  };
39
41
 
40
42
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-work-apps",
3
- "version": "0.50.3",
3
+ "version": "0.50.4",
4
4
  "description": "First party integrations for Inkeep Agents",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -33,7 +33,7 @@
33
33
  "jose": "^6.1.0",
34
34
  "minimatch": "^10.1.1",
35
35
  "slack-block-builder": "^2.8.0",
36
- "@inkeep/agents-core": "0.50.3"
36
+ "@inkeep/agents-core": "0.50.4"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@hono/zod-openapi": "^1.1.5",