> ## Documentation Index
> Fetch the complete documentation index at: https://developer.box.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Box AI API agent configurator

> Configure Box AI API agents with a visual configurator. Choose from multiple AI models from leading providers, all accessible through a single, easy-to-use platform. Fine-tune Box AI API and LLM parameters, then export a ready-to-use JSON configuration for your Box AI API requests.

export const AIAgentConfig = ({button}) => {
  const getProviderFromModel = model => {
    if (model.startsWith("openai__") || model.startsWith("azure__openai")) return "openai";
    if (model.startsWith("google__")) return "google";
    if (model.startsWith("aws__")) return "aws";
    if (model.startsWith("ibm__") || model.startsWith("meta__")) return "ibm";
    if (model.startsWith("xai__")) return "openai";
    if (model.startsWith("azure__text")) return "openai";
    return "openai";
  };
  const providerParams = {
    openai: {
      type: "openai_params",
      params: [{
        name: "temperature",
        label: "Temperature",
        min: 0,
        max: 2,
        step: 0.1,
        default: 0
      }, {
        name: "top_p",
        label: "Top P",
        min: 0.1,
        max: 1,
        step: 0.05,
        default: 0.9
      }, {
        name: "frequency_penalty",
        label: "Frequency Penalty",
        min: -2,
        max: 2,
        step: 0.1,
        default: 1.5
      }, {
        name: "presence_penalty",
        label: "Presence Penalty",
        min: -2,
        max: 2,
        step: 0.1,
        default: 1.5
      }, {
        name: "stop_sequence",
        label: "Stop Sequence",
        type: "text",
        default: ""
      }]
    },
    google: {
      type: "google_params",
      params: [{
        name: "temperature",
        label: "Temperature",
        min: 0,
        max: 2,
        step: 0.1,
        default: 0
      }, {
        name: "top_p",
        label: "Top P",
        min: 0.1,
        max: 2,
        step: 0.1,
        default: 0.9
      }, {
        name: "top_k",
        label: "Top K",
        min: 0.1,
        max: 2,
        step: 0.1,
        default: 1
      }]
    },
    aws: {
      type: "aws_params",
      params: [{
        name: "temperature",
        label: "Temperature",
        min: 0,
        max: 1,
        step: 0.1,
        default: 0
      }, {
        name: "top_p",
        label: "Top P",
        min: 0,
        max: 1,
        step: 0.1,
        default: 0.9
      }]
    },
    ibm: {
      type: "ibm_params",
      params: [{
        name: "temperature",
        label: "Temperature",
        min: 0,
        max: 1,
        step: 0.1,
        default: 0
      }, {
        name: "top_p",
        label: "Top P",
        min: 0.1,
        max: 1,
        step: 0.1,
        default: 0.9
      }, {
        name: "top_k",
        label: "Top K",
        min: 1,
        max: 100,
        step: 1,
        default: 50
      }]
    }
  };
  const getDefaultParamsForProvider = provider => {
    const params = {};
    providerParams[provider].params.forEach(p => {
      params[p.name] = p.default;
    });
    return params;
  };
  const providerParamNames = [...new Set(Object.values(providerParams).flatMap(({params}) => params.map(({name}) => name)))];
  const allContentTypeIds = ["basic_gen", "basic_text", "basic_text_multi", "basic_image", "basic_image_multi", "long_text", "long_text_multi", "spreadsheet"];
  const [selectedAgentType, setSelectedAgentType] = useState("ai_agent_ask");
  const [selectedContentTypes, setSelectedContentTypes] = useState(["basic_text"]);
  const [activeTab, setActiveTab] = useState("basic_text");
  const defaultModel = "openai__gpt_5_mini";
  const defaultProvider = getProviderFromModel(defaultModel);
  const defaultConfig = {
    model: defaultModel,
    ...getDefaultParamsForProvider(defaultProvider),
    num_tokens_for_completion: 8400,
    prompt_template: "It is `{current_date}`, consider these travel options `{content}` and answer the `{user_question}`.",
    system_message: "You are a helpful travel assistant specialized in budget travel",
    content_template: "`````{content}`````"
  };
  const [config, setConfig] = useState(() => {
    const initialConfig = {};
    allContentTypeIds.forEach(id => {
      initialConfig[id] = {
        ...defaultConfig
      };
    });
    return initialConfig;
  });
  const agentTypes = [{
    value: "ai_agent_ask",
    label: "AI Ask"
  }, {
    value: "ai_agent_text_gen",
    label: "AI Text gen"
  }, {
    value: "ai_agent_extract",
    label: "AI Extract free form"
  }, {
    value: "ai_agent_extract_structured",
    label: "AI Extract structured"
  }];
  const agentContentTypeIds = {
    ai_agent_ask: ["basic_text", "basic_text_multi", "basic_image", "basic_image_multi", "long_text", "long_text_multi", "spreadsheet"],
    ai_agent_text_gen: ["basic_gen"],
    ai_agent_extract: ["basic_text", "basic_image", "long_text"],
    ai_agent_extract_structured: ["basic_text", "basic_image", "long_text"]
  };
  const contentTypes = [{
    id: "basic_gen",
    title: "Basic Generation",
    description: "Text generation content"
  }, {
    id: "basic_text",
    title: "Basic Text",
    description: "Simple text content"
  }, {
    id: "basic_text_multi",
    title: "Basic Text Multi",
    description: "Multiple text files"
  }, {
    id: "basic_image",
    title: "Basic Image",
    description: "Single image file"
  }, {
    id: "basic_image_multi",
    title: "Basic Image Multi",
    description: "Multiple image files"
  }, {
    id: "long_text",
    title: "Long Text",
    description: "Documents and PDFs"
  }, {
    id: "long_text_multi",
    title: "Long Text Multi",
    description: "Multiple documents"
  }, {
    id: "spreadsheet",
    title: "Spreadsheet",
    description: "Excel or CSV files"
  }];
  const models = [{
    value: "openai__gpt_5_6_sol",
    label: "OpenAI GPT-5.6 Sol"
  }, {
    value: "openai__gpt_5_6_terra",
    label: "OpenAI GPT-5.6 Terra"
  }, {
    value: "openai__gpt_5_5",
    label: "OpenAI GPT-5.5"
  }, {
    value: "openai__gpt_5_4",
    label: "OpenAI GPT-5.4"
  }, {
    value: "openai__gpt_5_4_mini",
    label: "OpenAI GPT-5.4 mini"
  }, {
    value: "openai__gpt_5_2",
    label: "OpenAI GPT-5.2"
  }, {
    value: "openai__gpt_5_1",
    label: "OpenAI GPT-5.1"
  }, {
    value: "openai__gpt_5",
    label: "OpenAI GPT-5"
  }, {
    value: "openai__gpt_5_mini",
    label: "OpenAI GPT-5 mini"
  }, {
    value: "openai__gpt_o3",
    label: "OpenAI GPT o3"
  }, {
    value: "google__gemini_3_5_flash",
    label: "Google Gemini 3.5 Flash"
  }, {
    value: "google__gemini_3_5_flash_lite",
    label: "Google Gemini 3.5 Flash Lite"
  }, {
    value: "google__gemini_3_1_flash_lite",
    label: "Google Gemini 3.1 Flash Lite"
  }, {
    value: "google__gemini_2_5_pro",
    label: "Google Gemini 2.5 Pro"
  }, {
    value: "google__gemini_2_5_flash",
    label: "Google Gemini 2.5 Flash"
  }, {
    value: "google__gemini_3_6_flash",
    label: "Google Gemini 3.6 Flash"
  }, {
    value: "google__gemini_3_1_pro",
    label: "Google Gemini 3.1 Pro"
  }, {
    value: "google__gemini_3_flash",
    label: "Google Gemini 3 Flash"
  }, {
    value: "aws__claude_opus_5",
    label: "AWS Claude Opus 5"
  }, {
    value: "aws__claude_sonnet_5",
    label: "AWS Claude Sonnet 5"
  }, {
    value: "aws__claude_4_8_opus",
    label: "AWS Claude Opus 4.8"
  }, {
    value: "aws__claude_4_7_opus",
    label: "AWS Claude Opus 4.7"
  }, {
    value: "aws__claude_4_6_opus",
    label: "AWS Claude Opus 4.6"
  }, {
    value: "aws__claude_4_6_sonnet",
    label: "AWS Claude Sonnet 4.6"
  }, {
    value: "aws__claude_4_5_opus",
    label: "AWS Claude Opus 4.5"
  }, {
    value: "aws__claude_4_5_sonnet",
    label: "AWS Claude Sonnet 4.5"
  }, {
    value: "aws__claude_4_5_haiku",
    label: "AWS Claude Haiku 4.5"
  }, {
    value: "aws__claude_fable_5",
    label: "AWS Claude Fable 5"
  }, {
    value: "ibm__llama_4_maverick",
    label: "IBM Llama 4 Maverick"
  }, {
    value: "ibm__mistral_medium_2505",
    label: "IBM Mistral Medium 3"
  }, {
    value: "ibm__mistral_small_3_1_24b_instruct_2503",
    label: "IBM Mistral Small 3.1"
  }];
  const handleAgentTypeChange = newAgentType => {
    const allowedContentTypes = agentContentTypeIds[newAgentType];
    const nextSelectedContentTypes = selectedContentTypes.filter(id => allowedContentTypes.includes(id));
    if (nextSelectedContentTypes.length === 0) {
      nextSelectedContentTypes.push(allowedContentTypes[0]);
    }
    setSelectedAgentType(newAgentType);
    setSelectedContentTypes(nextSelectedContentTypes);
    setActiveTab(nextSelectedContentTypes.includes(activeTab) ? activeTab : nextSelectedContentTypes[0]);
  };
  const toggleContentType = id => {
    if (selectedContentTypes.includes(id)) {
      if (selectedContentTypes.length > 1) {
        const newSelected = selectedContentTypes.filter(t => t !== id);
        setSelectedContentTypes(newSelected);
        if (activeTab === id) {
          setActiveTab(newSelected[0]);
        }
      }
    } else {
      setSelectedContentTypes(prev => [...prev, id]);
      if (!config[id]) {
        setConfig(prev => ({
          ...prev,
          [id]: {
            ...defaultConfig
          }
        }));
      }
    }
  };
  const updateConfig = (contentType, field, value) => {
    setConfig(prev => ({
      ...prev,
      [contentType]: {
        ...prev[contentType],
        [field]: value
      }
    }));
  };
  const handleModelChange = (contentType, newModel) => {
    const newProvider = getProviderFromModel(newModel);
    setConfig(prev => {
      const oldProvider = getProviderFromModel(prev[contentType].model);
      const nextContentTypeConfig = {
        ...prev[contentType],
        model: newModel
      };
      if (newProvider !== oldProvider) {
        providerParamNames.forEach(name => {
          delete nextContentTypeConfig[name];
        });
        Object.assign(nextContentTypeConfig, getDefaultParamsForProvider(newProvider));
      }
      return {
        ...prev,
        [contentType]: nextContentTypeConfig
      };
    });
  };
  const generateJSON = () => {
    const output = {
      type: selectedAgentType
    };
    const allowedContentTypes = agentContentTypeIds[selectedAgentType];
    selectedContentTypes.filter(ct => allowedContentTypes.includes(ct)).forEach(ct => {
      if (config[ct]) {
        const provider = getProviderFromModel(config[ct].model);
        const paramsConfig = providerParams[provider];
        const llmParams = {
          type: paramsConfig.type
        };
        paramsConfig.params.forEach(p => {
          if (p.type === "text") {
            if (config[ct][p.name]) {
              llmParams[p.name === "stop_sequence" ? "stop" : p.name] = config[ct][p.name];
            }
          } else {
            llmParams[p.name] = config[ct][p.name];
          }
        });
        const baseConfig = {
          llm_endpoint_params: llmParams,
          model: config[ct].model,
          num_tokens_for_completion: config[ct].num_tokens_for_completion
        };
        if (ct !== "spreadsheet") {
          baseConfig.prompt_template = config[ct].prompt_template;
          baseConfig.system_message = config[ct].system_message;
        }
        if (ct === "basic_gen") {
          baseConfig.content_template = config[ct].content_template;
        }
        if (ct === "basic_gen" || ct === "long_text" || ct === "long_text_multi") {
          baseConfig.embeddings = {
            model: "azure__openai__text_embedding_ada_002",
            strategy: {
              id: "basic",
              num_tokens_per_chunk: 64
            }
          };
        }
        output[ct] = baseConfig;
      }
    });
    return JSON.stringify(output, null, 2);
  };
  const copyToClipboard = () => {
    navigator.clipboard.writeText(generateJSON());
  };
  const downloadJSON = () => {
    const blob = new Blob([generateJSON()], {
      type: "application/json"
    });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "ai-agent-config.json";
    a.click();
    URL.revokeObjectURL(url);
  };
  return <>
      <style>{`
        .mdx-content, #header {
          width: 100%;
          max-width: 1400px;
          padding-left: 1rem;
          padding-right: 1rem;
        }

        @media (min-width: 768px) {
          .mdx-content, #header {
            padding-left: 2rem;
            padding-right: 2rem;
          }
        }

        @media (min-width: 1440px) {
          .mdx-content, #header {
            width: 1000px;
            padding-left: 0;
            padding-right: 0;
          }
        }

        @media (min-width: 1510px) {
          .mdx-content, #header {
            width: 1100px;
            padding-left: 0;
            padding-right: 0;
          }
        }

        @media (min-width: 1740px) {
          .mdx-content, #header {
            width: 1200px;
            padding-left: 0;
            padding-right: 0;
          }
        }

        @media (min-width: 2100px) {
          .mdx-content, #header {
            width: 1400px;
            padding-left: 0;
            padding-right: 0;
          }
        }

        /* The wrapper owns the scrolling, so the code block must not clamp its own height. */
        .ai_agent_code > div,
        .ai_agent_code pre {
          max-height: none;
        }
      `}</style>
      <section className="max-w-[1400px] mx-auto w-full">
        <div className="grid grid-cols-1 min-[900px]:grid-cols-2 gap-8 w-full">
          {}
          <aside className="space-y-6">
            <div>
              <h2 className="text-[28px] font-bold text-gray-900 dark:text-white mb-2">Agent configuration</h2>
              <hr className="border-t border-dashed border-gray-300 dark:border-gray-600 my-3 mb-1" />
              <p className="text-gray-600 dark:text-gray-400">
                Configure your AI agent's settings and LLM adjust parameters.
              </p>
            </div>

            {}
            <div className="space-y-3 border border-1 dark:border-gray-700 rounded-xl p-5">
              <p className=" text-gray-900 dark:text-white text-[19px] font-medium">1. Choose agent type</p>
              <select value={selectedAgentType} onChange={e => handleAgentTypeChange(e.target.value)} className="w-full p-3 pr-8 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white cursor-pointer relative z-10" style={{
    appearance: "none",
    backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%236b7280'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E")`,
    backgroundRepeat: "no-repeat",
    backgroundPosition: "right 12px center",
    backgroundSize: "10px 10px"
  }}>
                {agentTypes.map(type => <option key={type.value} value={type.value}>
                    {type.label}
                  </option>)}
              </select>
            </div>

            {}
            <div className="space-y-3 border border-1 dark:border-gray-700 rounded-xl p-5">
              <p className=" text-gray-900 dark:text-white text-[19px] font-medium">2. Add content types</p>
              <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
                {contentTypes.filter(ct => agentContentTypeIds[selectedAgentType].includes(ct.id)).map(ct => <button type="button" key={ct.id} onClick={() => toggleContentType(ct.id)} className={`p-3 rounded-lg text-left transition-all border ${selectedContentTypes.includes(ct.id) ? "border-blue-500 bg-blue-50 dark:bg-blue-900/20" : "border-gray-200 dark:border-gray-700 hover:border-blue-500"}`}>
                      <h4 className="font-medium text-sm text-gray-900 dark:text-white">{ct.title}</h4>
                      <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">{ct.description}</p>
                    </button>)}
              </div>
            </div>

            {}
            <div className="space-y-3 border border-1 dark:border-gray-700 rounded-xl p-5">
              <p className=" text-gray-900 dark:text-white text-[19px] font-medium">
                3. Configure each content type object
              </p>

              {}
              <div className="flex flex-wrap gap-1 border-b border-gray-200 dark:border-gray-700">
                {selectedContentTypes.map(ct => <button key={ct} onClick={() => setActiveTab(ct)} className={`px-3 py-2 text-sm font-medium transition-colors whitespace-nowrap ${activeTab === ct ? "border-b-2 border-blue-500 text-blue-600 dark:text-blue-400 bg-gray-50 dark:bg-gray-800" : "text-gray-500 hover:text-gray-700 dark:text-gray-400 hover:bg-gray-50 dark:hover:bg-gray-800"}`}>
                    {contentTypes.find(c => c.id === ct)?.title || ct}
                  </button>)}
              </div>

              {}
              {config[activeTab] && <div className="space-y-6 pt-4">
                  {}
                  <div>
                    <h4 className="font-medium text-gray-900 dark:text-white mb-2">3.1 Choose LLM model</h4>
                    <select value={config[activeTab].model} onChange={e => handleModelChange(activeTab, e.target.value)} className="w-full p-3 pr-8 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white cursor-pointer relative z-10" style={{
    appearance: "none",
    backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%236b7280'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'%3E%3C/path%3E%3C/svg%3E")`,
    backgroundRepeat: "no-repeat",
    backgroundPosition: "right 12px center",
    backgroundSize: "10px 10px"
  }}>
                      {models.map(m => <option key={m.value} value={m.value}>
                          {m.label}
                        </option>)}
                    </select>
                  </div>

                  {}
                  <div>
                    <h4 className="font-medium text-gray-900 dark:text-white mb-3">3.2 Fine-tune LLM parameters</h4>
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                      {}
                      {providerParams[getProviderFromModel(config[activeTab].model)].params.map(param => <div key={param.name}>
                          {param.type === "text" ? <>
                              <label className="block text-sm text-gray-600 dark:text-gray-400 mb-1">
                                {param.label}
                              </label>
                              <input type="text" value={config[activeTab][param.name] || ""} onChange={e => updateConfig(activeTab, param.name, e.target.value)} placeholder={`Enter ${param.label.toLowerCase()}`} className="w-full p-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm" />
                            </> : <>
                              <label className="flex justify-between text-sm text-gray-600 dark:text-gray-400 mb-1">
                                <span>{param.label}</span>
                                <span>{config[activeTab][param.name] ?? param.default}</span>
                              </label>
                              <input type="range" min={param.min} max={param.max} step={param.step} value={config[activeTab][param.name] ?? param.default} onChange={e => updateConfig(activeTab, param.name, parseFloat(e.target.value))} className="w-full" />
                              <div className="flex justify-between text-xs text-gray-400 mt-1">
                                <span>{param.min}</span>
                                <span>{param.max}</span>
                              </div>
                            </>}
                        </div>)}
                      {}
                      <div>
                        <label className="flex justify-between text-sm text-gray-600 dark:text-gray-400 mb-1">
                          <span>Max Tokens</span>
                          <span>{config[activeTab].num_tokens_for_completion}</span>
                        </label>
                        <input type="range" min="100" max="10000" step="100" value={config[activeTab].num_tokens_for_completion} onChange={e => updateConfig(activeTab, "num_tokens_for_completion", parseInt(e.target.value))} className="w-full" />
                        <div className="flex justify-between text-xs text-gray-400 mt-1">
                          <span>100</span>
                          <span>10000</span>
                        </div>
                      </div>
                    </div>
                  </div>

                  {}
                  {activeTab !== "spreadsheet" && <div>
                      <h4 className="font-medium text-gray-900 dark:text-white mb-3">
                        3.3 Customize prompts and messages
                      </h4>
                      <div className="space-y-3">
                        <div>
                          <label className="block text-sm text-gray-600 dark:text-gray-400 mb-1">Prompt Template</label>
                          <textarea value={config[activeTab].prompt_template} onChange={e => updateConfig(activeTab, "prompt_template", e.target.value)} placeholder="Enter prompt template" rows={4} className="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm" />
                        </div>
                        <div>
                          <label className="block text-sm text-gray-600 dark:text-gray-400 mb-1">System Message</label>
                          <textarea value={config[activeTab].system_message} onChange={e => updateConfig(activeTab, "system_message", e.target.value)} placeholder="Enter system message" rows={3} className="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm" />
                        </div>
                        {activeTab === "basic_gen" && <div>
                            <label className="block text-sm text-gray-600 dark:text-gray-400 mb-1">
                              Content Template
                            </label>
                            <textarea value={config[activeTab].content_template} onChange={e => updateConfig(activeTab, "content_template", e.target.value)} placeholder="Enter content template" rows={3} className="w-full p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm" />
                          </div>}
                      </div>
                    </div>}
                </div>}
            </div>
          </aside>

          {}
          <nav className="border border-1 dark:border-gray-700 rounded-xl p-5 flex flex-col gap-4 sticky top-[200px] self-start max-h-[calc(100vh-220px)]">
            <div className="flex flex-wrap justify-between items-center gap-2 shrink-0">
              <h3 className="font-semibold text-[19px] text-gray-900 dark:text-white whitespace-nowrap">
                Generated configuration
              </h3>
              <div className="flex gap-2">
                <button onClick={copyToClipboard} className="flex items-center gap-2 px-3 py-1.5 text-sm bg-blue-700 text-white rounded-lg hover:bg-blue-600 transition-all duration-300 ease-in-out">
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24" strokeLinecap="round" strokeLinejoin="round">
                    <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
                    <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
                  </svg>
                  {button || "コピー"}
                </button>
                <button onClick={downloadJSON} className="flex items-center gap-2 px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 text-gray-700 dark:text-gray-300 transition-all duration-300 ease-in-out">
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
                    <polyline points="7 10 12 15 17 10"></polyline>
                    <line x1="12" y1="15" x2="12" y2="3"></line>
                  </svg>
                  Download configuration
                </button>
              </div>
            </div>

            <div className="ai_agent_code flex-1 min-h-0 overflow-auto">
              <CodeBlock language="json" wrap>
                {generateJSON()}
              </CodeBlock>
            </div>
          </nav>
        </div>
      </section>
    </>;
};

<FeatureTilesEN />

<AIAgentConfig button="Copy" />
