feat: improve AI chat - system prompt, tool output, context window display (#17769)

⚠️ **AI-generated PR — not ready for review** ⚠️

cc @FelixMalfait

---

## Changes

### System prompt improvements
- Explicit skill-before-tools workflow to prevent the model from calling
tools without loading the matching skill first
- Data efficiency guidance (default small limits, use filters)
- Pluralized `load_skill` → `load_skills` for consistency with
`load_tools`

### Token usage reduction
- Output serialization layer: strips null/undefined/empty values from
tool results
- Lowered default `find_*` limit from 100 → 10, max from 1000 → 100

### System object tool generation
- System objects (calendar events, messages, etc.) now generate AI tools
- Only workflow-related and favorite-related objects are excluded

### Context window display fix
- **Bug**: UI compared cumulative tokens (sum of all turns) against
single-request context window → showed 100% after a few turns
- **Fix**: Track `conversationSize` (last step's `inputTokens`) which
represents the actual conversation history size sent to the model
- New `conversationSize` column on thread entity with migration

### Workspace AI instructions
- Support for custom workspace-level AI instructions

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
This commit is contained in:
Félix Malfait
2026-02-09 14:26:02 +01:00
committed by GitHub
parent 6c7c389785
commit 3216b634a3
105 changed files with 3245 additions and 1714 deletions
@@ -12,11 +12,19 @@ import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
export type UserContext = {
firstName: string;
lastName: string;
locale: string;
timezone: string | null;
};
export type AgentActorContext = {
actorContext: ActorMetadata;
roleId: string;
userId: string;
userWorkspaceId: string;
userContext: UserContext;
};
@Injectable()
@@ -87,11 +95,19 @@ export class AgentActorContextService {
workspaceMemberId: workspaceMember.id,
});
const userContext: UserContext = {
firstName: workspaceMember.name?.firstName ?? '',
lastName: workspaceMember.name?.lastName ?? '',
locale: userWorkspace.locale,
timezone: workspaceMember.timeZone ?? null,
};
return {
actorContext,
roleId,
userId: userWorkspace.userId,
userWorkspaceId,
userContext,
};
}
}