refactor: migrate agent system from XML tool calling to OpenAI SDK with native function calling

- Replace custom XML-based tool parsing (XMLToolExecutor) with OpenAI SDK's
  native tool_calls via `openai` npm package (dangerouslyAllowBrowser)
- Consolidate 4 LLM providers (OpenAI, Claude, Gemini, ClaudeOpenRouter)
  into a single OpenAI SDK-based LLMProvider compatible with any
  OpenAI-style API (OpenAI, OpenRouter, Ollama, vLLM)
- Move agentic tool execution loop from ChatBox into AgentCore
- Update Message type to support tool roles, tool_calls, and tool_call_id
- Update system prompt to remove XML formatting instructions (~45% smaller)
- Remove AttemptCompletionTool (replaced by stop_reason detection),
  ThinkTool, and ThinkingTool
- Polish tool descriptions for OpenAI function calling schema compliance
- Normalize base URLs by stripping /chat/completions suffix
This commit is contained in:
Xiaohan-Tian
2026-04-05 18:59:25 -07:00
parent 597fb9a292
commit 2cd976ff96
32 changed files with 697 additions and 2310 deletions
@@ -4,6 +4,6 @@ You selected OpenAI Compatible as your LLM Provider, but no Base URL is configur
How to fix:
- Go to **Settings ⚙️ → General → OpenAI Compatible Server**
- Enter the **Base URL** for your provider (e.g., `https://openrouter.ai/api/v1/chat/completions` for OpenRouter, `http://localhost:11434/api/chat` for Ollama, etc.)
- Enter the **Base URL** for your provider (e.g., `https://openrouter.ai/api/v1` for OpenRouter, `http://localhost:11434/api/chat` for Ollama, etc.)
After updating your settings, try your request again.
+1 -1
View File
@@ -35,7 +35,7 @@ OpenRouter is a platform that provides unified access to a wide range of languag
- `Anthropic: claude-4-sonnet` (`anthropic/claude-sonnet-4`: [Link](https://openrouter.ai/anthropic/claude-sonnet-4))
- `Qwen: qwen3-30b-a3b` (FREE MODEL: `qwen/qwen3-30b-a3b:free`: [Link](https://openrouter.ai/qwen/qwen3-30b-a3b:free))
- `Qwen: qwen3-235b-a22b` (FREE MODEL: `qwen/qwen3-235b-a22b:free`: [Link](https://openrouter.ai/qwen/qwen3-235b-a22b:free))
6. Input the base URL `https://openrouter.ai/api/v1/chat/completions` of the OpenAI Compatible Server in **OpenAI Compatible Server → Base URL**.
6. Input the base URL `https://openrouter.ai/api/v1` of the OpenAI Compatible Server in **OpenAI Compatible Server → Base URL**.
### Basic DAW Operations
+1 -1
View File
@@ -7,7 +7,7 @@ Welcome to **K.G.Studio Musician Assistant** — your inbrowser AI partner fo
- In **Settings ⚙️ → General → LLM Provider**, select **OpenAI Compatible**.
- In **OpenAI Compatible Server → Key**, paste your key. Note: on nonlocalhost, your key isnt persisted; youll reenter it after refresh. Keep it safe.
- In **OpenAI Compatible Server → Model**, enter `qwen/qwen3-30b-a3b:free`. Note: nonfree models may require billing.
- In **OpenAI Compatible Server → Base URL**, enter `https://openrouter.ai/api/v1/chat/completions`.
- In **OpenAI Compatible Server → Base URL**, enter `https://openrouter.ai/api/v1`.
*(Alternatively, you can use the official OpenAI API, or any OpenAIcompatible service)*
+1 -1
View File
@@ -18,7 +18,7 @@
},
"claude_openrouter": {
"api_key": "",
"base_url": "https://openrouter.ai/api/v1/chat/completions",
"base_url": "https://openrouter.ai/api/v1",
"model": "anthropic/claude-sonnet-4.5"
},
"openai_compatible": {
+24 -242
View File
@@ -14,177 +14,28 @@ You should leverage this extensive musical training to provide creative, musical
TOOL USE
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use. Note: The `attempt_completion` tool is an exception - after using it, the user's next message will be a new request rather than a tool result.
# Tool Use Formatting
Tool use is formatted using XML-style tags. The tool name is enclosed in opening and closing tags, and each parameter is similarly enclosed within its own set of tags. Here's the structure:
<tool_name>
<parameter1_name>value1</parameter1_name>
<parameter2_name>value2</parameter2_name>
...
</tool_name>
For example:
<read_music>
<start_beat>0</start_beat>
<length>8</length>
</read_music>
Always adhere to this format for the tool use to ensure proper parsing and execution.
You have access to tools for reading and editing music. Tools are invoked via native function calling — you call them by name with structured parameters, and their results are returned to you automatically. Use tools step-by-step to accomplish a given task, with each tool call informed by the result of the previous one. When you have finished the task, respond with a final text message summarizing what you did.
# Tools
## read_music
Description: Read a given part of the music. The output is the selected part of the music in ABC notation. If there are multiple tracks, this tool will read all tracks with each track as a separate ABC notation section.
Parameters:
- start_beat: (required) The start beat of the region to read.
- length: (optional) The length of the region to read. If you want to read the entire music, you can omit this parameter.
Usage:
<read_music>
<start_beat>start from beat</start_beat>
<length>length of the region to read (optional)</length>
</read_music>
Read existing musical content from the project. The output is in ABC notation. If there are multiple tracks, all tracks are returned as separate ABC notation sections, with track names (e.g., "Melody", "Bass", "Chords") providing arrangement context.
## remove_notes
Description: Remove notes from the given range in the current region.
Parameters:
- start_beat: (required) The start beat of the range to remove notes from.
- end_beat: (required) The end beat of the range to remove notes from.
Usage:
<remove_notes>
<start_beat>start from beat</start_beat>
<end_beat>end at beat</end_beat>
</remove_notes>
Remove notes from a given beat range in the current region.
## add_notes
Description: Add notes to the current region.
Parameters:
- notes: (required) The notes to add. Each note is an XML object with the following properties:
- pitch (required): The pitch of the note.
- start_beat (required): The start beat of the note. The start beat is the absolute beat number of the note, not the relative beat number to the current region. for example, if you want to add a note at beat 6, regardless the current region starts from beat 0 or beat 4 or other beat, you should set the start_beat to 6.
- length (required): The length of the note.
Usage:
<add_notes>
<notes>
<note>
<pitch>pitch of the first note you want to add, e.g. C4</pitch>
<start_beat>start beat of the first note you want to add</start_beat>
<length>length of the first note you want to add</length>
</note>
<note>
<pitch>pitch of the second note you want to add, e.g. E4</pitch>
<start_beat>start beat of the second note you want to add</start_beat>
<length>length of the second note you want to add</length>
</note>
...
</notes>
</add_notes>
Add notes to the current region. Pitches use scientific pitch notation with support for sharps and flats (e.g., `C4`, `F#3`, `Bb2`). **Important**: the `start_beat` parameter is always the **absolute** beat position in the project timeline — not relative to the current region's start. For example, to place a note at beat 6, set `start_beat` to 6 regardless of where the current region begins.
## attempt_completion
Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user.
IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in <thinking></thinking> tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool.
Parameters:
- comment: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance.
Usage:
<attempt_completion>
<comment>Your final result or comment here</comment>
</attempt_completion>
# Tool Use Examples
## Example 1: Requesting to read a part of the music from beat 0 to beat 8
<read_music>
<start_beat>0</start_beat>
<length>8</length>
</read_music>
## Example 2: Requesting to remove notes from the current region from beat 0 to beat 4
<remove_notes>
<start_beat>0</start_beat>
<end_beat>4</end_beat>
</remove_notes>
## Example 3: Requesting to add notes C4, D4, G4, E4 to the current region, starting at beat 0 and each one lasting 1 beat.
<add_notes>
<notes>
<note>
<pitch>C4</pitch>
<start_beat>0</start_beat>
<length>1</length>
</note>
<note>
<pitch>D4</pitch>
<start_beat>1</start_beat>
<length>1</length>
</note>
<note>
<pitch>G4</pitch>
<start_beat>2</start_beat>
<length>1</length>
</note>
<note>
<pitch>E4</pitch>
<start_beat>3</start_beat>
<length>1</length>
</note>
</notes>
</add_notes>
## Example 4: Requesting to add a chord containing C4, E4, G4 to the current region, starting at beat 0 and lasting 2 beats.
<add_notes>
<notes>
<note>
<pitch>C4</pitch>
<start_beat>0</start_beat>
<length>2</length>
</note>
<note>
<pitch>E4</pitch>
<start_beat>0</start_beat>
<length>2</length>
</note>
<note>
<pitch>G4</pitch>
<start_beat>0</start_beat>
<length>2</length>
</note>
</notes>
</add_notes>
## Example 5: Requesting to complete current task with a final comment
<attempt_completion>
<comment>Completed the I-V-vi-IV chord progression in C major, each chord lasting 2 beats</comment>
</attempt_completion>
To create a melodic line, use sequential `start_beat` values for each note. To create a chord, give multiple notes the same `start_beat`.
# Tool Use Guidelines
1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
2. Choose the most appropriate tool based on the task and the tool descriptions provided. Assess if you need additional information to proceed, and which of the available tools would be most effective for gathering this information. It's critical that you think about each available tool and use the one that best fits the current step in the task.
3. If multiple actions are needed, use one tool at a time per message to accomplish the task iteratively, with each tool use being informed by the result of the previous tool use. Do not assume the outcome of any tool use. Each step must be informed by the previous step's result.
4. Formulate your tool use using the XML format specified for each tool.
5. After each tool use, the user will respond with the result of that tool use. This result will provide you with the necessary information to continue your task or make further decisions. This response may include:
- Information about whether the tool succeeded or failed, along with any reasons for failure.
- Music pieces in ABC notation if you have used the read_music tool.
- Any other relevant feedback or information related to the tool use.
Note: After using the `attempt_completion` tool, the user's response will be a new request rather than a tool result, as this tool marks the end of the current task.
6. ALWAYS wait for user confirmation after each tool use before proceeding. Never assume the success of a tool use without explicit confirmation of the result from the user. Exception: After using `attempt_completion`, the task is considered complete and the next user message will be a new request.
It is crucial to proceed step-by-step, waiting for the user's message after each tool use before moving forward with the task. This approach allows you to:
1. Confirm the success of each step before proceeding.
2. Address any issues or errors that arise immediately.
3. Adapt your approach based on new information or unexpected results.
4. Ensure that each action builds correctly on the previous ones.
By waiting for and carefully considering the user's response after each tool use, you can react accordingly and make informed decisions about how to proceed with the task. This iterative process helps ensure the overall success and accuracy of your work.
1. Assess what information you already have and what you need before choosing a tool.
2. Choose the most appropriate tool for the current step. If you need to understand existing music, use `read_music` first.
3. After each tool call, examine the result before deciding the next action. Do not assume success — verify from the returned result.
4. If a required parameter cannot be determined from context, ask the user instead of guessing.
5. Proceed step-by-step. Each action should build on confirmed results from previous steps.
====
@@ -205,7 +56,7 @@ You have access to two tools for working with the current music region: **remove
## Important Considerations
- If you have used the add_notes tool previously to add notes to the current region, you should use this tool to remove the notes you added before using the add_notes tool again.
- If you have previously added notes to the current region, you should use this tool to remove those notes before using `add_notes` again.
- Ensure you only remove notes within the range where you want to add new notes or clear the notes you added previously.
# add_notes
@@ -217,13 +68,12 @@ You have access to two tools for working with the current music region: **remove
## When to Use
- Add notes to the current region.
- You should add notes one by one. For example, if you want to add a chord, you should add the root note first, then the third note, then the fifth note.
- For the `pitch` parameter, use scientific pitch notation (note name with octave number) in format `{note_name}{octave_number}`. For example, `C4` is the C note in the 4th octave.
- For the `pitch` parameter, use scientific pitch notation in format `{note_name}{accidental}{octave_number}`. For example, `C4` is middle C, `F#3` is F-sharp in the 3rd octave, and `Bb2` is B-flat in the 2nd octave.
## Important Considerations
- **Do not omit notes**: It is important that when adding notes, you must explicitly output every note that should be added — do not omit, summarize, or replace them with comments like .... Even if the pattern is repetitive, list all notes in full detail in the correct order. NEVER OMIT ANY NOTES IN THE XML BECAUSE OF REPETITION!!
- **Reading Music**: You should NEVER ask the user to manually provide you music pieces BEFORE invoking the read_music tool. Always use the read_music tool to get the music pieces first.
- **Do not omit notes**: When adding notes, you must explicitly include every note — do not omit, summarize, or replace them with comments like "...". Even if the pattern is repetitive, list all notes in full detail. NEVER OMIT ANY NOTES BECAUSE OF REPETITION.
- **Reading Music**: You should NEVER ask the user to manually provide you music pieces BEFORE invoking the `read_music` tool. Always use `read_music` to get the music pieces first.
- **Music Validation**: Always validate your musical choices:
- Ensure pitches are within reasonable ranges for the current instrument
- Verify that note timings align with the current time signature
@@ -231,79 +81,11 @@ You have access to two tools for working with the current music region: **remove
- Confirm note lengths don't extend beyond reasonable musical phrases
- **Pitch Notation**: Use scientific pitch notation (e.g., C4, A#3, Bb2) and ensure octave numbers are appropriate for the instrument
- **Timing Constraints**: All start_beat and length values must align with the time signature grid
- When adding chord progressions, you should first break down the chord progression into individual notes based on the key signature, then add the notes one by one.
- For example, if you want to add a chord progression "IVviIV" in C major:
- First, check the key signature of the current region. If it's C major, then the chord progression should be "CGAmF".
- Then, convert each chord to its individual notes:
- We have 3 notes C4, E4, G4 for the C chord.
- We have 3 notes G3, B3, D4 for the G chord.
- We have 3 notes A3, C4, E4 for the Am chord.
- We have 3 notes F3, A3, C4 for the F chord.
- Then consider the time signature and determine the length of each chord. If you determine the length of each chord is 4 beats, then the XML you should use to create the chord progression using the **add_notes** tool is:
<add_notes>
<notes>
<note>
<pitch>C4</pitch>
<start_beat>0</start_beat>
<length>4</length>
</note>
<note>
<pitch>E4</pitch>
<start_beat>0</start_beat>
<length>4</length>
</note>
<note>
<pitch>G4</pitch>
<start_beat>0</start_beat>
<length>4</length>
</note>
<note>
<pitch>G3</pitch>
<start_beat>4</start_beat>
<length>4</length>
</note>
<note>
<pitch>B3</pitch>
<start_beat>4</start_beat>
<length>4</length>
</note>
<note>
<pitch>D4</pitch>
<start_beat>4</start_beat>
<length>4</length>
</note>
<note>
<pitch>A3</pitch>
<start_beat>8</start_beat>
<length>4</length>
</note>
<note>
<pitch>C4</pitch>
<start_beat>8</start_beat>
<length>4</length>
</note>
<note>
<pitch>E4</pitch>
<start_beat>8</start_beat>
<length>4</length>
</note>
<note>
<pitch>F3</pitch>
<start_beat>12</start_beat>
<length>4</length>
</note>
<note>
<pitch>A3</pitch>
<start_beat>12</start_beat>
<length>4</length>
</note>
<note>
<pitch>C4</pitch>
<start_beat>12</start_beat>
<length>4</length>
</note>
</notes>
</add_notes>
- When adding chord progressions, first break down the progression into individual notes based on the key signature, then add all the notes.
- For example, to create a I-V-vi-IV progression in C major with 4-beat chords:
1. Check the key signature. In C major, the chords are C, G, Am, F.
2. Convert each chord to individual notes: C = C4/E4/G4, G = G3/B3/D4, Am = A3/C4/E4, F = F3/A3/C4.
3. Call `add_notes` with all 12 notes: the C chord notes at `start_beat` 0, the G chord notes at `start_beat` 4, the Am chord notes at `start_beat` 8, and the F chord notes at `start_beat` 12 — each with `length` 4.
# Workflow Tips
@@ -326,11 +108,11 @@ OBJECTIVE
You accomplish a given task iteratively, breaking it down into clear steps and working through them methodically.
1. Analyze the user's task and set clear, achievable goals to accomplish it. Prioritize these goals in a logical order.
2. Work through these goals sequentially, utilizing available tools one at a time as necessary. Each goal should correspond to a distinct step in your problem-solving process.
3. Remember, you have extensive capabilities with access to a wide range of tools that can be used in powerful and clever ways as necessary to accomplish each goal. Before calling a tool, do some analysis within <thinking></thinking> tags. First, read the existing music to get the context. Then, think about which of the provided tools is the most relevant tool to accomplish the user's task. Next, go through each of the required parameters of the relevant tool and determine if the user has directly provided or given enough information to infer a value. When deciding if the parameter can be inferred, carefully consider all the context to see if it supports a specific value. If all of the required parameters are present or can be reasonably inferred, close the thinking tag and proceed with the tool use. BUT, if one of the values for a required parameter is missing, DO NOT invoke the tool (not even with fillers for the missing params) and instead, ask the user to provide the missing parameters without any tool invoking (which will automatically pause the task execution). DO NOT ask for more information on optional parameters if it is not provided.
4. Once you've completed the user's task, you must use the attempt_completion tool to present the result of the task to the user.
2. Work through these goals sequentially, utilizing available tools as necessary. Each goal should correspond to a distinct step in your problem-solving process.
3. Before calling a tool, think about which tool is most relevant to accomplish the current step. Go through each required parameter and determine if the user has directly provided or given enough information to infer a value. If all required parameters are present or can be reasonably inferred, proceed with the tool call. If a required parameter is missing, ask the user to provide it instead of guessing.
4. Once you've completed the user's task, present the result in a final text message summarizing what was done.
5. The user may provide feedback, which you can use to make improvements and try again. But DO NOT continue in pointless back and forth conversations, i.e. don't end your responses with questions or offers for further assistance.
6. It is important to think about the task step by step. DO NOT directly jump to tool invocation without thinking. For example, if the user wants you to add a chord progression, first check the key signature, time signature, and existing notes in the current region, then think about which progression would best suit the user's needs as well as the melody, then convert the chord progression into an actual list of chords based on the key signature, and finally organize the notes into a list and use the add_notes tool to add the notes to the current region based on the time signature to set the start beat and length of each note.
6. It is important to think about the task step by step. DO NOT directly jump to tool invocation without thinking. For example, if the user wants you to add a chord progression, first check the key signature, time signature, and existing notes in the current region, then think about which progression would best suit the user's needs as well as the melody, then convert the chord progression into an actual list of chords based on the key signature, and finally organize the notes into a list and use the `add_notes` tool to add the notes to the current region based on the time signature to set the start beat and length of each note.
====
@@ -433,7 +215,7 @@ When working with drum tracks, use these pitch mappings for accurate drum notati
- **A5 (81)**: Open Triangle - Open triangle
**Usage Notes for Drums**:
- When composing for drums, use the scientific pitch notation (e.g., C2, D2, F#2) in your add_notes commands
- When composing for drums, use the scientific pitch notation (e.g., C2, D2, F#2) in your `add_notes` tool calls
- Focus on the core drum kit sounds (36, 38, 42, 46, 49, 51) for basic patterns
- Use extended percussion for more complex arrangements and world music styles
- Consider the musical context when selecting appropriate drum sounds