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_id to the return array
- Enrich with
agent_name/agent_slug via batch post-query lookup using get_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
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 repositoryFile:
inc/Core/Database/Agents/Agents.phpget_by_owner_id()is hard-coded toLIMIT 1(line 137). There is no way to list all agents a user owns without fetching the entire agents table:This fetches every agent in the system and filters in-memory. Completely wrong at scale.
Needed
Also fix
AgentAbilities::createAgent()to use this instead ofget_all()+array_filter.Gap 2: No
get_agents_by_ids()batch methodFile:
inc/Core/Database/Agents/Agents.phpAgentAccess::get_agent_ids_for_user()returnsint[]— just IDs. To get full agent rows, callers must make N+1 queries viaget_agent()in a loop. This pattern exists inApi/Agents.php::handle_list()for non-admin users.Needed
Gap 3:
get_user_sessions()stripsagent_idfrom responseFile:
inc/Core/Database/Chat/Chat.phplines 507-528The
SELECT *query fetchesagent_idfrom the row, but the return array mapping discards it:The frontend cannot display which agent a session belongs to, making multi-agent session lists impossible.
Needed
agent_idto the return arrayagent_name/agent_slugvia batch post-query lookup usingget_agents_by_ids()Gap 4:
get_all()has noowner_idfilterFile:
inc/Core/Database/Agents/Agents.phplines 269-306get_all()accepts$args['site_id']but ignores anyowner_idparameter. Should support$args['owner_id']for filtered queries.Gap 5:
PermissionHelper::resolve_scoped_agent_id()returns only first agentFile:
inc/Abilities/PermissionHelper.phplines 379-425This method finds ONE agent via
get_by_owner_id()(LIMIT 1) or takes the first fromget_agent_ids_for_user(). For multi-agent, a companionresolve_all_accessible_agent_ids()is needed.Checklist
Agents::get_all_by_owner_id(int $owner_id): arrayAgents::get_agents_by_ids(array $agent_ids): arrayowner_idsupport toAgents::get_all()argsagent_id(+ optionallyagent_name,agent_slug) toChat::get_user_sessions()return shapeAgentAbilities::createAgent()to useget_all_by_owner_id()instead ofget_all()+array_filterPermissionHelper::resolve_all_accessible_agent_ids()or equivalent