-
Notifications
You must be signed in to change notification settings - Fork 5
feat: Multi-agent database primitives — batch queries + session agent info #993
Description
Summary
The agent database layer assumes single-agent-per-user throughout. To support multi-agent frontend chat (agent switching, personal agents, multi-agent views), several DB-level primitives are missing.
Related: #972 (per-user dynamic toolsets), #919 (scoped agent creation)
Gap 1: No get_all_by_owner_id() on Agents repository
File: inc/Core/Database/Agents/Agents.php
get_by_owner_id() is hard-coded to LIMIT 1 (line 137). There is no way to list all agents a user owns without fetching the entire agents table:
// Current workaround in AgentAbilities::createAgent() line 503:
$all_agents = $agents_repo->get_all();
$owned = array_filter($all_agents, fn($a) => (int) $a['owner_id'] === $owner_id);This fetches every agent in the system and filters in-memory. Completely wrong at scale.
Needed
public function get_all_by_owner_id(int $owner_id): array {
$rows = $this->wpdb->get_results(
$this->wpdb->prepare(
'SELECT * FROM %i WHERE owner_id = %d ORDER BY agent_id ASC',
$this->table_name,
$owner_id
),
ARRAY_A
);
// ...decode agent_config...
return $rows ?: [];
}Also fix AgentAbilities::createAgent() to use this instead of get_all() + array_filter.
Gap 2: No get_agents_by_ids() batch method
File: inc/Core/Database/Agents/Agents.php
AgentAccess::get_agent_ids_for_user() returns int[] — just IDs. To get full agent rows, callers must make N+1 queries via get_agent() in a loop. This pattern exists in Api/Agents.php::handle_list() for non-admin users.
Needed
public function get_agents_by_ids(array $agent_ids): array {
if (empty($agent_ids)) return [];
$placeholders = implode(',', array_fill(0, count($agent_ids), '%d'));
$rows = $this->wpdb->get_results(
$this->wpdb->prepare(
"SELECT * FROM %i WHERE agent_id IN ({$placeholders}) ORDER BY agent_id ASC",
array_merge([$this->table_name], $agent_ids)
),
ARRAY_A
);
// ...decode agent_config...
return $rows ?: [];
}Gap 3: get_user_sessions() strips agent_id from response
File: inc/Core/Database/Chat/Chat.php lines 507-528
The SELECT * query fetches agent_id from the row, but the return array mapping discards it:
$result[] = [
'session_id' => $session['session_id'],
'title' => $session['title'] ?? null,
'context' => $session['context'] ?? 'chat',
'first_message' => mb_substr($first_message, 0, 100),
'message_count' => count($messages),
'created_at' => ...,
'updated_at' => ...,
// agent_id is NOT included
];The frontend cannot display which agent a session belongs to, making multi-agent session lists impossible.
Needed
- Add
agent_idto the return array - Enrich with
agent_name/agent_slugvia batch post-query lookup usingget_agents_by_ids()
Gap 4: get_all() has no owner_id filter
File: inc/Core/Database/Agents/Agents.php lines 269-306
get_all() accepts $args['site_id'] but ignores any owner_id parameter. Should support $args['owner_id'] for filtered queries.
Gap 5: PermissionHelper::resolve_scoped_agent_id() returns only first agent
File: inc/Abilities/PermissionHelper.php lines 379-425
This method finds ONE agent via get_by_owner_id() (LIMIT 1) or takes the first from get_agent_ids_for_user(). For multi-agent, a companion resolve_all_accessible_agent_ids() is needed.
Checklist
- Add
Agents::get_all_by_owner_id(int $owner_id): array - Add
Agents::get_agents_by_ids(array $agent_ids): array - Add
owner_idsupport toAgents::get_all()args - Add
agent_id(+ optionallyagent_name,agent_slug) toChat::get_user_sessions()return shape - Fix
AgentAbilities::createAgent()to useget_all_by_owner_id()instead ofget_all()+array_filter - Add
PermissionHelper::resolve_all_accessible_agent_ids()or equivalent