Einheiten, Stufe 2: das Adressbuch durchsetzen und jedem Agenten seinen Platz sagen (#683)
Durchgesetzt vom Code, nicht nur im Prompt beschrieben: - Nachricht und Spawn an einen Agenten ausserhalb des Adressbuchs werden vor jedem Modellaufruf abgelehnt; die Antwort nennt den offenen Weg (die eigene Leitung, sonst @human). - list_agents zeigt nur noch das Adressbuch. - task_create und task_update pruefen die Zuweisung an einen Agenten gegen dasselbe Adressbuch; sonst liesse es sich ueber eine Aufgabe umgehen. - Die Delegationstiefe folgt der Tiefe des Baums (Tiefe + 1), der eingestellte Wert bleibt Untergrenze. Unterrichtet werden, wie das Konzept verlangt: - OrgBriefing erzeugt einen Abschnitt "# Organisation" im Systemprompt: Einheit mit Pfad und Ziel, seit wann (mit Hinweis, wenn frisch), die effektive Leitung oder "@human", als Leitung die Untereinheiten und neue Mitglieder, und wen man sonst erreicht. Er ist immer wahr, weil er aus dem Baum kommt; ein Umzug aendert ihn von selbst. - In einem laufenden Chat wird nur dieser Abschnitt ersetzt; der uebrige Systemprompt bleibt, wie er war (#193). - Ohne Einheiten gibt es keinen Abschnitt und keine Einschraenkung. Bestehende Instanzen behalten ihren Prompt und ihren Prompt-Cache. AppHost setzt den Organisationsbaum als Provider (frisch je Frage, eine Aenderung gilt ab dem naechsten Lauf) und protokolliert Probleme der Struktur beim Start. Tests: AddressBookEnforcementTests (10), AssignmentReachTests (4). 1.317 gruen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d014a20c38
commit
626fc8d593
@@ -151,6 +151,12 @@ public sealed class TaskboardTool : IAgentTool
|
||||
if (string.IsNullOrWhiteSpace(action))
|
||||
return ToolResult.Fail("'action' is required.");
|
||||
|
||||
// #683: A task for another agent is a way of reaching it — the same address book
|
||||
// applies as for a message, otherwise it could be walked around.
|
||||
if (action is "task_create" or "task_update"
|
||||
&& CheckAssignee(GetString(input, "assignee"), context) is { } outOfReach)
|
||||
return ToolResult.Fail(outOfReach);
|
||||
|
||||
try
|
||||
{
|
||||
return action switch
|
||||
@@ -170,6 +176,26 @@ public sealed class TaskboardTool : IAgentTool
|
||||
}
|
||||
}
|
||||
|
||||
private static string? CheckAssignee(string? assignee, AgentToolContext context)
|
||||
{
|
||||
if (context.Organisation is not { HasUnits: true } org || string.IsNullOrWhiteSpace(assignee))
|
||||
return null;
|
||||
if (TaskAssignee.KindOf(assignee) == TaskAssigneeKind.Human)
|
||||
return null;
|
||||
|
||||
var target = TaskAssignee.AgentId(assignee);
|
||||
if (target.Length == 0 || string.Equals(target, context.AgentId, StringComparison.OrdinalIgnoreCase))
|
||||
return null;
|
||||
if (org.CanAddress(context.AgentId, target))
|
||||
return null;
|
||||
|
||||
var lead = org.EffectiveLeaderOf(context.AgentId);
|
||||
return $"'{target}' is not in your address book, so you cannot assign tasks to it. " +
|
||||
(lead is not null
|
||||
? $"Assign it to your lead '{lead.AgentId}', who can pass it on."
|
||||
: "Assign it to @human.");
|
||||
}
|
||||
|
||||
// ─── Aktionen ───
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user