@@ -57,7 +57,7 @@ in `x-pack/platform/packages/shared/agent-builder/agent-builder-server/allow_lis
5757
5858### Making sure the tool's namespace is registered as being internal
5959
60- Platform tools should all be namespaced under protected namespaces, to avoid id collisions with user-created tools.
60+ Platform tools should all be namespaced under protected namespaces, to avoid id collisions with user-created tools.
6161When introducing a new protected namespace (e.g. when adding a new category of tools), it must be added
6262to the ` protectedNamespaces ` array in ` x-pack/platform/packages/shared/agent-builder/agent-builder-common/base/namespaces.ts `
6363
@@ -273,7 +273,6 @@ agentBuilder.agents.register({
273273});
274274```
275275
276-
277276### Specific research and answer instructions
278277
279278It is possible to specify specific research and answer instructions for an agent, to avoid
@@ -288,10 +287,12 @@ agentBuilder.agents.register({
288287 avatar_icon: ' dashboardApp' ,
289288 configuration: {
290289 research: {
291- instructions: ' You are a dashboard builder specialist assistant. Always uses the XXX tool when the user wants to YYY...'
290+ instructions:
291+ ' You are a dashboard builder specialist assistant. Always uses the XXX tool when the user wants to YYY...' ,
292292 },
293293 answer: {
294- instructions: ' When answering, if a dashboard configuration is present in the results, always render it using [...]' ,
294+ instructions:
295+ ' When answering, if a dashboard configuration is present in the results, always render it using [...]' ,
295296 },
296297 tools: [
297298 {
@@ -325,6 +326,7 @@ class MyPlugin {
325326```
326327
327328There are two main categories of attachment types:
329+
328330- ` inline ` : attachment is self-contained, with the data attached to it.
329331 ` reference ` : reference a persisted resource (for example, a dashboard, an alert, etc) by its id, and resolve it dynamically when needed.
330332 - (Not implemented yet)
@@ -354,15 +356,101 @@ const textArrachmentType: InlineAttachmentTypeDefinition = {
354356 format : (input ) => {
355357 return { type: ' text' , value: input .content };
356358 },
357- }
359+ };
358360```
359361
360362Refer to [ ` AttachmentTypeDefinition ` ] ( https://github.com/elastic/kibana/blob/main/x-pack/platform/packages/shared/agent-builder/agent-builder-server/attachments/type_definition.ts )
361363for the full list of available configuration options.
362364
363365### Browser-side registration
364366
365- Not implemented yet
367+ Register a UI definition for your attachment type using the ` attachments.addAttachmentType ` API from the ` agentBuilder ` plugin's start contract:
368+
369+ ``` ts
370+ class MyPlugin {
371+ start(core : CoreStart , { agentBuilder }: { agentBuilder: AgentBuilderPluginStart }) {
372+ agentBuilder .attachments .addAttachmentType (' my_type' , myAttachmentDefinition );
373+ }
374+ }
375+ ```
376+
377+ #### Complete example
378+
379+ ``` ts
380+ import React from ' react' ;
381+ import { i18n } from ' @kbn/i18n' ;
382+ import { EuiCodeBlock } from ' @elastic/eui' ;
383+ import {
384+ ActionButtonType ,
385+ type AttachmentUIDefinition ,
386+ } from ' @kbn/agent-builder-browser/attachments' ;
387+ import type { Attachment } from ' @kbn/agent-builder-common/attachments' ;
388+
389+ type MyAttachment = Attachment <' my_type' >;
390+
391+ export const myAttachmentDefinition: AttachmentUIDefinition <MyAttachment > = {
392+ getLabel : () => ' My attachment' ,
393+ getIcon : () => ' document' ,
394+
395+ // Compact view rendered inline in the conversation
396+ renderInlineContent : ({ attachment , isSidebar }) => {
397+ if (isSidebar ) {
398+ // For example: render a condensed view in the sidebar only
399+ }
400+
401+ return (
402+ < EuiCodeBlock fontSize = " s" > {attachment.data.content }< / EuiCodeBlock >
403+ );
404+ },
405+
406+ // Expanded view rendered in the canvas flyout
407+ renderCanvasContent : ({ attachment }) => (
408+ < EuiCodeBlock fontSize = " m" lineNumbers isCopyable >
409+ {attachment .data .content }
410+ < / EuiCodeBlock >
411+ ),
412+
413+ // Customize buttons based on viewport context
414+ getActionButtons : ({ attachment , isCanvas , isSidebar , openCanvas }) => {
415+ const buttons = [];
416+
417+ if (isSidebar ) {
418+ // add sidebar only buttons
419+ }
420+
421+ if (isCanvas ) {
422+ // add canvas only buttons
423+ }
424+
425+ buttons .push ({
426+ label: ' Copy' ,
427+ icon: ' copy' ,
428+ type: ActionButtonType .SECONDARY ,
429+ handler : async () => navigator .clipboard .writeText (attachment .data .content ),
430+ });
431+
432+ // openCanvas is {undefined} when already in canvas mode
433+ if (openCanvas ) {
434+ buttons .push ({
435+ label: ' Open Canvas' ,
436+ icon: ' play' ,
437+ type: ActionButtonType .PRIMARY ,
438+ handler: openCanvas ,
439+ });
440+ }
441+
442+ return buttons ;
443+ },
444+ };
445+ ```
446+
447+ #### Viewport
448+
449+ The ` getActionButtons ` params include flags to customize behavior per viewport:
450+
451+ - ** ` isSidebar ` ** - ` true ` when rendered in the sidebar (constrained width)
452+ - ** ` isCanvas ` ** - ` true ` when rendered in the canvas flyout (expanded view)
453+ - ** ` openCanvas ` ** - Callback to open canvas mode; ` undefined ` when already in canvas
366454
367455## Registering skills
368456
@@ -400,7 +488,7 @@ agentBuilder.skills.register({
400488 // list of tools (from the tool registry) which will be enabled when the skill is read
401489 getRegistryTools : () => [' platform.core.generate_esql' ],
402490 // list of inline tools which will be enabled when the skill is read
403- getInlineTools : () => [myInlineToolDefinition ]
491+ getInlineTools : () => [myInlineToolDefinition ],
404492});
405493```
406494
@@ -430,4 +518,4 @@ agentBuilder.skills.register({
430518 { name: ' brownie-recipe' , relativePath: ' ./recipes' , content: ' [some brownie recipe]' },
431519 ],
432520});
433- ```
521+ ```
0 commit comments