fix(tools): add missing tools to goclaw group and relax agent update ownership

- Add 10 missing tools to the goclaw group in policy.go: skill_manage,
  publish_skill, use_skill, delegate, memory_expand, knowledge_graph_search,
  vault_search, create_audio, datetime, heartbeat. Fixes skill creation
  permission denied when agents use group:goclaw allow list.

- Relax agent update ownership check: tenant admins can now update any
  agent in their tenant (adminMiddleware + tenant-scoped GetByID already
  ensures proper authorization). Previously only agent owner or system
  owner could update.

- Improve agent update error logging: include user_id and tenant_id in
  structured log, return actual error message instead of generic
  "internal error" for better debugging.
This commit is contained in:
viettranx committed 2026-04-12 12:37:53 +07:00
1 parent 35ce8cc2c5
commit e043241dea
2 files changed
+15 -11

No files matched your search

+7 -7
View File
@@ -347,16 +347,15 @@ func (h *AgentsHandler) handleUpdate(w http.ResponseWriter, r *http.Request) {
return
}
// Only owner can update
// Tenant admins can update any agent in their tenant (adminMiddleware already
// verified RoleAdmin). System owners can update any agent across tenants.
// GetByID respects tenant scoping from context, so if the agent is returned
// it belongs to the caller's tenant.
ag, err := h.agents.GetByID(r.Context(), id)
if err != nil {
writeError(w, http.StatusNotFound, protocol.ErrNotFound, i18n.T(locale, i18n.MsgNotFound, "agent", id.String()))
return
}
if userID != "" && ag.OwnerID != userID && !h.isOwnerUser(userID) {
writeError(w, http.StatusForbidden, protocol.ErrUnauthorized, i18n.T(locale, i18n.MsgOwnerOnly, "update agent"))
return
}
var updates map[string]any
if !bindJSON(w, r, locale, &updates) {
@@ -426,8 +425,9 @@ func (h *AgentsHandler) handleUpdate(w http.ResponseWriter, r *http.Request) {
}
if err := h.agents.Update(r.Context(), id, allowed); err != nil {
slog.Error("agents.update", "id", id, "error", err)
writeError(w, http.StatusInternalServerError, protocol.ErrInternal, i18n.T(locale, i18n.MsgFailedToUpdate, "agent", "internal error"))
slog.Error("agents.update", "id", id, "user_id", userID,
"tenant_id", store.TenantIDFromContext(r.Context()), "error", err)
writeError(w, http.StatusInternalServerError, protocol.ErrInternal, i18n.T(locale, i18n.MsgFailedToUpdate, "agent", err.Error()))
return
}
+8 -4
View File
@@ -28,12 +28,16 @@ var toolGroups = map[string][]string{
"goclaw": {
"read_file", "write_file", "list_files", "edit", "exec",
"web_search", "web_fetch", "browser",
"memory_search", "memory_get",
"memory_search", "memory_get", "memory_expand",
"knowledge_graph_search", "vault_search",
"sessions_list", "sessions_history", "sessions_send", "spawn", "session_status",
"cron", "message", "create_forum_topic", "list_group_members",
"delegate",
"cron", "datetime", "heartbeat",
"message", "create_forum_topic", "list_group_members",
"read_image", "read_document", "read_audio", "read_video",
"create_image", "create_video",
"skill_search", "mcp_tool_search", "tts",
"create_image", "create_video", "create_audio",
"skill_search", "skill_manage", "publish_skill", "use_skill",
"mcp_tool_search", "tts",
"team_tasks",
},
}