diff --git a/TASKS.md b/TASKS.md
index 0668479..8caa6f9 100644
--- a/TASKS.md
+++ b/TASKS.md
@@ -51,8 +51,9 @@ Progress:
- `API Keys` page now has a mobile card layout instead of relying only on desktop table presentation
- `Secrets` page now has a mobile card layout instead of relying only on desktop table presentation
- `Usage` page now has a mobile card layout instead of relying only on desktop table presentation
+ - `Agents` page and modal now explain separate agent endpoints, next-step machine access, and stable slug expectations
- pending:
- - remaining `Agents` and `Settings` commercial UX polish
+ - remaining `Settings` and workspace commercial UX polish
## Planned
diff --git a/apps/ui/html/agents.html b/apps/ui/html/agents.html
index 9ddb65e..830afb5 100644
--- a/apps/ui/html/agents.html
+++ b/apps/ui/html/agents.html
@@ -168,6 +168,7 @@
No agents yet
Create your first agent to get a dedicated MCP endpoint with a curated set of tools.
+
After creation, issue separate machine-access keys for this endpoint on the API Keys page.
+
diff --git a/apps/ui/js/agents.js b/apps/ui/js/agents.js
index 2951000..2099454 100644
--- a/apps/ui/js/agents.js
+++ b/apps/ui/js/agents.js
@@ -446,6 +446,13 @@ document.addEventListener('alpine:init', function() {
return '/mcp/v1/' + workspaceSlug + '/' + agent.slug;
},
+ endpointHelpText(agent) {
+ return this.tfKey(
+ this.isCommunityBuild ? 'agents.card.endpoint_help_community' : 'agents.card.endpoint_help',
+ { count: agent.key_count || 0 }
+ );
+ },
+
copyEndpoint(agent) {
var endpoint = this.mcpEndpoint(agent);
navigator.clipboard.writeText(endpoint).catch(function() {});
diff --git a/apps/ui/js/i18n.js b/apps/ui/js/i18n.js
index 7bcc200..b7b712e 100644
--- a/apps/ui/js/i18n.js
+++ b/apps/ui/js/i18n.js
@@ -967,6 +967,7 @@ var TRANSLATIONS = {
'agents.empty.initial.title': 'No agents yet',
'agents.empty.initial.sub': 'Create your first agent to get a dedicated MCP endpoint with a curated set of tools.',
'agents.empty.initial.sub_community': 'Create your first agent to get one dedicated MCP endpoint and its static machine-access keys for a focused toolset.',
+ 'agents.empty.initial.next_step': 'After creation, issue separate machine-access keys for this endpoint on the API Keys page.',
'agents.empty.search.title': 'No agents match "{query}"',
'agents.empty.search.sub': 'Try a different search term.',
'agents.card.tools': 'tools',
@@ -974,6 +975,8 @@ var TRANSLATIONS = {
'agents.card.calls_today': 'calls today',
'agents.card.created': 'Created {date}',
'agents.card.copy_endpoint': 'Copy endpoint',
+ 'agents.card.endpoint_help': 'Use this MCP endpoint in your client and manage its machine-access keys on the API Keys page.',
+ 'agents.card.endpoint_help_community': 'Use this MCP endpoint in your client. Community keeps machine access on static agent keys managed on the API Keys page.',
'agents.action.edit': 'Edit',
'agents.action.archive': 'Archive',
'agents.action.delete': 'Delete',
@@ -996,6 +999,7 @@ var TRANSLATIONS = {
'agents.drawer.required': 'required',
'agents.drawer.status': 'Status',
'agents.drawer.endpoint': 'MCP endpoint',
+ 'agents.drawer.slug_hint': 'Keep the slug stable after clients start using this endpoint. Changing it changes the MCP path.',
'agents.drawer.placeholder.name': 'Customer Support',
'agents.drawer.placeholder.slug': 'customer-support',
'agents.drawer.placeholder.description': 'What does this agent do? What LLM or use-case is it for?',
@@ -2042,6 +2046,7 @@ var TRANSLATIONS = {
'agents.empty.initial.title': 'Агентов пока нет',
'agents.empty.initial.sub': 'Создайте первого агента, чтобы получить отдельный MCP endpoint с нужным набором инструментов.',
'agents.empty.initial.sub_community': 'Создайте первого агента, чтобы получить один отдельный MCP endpoint и его статические машинные ключи для конкретного набора инструментов.',
+ 'agents.empty.initial.next_step': 'После создания выпустите отдельные машинные ключи для этого endpoint на странице API Keys.',
'agents.empty.search.title': 'Нет агентов по запросу "{query}"',
'agents.empty.search.sub': 'Попробуйте другой поисковый запрос.',
'agents.card.tools': 'инструментов',
@@ -2049,6 +2054,8 @@ var TRANSLATIONS = {
'agents.card.calls_today': 'вызовов сегодня',
'agents.card.created': 'Создан {date}',
'agents.card.copy_endpoint': 'Скопировать endpoint',
+ 'agents.card.endpoint_help': 'Используйте этот MCP endpoint в клиенте и управляйте его машинными ключами на странице API Keys.',
+ 'agents.card.endpoint_help_community': 'Используйте этот MCP endpoint в клиенте. В Community машинный доступ держится на статических ключах агента со страницы API Keys.',
'agents.action.edit': 'Редактировать',
'agents.action.archive': 'Архивировать',
'agents.action.delete': 'Удалить',
@@ -2071,6 +2078,7 @@ var TRANSLATIONS = {
'agents.drawer.required': 'обязательно',
'agents.drawer.status': 'Статус',
'agents.drawer.endpoint': 'MCP endpoint',
+ 'agents.drawer.slug_hint': 'Сохраняйте slug стабильным после подключения клиентов. Его изменение меняет MCP path.',
'agents.drawer.placeholder.name': 'Customer Support',
'agents.drawer.placeholder.slug': 'customer-support',
'agents.drawer.placeholder.description': 'Что делает этот агент? Для какой LLM или сценария он нужен?',
diff --git a/apps/ui/tests/e2e/agents.spec.js b/apps/ui/tests/e2e/agents.spec.js
index 783e37d..8adbddc 100644
--- a/apps/ui/tests/e2e/agents.spec.js
+++ b/apps/ui/tests/e2e/agents.spec.js
@@ -6,8 +6,12 @@ test('agents page shows demo cards and edit drawer opens', async ({ page }) => {
await page.goto('/agents');
await expect(page.locator('.page-heading')).toHaveText(localized('Agents', 'Агенты'));
await expect(page.locator('.agents-info-callout')).toContainText(localized('static agent keys', 'статические ключи агента'));
+ await expect(page.locator('.agent-card-date').first()).toContainText(
+ localized('API Keys page', 'API Keys')
+ );
await page.getByRole('button', { name: localized('New agent', 'Новый агент') }).click();
await expect(page.locator('.drawer-title')).toHaveText(localized('New agent', 'Новый агент'));
await expect(page.locator('.drawer-subtitle')).toContainText(localized('static agent-key boundary', 'статических ключах агента'));
+ await expect(page.locator('.form-hint')).toContainText(localized('Keep the slug stable', 'Сохраняйте slug стабильным'));
await expect(page.locator('.drawer')).toContainText(/mcp/i);
});