mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-27 08:02:39 +00:00
feat: let flow builder operators build AI agents (#11898)
* feat: let flow builder operators build AI agents Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: check linked agents' bound tools and type, validate on the write's transaction Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: bound the linked-agent walk by sorting bound tool ids Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: let builders bind only the agent tool inputs left to the model Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: check every agent tool sharing a bound id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: show builders the agent's own tool inputs read-only and name agents in the setting Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: show the agent's own tool inputs with the read-only step viewer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: give the agent-set inputs heading the input label style Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * style: label the agent's fixed tool inputs static inputs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: address cubic review on agent builder rights Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: check agent writes against the role's flows capability Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: name the flows capability as the agent builder right Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: gate agent evals on the role's code capability Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor: move the composed-flow check into windmill-api-auth Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
da443d2fb2
commit
e5dedd147e
@@ -499,6 +499,43 @@ async fn update_draft(
|
||||
}
|
||||
}
|
||||
|
||||
// An agent draft is held to the rules of its deploy, as a flow draft is: a developer who
|
||||
// tests it in the agent editor runs its tools as themselves.
|
||||
if caps.flows != AuthorLevel::Full && kind == UserDraftItemKind::Resource {
|
||||
if let Some(value) = &req.value {
|
||||
#[derive(Deserialize)]
|
||||
struct ResourceDraft {
|
||||
#[serde(default)]
|
||||
args: serde_json::Value,
|
||||
resource_type: Option<String>,
|
||||
}
|
||||
let draft: ResourceDraft = serde_json::from_str(&strip_json_nul(value.0.get()))
|
||||
.map_err(|e| Error::BadRequest(format!("Invalid resource draft: {e}")))?;
|
||||
// Whatever type the draft names, deploying it over a deployed agent keeps the row's type.
|
||||
let is_agent = draft.resource_type.as_deref() == Some("ai_agent")
|
||||
|| sqlx::query_scalar!(
|
||||
"SELECT EXISTS(SELECT 1 FROM resource WHERE workspace_id = $1 AND path = $2 AND resource_type = 'ai_agent')",
|
||||
&w_id,
|
||||
path,
|
||||
)
|
||||
.fetch_one(&db)
|
||||
.await?
|
||||
.unwrap_or(false);
|
||||
if is_agent {
|
||||
let mut tx = user_db.clone().begin(&authed).await?;
|
||||
windmill_api_auth::composed::validate_operator_agent(
|
||||
&draft.args,
|
||||
&authed,
|
||||
&db,
|
||||
&mut tx,
|
||||
&w_id,
|
||||
)
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A raw-app draft carries the app value and its policy side by side.
|
||||
if caps.apps == AuthorLevel::Compose && kind == UserDraftItemKind::RawApp {
|
||||
if let Some(value) = &req.value {
|
||||
|
||||
Reference in New Issue
Block a user