Skip to content

Conversation

@bobbai00
Copy link
Contributor

@bobbai00 bobbai00 commented Nov 4, 2025

What changes were proposed in this PR?

This PR introduces the LLM agent management & chat panel on the workflow workspace to help users with their workflows.

Demo

  1. Manage agent using the panel
    2025-11-08 14 59 31

  2. Ask agent questions regarding available Texera operators
    2025-11-08 15 00 38

  3. Ask agent about users' current workflow

2025-11-08 15 02 05

Architecture Diagram

See #4034

Major Changes

  1. Frontend: introduce the agent management & chat panel

  2. Backend:

  • New micro service litellm is introduced: which is a open source service that manages the communication between app and LLM APIs
  • AccessControlService is modified: adding the logic for routing litellm related requests

Any related issues, documentation, discussions?

Related to #4034

Current PR limitation and future PR plans

In current PR, the agent is only able to act in a "read-only" way, meaning it can only answer questions regarding operators, but couldn't change user's workflow.

In future PRs,

  • Agent will be able to edit user's workflow
  • Agent feature will be added to k8s deployment architecture.

How was this PR tested?

Frontend unit test cases are added.

To test the PR e2e:

  1. Launch litellm by following the instruction in bin/litellm-config.yaml
  2. Launch AccessControlService
  3. All set! You can now test the agent in workflow workspace.

Was this PR authored or co-authored using generative AI tooling?

The code content is co-authored with Claude code. This PR is not generated by generative AI.

@github-actions github-actions bot added feature dependencies Pull requests that update a dependency file frontend Changes related to the frontend GUI build common and removed common labels Nov 4, 2025
@bobbai00 bobbai00 self-assigned this Nov 4, 2025
@bobbai00 bobbai00 requested a review from aglinxinyuan November 4, 2025 17:15
@chenlica
Copy link
Contributor

chenlica commented Nov 7, 2025

@bobbai00 Please summarize the plan per our discussion. In the new PRs, include a architecture diagram and related screenshots.

@bobbai00
Copy link
Contributor Author

bobbai00 commented Nov 8, 2025

@bobbai00 Please summarize the plan per our discussion. In the new PRs, include a architecture diagram and related screenshots.

Done. They are all reflected in PR description and Issue #4034

Copy link
Contributor

@Xiao-zhen-Liu Xiao-zhen-Liu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested and works well. Left some comments mainly for improving clarity.

I also think we should have a configuration flag for this feature. It would be even better if admins can turn it on / off dynamically.

private model: any;
private modelType = "";
private agentName = "";
private messages: ModelMessage[] = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some comments about these variables? Both messages and agentResponses are messages and it is not immediately clear which does what.

try {
this.model = createOpenAI({
baseURL: new URL(`${AppSettings.getApiEndpoint()}`, document.baseURI).toString(),
apiKey: "dummy",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can this be dummy?

this.notificationService.info(`Agent ${this.agentName} has stopped generation`);
return true;
}
return stepCountIs(50)({ steps });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean?

const tools = this.createWorkflowTools();
let isFirstStep = true;

return from(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the most import part of the life-cycle of agent handling. It would be good if you can have some docs here about what each step / callback does.

this.emitAgentUIMessage("user", message, true, true);
this.messages.push({ role: "user", content: message });

const tools = this.createWorkflowTools();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this have to be created inside sendMessage? Can it be created once inside this class?

<li
nz-menu-item
*ngIf="hasHighlightedLinks() &&
*ngIf="hasHighlightedLinks() &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accidental change?

return this.agentState === CopilotState.GENERATING;
}

public isStopping(): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this method used?


ngOnInit(): void {
// Load saved panel dimensions and position
const savedWidth = localStorage.getItem("agent-panel-width");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be clearer if the logics for setting / loading local storage are contained in their own methods.

onResize({ width, height }: NzResizeEvent): void {
cancelAnimationFrame(this.id);
this.id = requestAnimationFrame(() => {
this.width = width!;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if width or height are undefined? Should there be some default values for such case?

/**
* Create a new agent with the selected model type.
*/
public async createAgent(): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is marked async but doesn’t use await or return a Promise-based flow. Since the logic uses RxJS and subscribe(), it doesn’t need to be async.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build common dependencies Pull requests that update a dependency file feature frontend Changes related to the frontend GUI service

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants