--- name: clip-agent description: Gerir agente Paperclip individual — estado, config, AGENTS.md, histórico runs, issues. Aceita nome como argumento. Usar quando "clip agent", "agente clip", "ver agente", "estado do CTO". context: fork layer: wiki --- # /clip-agent — Gerir Agente Paperclip Aceita argumento: nome do agente (ex: `/clip-agent CTO`). ## Constantes ``` BD: PGPASSWORD="paperclip" psql -h localhost -p 54329 -U paperclip -d paperclip COMPANY_ID: ebe10308-efd7-453f-86ab-13e6fe84004f AGENTS_PATH: /media/ealmeida/Dados/Hub/04-Stack/02.06-Clip/agents/ ``` ## Procedimento ### Passo 1: Contexto completo do agente Invocar tool MCP: `mcp__paperclip__diag_agent_full_context(agent_name="{{NOME}}")` Esta tool retorna config, últimas runs, membership, permissões e tokens — cobre os Passos 1, 3, 6, 7 e 7b de uma só vez. Se multiplos resultados, mostrar lista e pedir clarificacao. ### Passo 2: Hierarquia Quem lhe reporta: ```sql SELECT name, role, status FROM agents WHERE reports_to = '{{AGENT_ID}}' AND company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f' ORDER BY role, name; ``` A quem reporta: ```sql SELECT name, role FROM agents WHERE id = '{{REPORTS_TO_ID}}'; ``` ### Passo 3: Ultimas 5 runs ```sql SELECT hr.status, hr.started_at, hr.finished_at, LEFT(hr.error, 80) as erro FROM heartbeat_runs hr WHERE hr.agent_id = '{{AGENT_ID}}' ORDER BY hr.started_at DESC LIMIT 5; ``` ### Passo 4: Issues atribuidas ```sql SELECT title, status, priority FROM issues WHERE assignee_agent_id = '{{AGENT_ID}}' AND status NOT IN ('done','cancelled') ORDER BY priority, status; ``` ### Passo 4b: Verificar falsos blockers (INC-07) Se o agente tem issues `blocked`, invocar tool MCP: `mcp__paperclip__diag_false_blockers` e filtrar pelo agente. TODO: criar diag_* tool per-agent se uso recorrente. Se `sub_activas > 0` e o agente está operacional → falso blocker. Alertar: "Issue {{ID}} marcada como blocked mas tem sub-tasks activas — deveria ser in_progress." ### Passo 5: AGENTS.md Procurar em `AGENTS_PATH`: ```bash find /media/ealmeida/Dados/Hub/04-Stack/02.06-Clip/agents/ -name "AGENTS.md" -exec grep -l "{{NOME}}" {} \; ``` Se encontrado, ler e apresentar resumo (primeiras 30 linhas). ## Formato de output ``` ## Agente: {{NOME}} **Role:** {{role}} | **Status:** {{status}} | **Ultimo heartbeat:** {{last_heartbeat_at}} **Reporta a:** {{reports_to_name}} | **Budget:** {{spent}}/{{budget}} ({{pct}}%) **Tokens cached:** {{tokens_M}}M | **CWD:** {{cwd}} | **Model:** {{model}} ### Equipa (reportam a este agente) | Nome | Role | Status | ... ### Ultimas 5 runs | Status | Início | Fim | Erro | ... ### Issues atribuidas | Titulo | Status | Prioridade | ... ### Skills atribuidas [lista de desiredSkills ou "Sem skills (apenas built-in paperclip)"] ### AGENTS.md [resumo ou path] ``` ### Passo 6: Skills do agente ```sql SELECT adapter_config->'paperclipSkillSync'->'desiredSkills' as desired_skills FROM agents WHERE id = '{{AGENT_ID}}'; ``` Se nao NULL, listar as skills. Se NULL, indicar "Sem skills atribuidas (apenas built-in paperclip)". Para ver detalhes das skills disponiveis na empresa: ```sql SELECT name, slug, key, source_type FROM company_skills WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f' ORDER BY name; ``` ### Skills atribuídas ao agente ```sql -- Ver skills desejadas (configuradas via API) SELECT a.name as agente, a.adapter_config->'paperclipSkillSync'->'desiredSkills' as desired_skills FROM agents a WHERE a.id = '{{AGENT_ID}}'; ``` **Acções disponíveis:** - Ver skills da empresa: `SELECT name, slug FROM company_skills WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f'` - Atribuir skills via API (fetch no browser): `POST /api/agents/{{AGENT_ID}}/skills/sync` com `{ "desiredSkills": ["slug1", "slug2"] }` ### Membership (OBRIGATÓRIO — sem isto, permissões não funcionam) A função `hasPermission()` verifica **primeiro** se o agente tem membership activa em `company_memberships`. Sem membership → permissão negada mesmo com grants correctos. ```sql -- Verificar membership SELECT status, membership_role FROM company_memberships WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f' AND principal_id = '{{AGENT_ID}}'; ``` Se **0 rows** → agente não tem membership. Criar: ```sql INSERT INTO company_memberships (id, company_id, principal_type, principal_id, status, membership_role, created_at, updated_at) VALUES (gen_random_uuid(), 'ebe10308-efd7-453f-86ab-13e6fe84004f', 'agent', '{{AGENT_ID}}', 'active', 'member', NOW(), NOW()); ``` **Nota:** Agentes criados via SQL directo NÃO recebem membership automaticamente — apenas os onboarded via fluxo OpenClaw/hiring. Sempre criar membership ao adicionar agentes manualmente. ### Permissões do agente ```sql SELECT permission_key FROM principal_permission_grants WHERE company_id = 'ebe10308-efd7-453f-86ab-13e6fe84004f' AND principal_id = '{{AGENT_ID}}'; ``` Para adicionar `tasks:assign` (necessário para delegação): ```sql INSERT INTO principal_permissi