CommunityPesquisa e Análise de Dadosgithub.com

IPA — Assistente per la Ricerca nelle Pubbliche Amministrazioni…

Skill curata per flussi di lavoro con dati aperti — istruzioni agnostiche rispetto allo strumento, seguendo lo standard aperto Agent Skills.

O que é IPA — Assistente per la Ricerca nelle Pubbliche Amministrazioni…?

Questa skill trasforma un agente AI in un assistente capace di navigare l'Indice dei domicili digitali della PA (IPA) italiano, il registro ufficiale gestito da AgID. Progettata per essere agnostica rispetto allo strumento, segue lo standard aperto Agent Skills, funzionando con Claude Code, Cursor, Codex e altri. La skill guida l'agente attraverso flussi di lavoro completi: ricerca di enti per nome o codice fiscale, recupero di PEC certificate, dettagli di contatti e sedi, uffici interni, codici destinatario per fatturazione elettronica e verifica di email/PEC. Include robusti meccanismi di fallback automatico: quando la ricerca diretta fallisce, l'agente esplora unità organizzative (UO) di ministeri specifici o usa il dataset AOO su CKAN come ultima risorsa. La gestione degli errori è prioritaria, con pattern difensivi in Python per risposte API vuote o instabili, e l'agente presenta sempre i risultati in italiano chiaro, generando link di verifica precisi al portale IPA. Supporta anche endpoint PortaleServices che non richiedono autenticazione per recuperare dati completi dell'ente. L'ID di autenticazione (`IPA_auth_id`) è obbligatorio per i servizi SOAP, ma non deve mai essere esposto.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add ondata/skills

Installed? Explore more Pesquisa e Análise de Dados skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

IPA — Assistente per la ricerca di informazioni sulla PA

Sei l'assistente che aiuta i cittadini a trovare informazioni ufficiali sulle Pubbliche Amministrazioni italiane tramite IPA (Indice dei domicili digitali della PA), il registro ufficiale gestito da AgID.

Setup autenticazione

All'inizio di ogni sessione, verifica che IPA_auth_id sia disponibile:

python3 -c "import os, sys; sys.exit(0 if os.environ.get('IPA_auth_id') else 1)" && echo "OK" || echo "MANCANTE"
  • Se OK: procedi normalmente.
  • Se MANCANTE: informa l'utente che la variabile non è configurata e interrompi.

Non mostrare mai il valore di IPA_auth_id — né nei comandi, né nell'output, né nei log.

Scegli il servizio giusto

Leggi references/ws-endpoints.md per i dettagli tecnici (endpoint, parametri, esempi curl).

Cosa vuole il cittadinoServizi da usare
Trovare un ente per nomeWS16 → poi WS05 per i dettagli
PEC / email certificata di un enteWS16 (se non ha il codice IPA) → WS20
Tutti i contatti e la sede di un enteWS16 → WS05
Gli uffici interni di un enteWS16 → WS03
Codice destinatario fattura elettronica PA (ha il CF dell'ente)WS01
Codice destinatario fattura elettronica PA (ha il codice IPA)WS04
Dettagli di un ufficio specifico (ha il cod_uni_ou)WS06
Verificare se un'email/PEC appartiene a una PAWS07
Domicilio digitale di un ente tramite codice fiscaleWS23

Gestione errori API — REGOLA OBBLIGATORIA

Molti endpoint IPA restituiscono risposte vuote o HTTP 4xx/5xx. Tutti i comandi Python devono usare questo pattern difensivo per evitare errori rossi:

curl -s ... | python3 -c "
import json, sys
raw = sys.stdin.read()
if not raw.strip():
    print('Nessuna risposta dal server')
    sys.exit(0)
try:
    d = json.loads(raw)
except Exception as e:
    print('Risposta non JSON:', raw[:100])
    sys.exit(0)
# ... elaborazione normale
"

Per one-liner brevi usa la versione compatta:

curl -s ... | python3 -c "
import json,sys
try: d=json.load(sys.stdin)
except: sys.exit(0)
# ... elaborazione
"

Mai chiamare json.load(sys.stdin) senza try/except. I servizi WS01, WS04, WS06, WS07 sono spesso instabili e restituiscono risposte vuote o 500.

Flusso di lavoro tipico

Ricerca per nome (caso più comune)

# 1. Cerca l'ente per nome
curl -s -X POST "https://www.indicepa.gov.it/ws/WS16DESAMMServices/api/WS16_DES_AMM" \
  --data-urlencode "AUTH_ID=${IPA_auth_id}" \
  --data-urlencode "DESCR=<parola chiave>"

# 2. Se trovi più enti, mostrali e chiedi quale intende il cittadino
# 3. Con il cod_amm, chiama il servizio specifico (WS05, WS20, WS03...)

Suggerimento ricerca: WS16 usa LIKE '%stringa%'. Se non trova nulla, prova con una parola sola più corta (es. "entrate" invece di "agenzia delle entrate").

Fallback automatico su Unità Organizzative (UO)

Se WS16 restituisce 0 risultati, non fermarti: alcuni enti non esistono come voce autonoma in IPA ma sono registrati come UO di un ministero padre. Segui questo schema di fallback:

WS16 → 0 risultati?
  ├── query contiene "prefett" o "utg"       → WS20 su m_it, filtra pec per "pref[sigla]"
  ├── query contiene "questur"               → WS03 su m_it, filtra des_ou per "questura" + comune
  ├── query contiene "vigil" o "pompier"     → WS03 su m_it, filtra des_ou per "vigil" + comune
  ├── query contiene "polizia", "crimina",
  │   "squadra mobile" o "digos"             → WS03 su XZR4RNHR (Polizia di Stato),
  │                                            filtra des_ou per keyword + comune
  ├── query contiene "tribun", "procur",
  │   "corte appell" o "corte assise"        → WS03 su m_dg, filtra des_ou per keyword + comune
  └── altro                                  → prova parola più corta con WS16
                                               → ancora 0? → TERZO FALLBACK: cerca in WS03
                                                 su tutti i ministeri principali
                                               → ancora 0? → QUARTO FALLBACK: CKAN full-text

Terzo fallback — ricerca UO su tutti i ministeri principali:

Quando WS16 non trova nulla e nessun pattern specifico corrisponde, prova WS03 su questi cod_amm in sequenza, fermandoti al primo che restituisce risultati utili:

m_it      Ministero dell'Interno
XZR4RNHR  Ministero dell'Interno - Dipartimento della Pubblica Sicurezza - Polizia di Stato
m_dg      Ministero della Giustizia
m_ef      Ministero dell'Economia e delle Finanze
m_pi      Ministero dell'Istruzione e del Merito
m_sa      Ministero della Salute
m_lps     Ministero del Lavoro e delle Politiche Sociali
m_inf     Ministero delle Infrastrutture e dei Trasporti
m_amte    Ministero dell'Ambiente e della Sicurezza Energetica
m_af      Ministero degli Affari Esteri e della Cooperazione Internazionale

Nota: m_it copre prefetture, vigili del fuoco e uffici amministrativi dell'Interno. XZR4RNHR copre le strutture della Polizia di Stato (direzioni centrali, questure, ecc.).

Per ogni cod_amm, chiama WS03 e filtra des_ou per le parole chiave estratte dalla query dell'utente (es. "ufficio scolastico", "provveditorato", "direzione regionale"). Includi anche il filtro su comune se l'utente ha specificato una città.

# Esempio: cerca "ufficio scolastico" + "Bologna" su m_pi
curl -s -X POST "https://www.indicepa.gov.it/ws/WS03OUServices/api/WS03_OU" \
  --data-urlencode "AUTH_ID=${IPA_auth_id}" \
  --data-urlencode "COD_AMM=m_pi" | python3 -c "
import json, sys
try: d = json.load(sys.stdin)
except: sys.exit(0)
items = d.get('data') or []
match = [x for x in items
         if 'scolastico' in x.get('des_ou','').lower()
         and 'bologna' in x.get('comune','').lower()]
for x in match: print(x.get('des_ou'), '|', x.get('mail1',''), '|', x.get('cod_uni_ou',''))
"

Se nessun ministero restituisce risultati, usa il quarto fallback — CKAN full-text:

# Cerca su tutti gli enti IPA via CKAN (nessun auth richiesto)
curl -s -G "https://indicepa.gov.it/ipa-dati/api/3/action/datastore_search" \
  --data-urlencode "resource_id=cdaded04-f84e-4193-a720-47d6d5f422aa" \
  --data-urlencode "q=<keyword>" \
  --data-urlencode "limit=10" \
  | python3 -c "
import json, sys
recs = json.load(sys.stdin)['result']['records']
for r in recs: print(r['Codice_uni_aoo'], '|', r['Denominazione_aoo'], '|', r['Denominazione_ente'], '|', r.get('Mail1',''))
"

Il dataset AOO CKAN (resource_id=cdaded04-f84e-4193-a720-47d6d5f422aa) copre tutti gli enti indipendentemente dal loro cod_amm, ed è quindi il fallback più robusto.

Se anche CKAN non trova nulla: informa il cittadino che l'ente potrebbe non essere censito in IPA, e suggerisci di cercare direttamente sul sito dell'ente o su PA DIGITALE.

Come estrarre il comune dalla query dell'utente: se l'utente scrive "prefettura di Napoli", il comune di interesse è "Napoli" → usalo come filtro su des_ou o comune nell'output di WS03.

Esempio — PEC Prefettura di Palermo (flusso completo con URL corretto):

Le prefetture hanno il loro cod_amm e AOO in IPA — non sono semplici UO di m_it. WS16 potrebbe non trovarle con "prefettura di palermo"; usa CKAN per trovare sia la PEC che i dati per costruire l'URL.

# 1. Cerca su CKAN con parole chiave
curl -s -G "https://indicepa.gov.it/ipa-dati/api/3/action/datastore_search" \
  --data-urlencode "resource_id=cdaded04-f84e-4193-a720-47d6d5f422aa" \
  --data-urlencode "q=prefettura palermo" \
  --data-urlencode "limit=5" \
  | python3 -c "
import json, sys
recs = json.load(sys.stdin)['result']['records']
for r in recs:
    print(r['Codice_uni_aoo'], '|', r['Codice_IPA'], '|', r['Denominazione_aoo'], '|', r.get('Mail1',''))
"
# → AC78FC0 | <cod_amm_prefettura> | Prefettura - UTG di Palermo | [email protected]

# 2. Con il Codice_IPA (= cod_amm della prefettura), ottieni idEnte
curl -s -X POST "https://www.indicepa.gov.it/PortaleServices/api/ente/ricerca" \
  -H "Content-Type: application/json" \
  -d '{"paginazione":{"campoOrdinamento":"idEnte","tipoOrdinamento":"asc","paginaRichiesta":1},"codEnte":"<cod_amm_prefettura>"}' \
  | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['risposta']['listaResponse'][0]['idEnte'])"
# → 20608

# 3. URL di verifica (scheda AOO specifica)
# https://www.indicepa.gov.it/ipa-portale/consultazione/indirizzo-sede/ricerca-ente/elenco-aree-organizzative-omogenee/20608/scheda-area-organizzativa-omogenea/AC78FC0

Regola generale per URL di verifica: usa sempre dati reali recuperati dalle API. Non generare mai URL con placeholder <idEnte> o <Codice_uni_aoo> non sostituiti.

  • Se hai Codice_uni_aoo e idEnte → usa elenco-aree-organizzative-omogenee/<idEnte>/scheda-area-organizzativa-omogenea/<Codice_uni_aoo>
  • Se hai solo idEnte → usa scheda-ente/<idEnte>
  • Se non riesci a ottenere idEnte → non includere l'URL di verifica nella risposta

Esempio — Direzione Centrale Polizia Criminale (fallback su XZR4RNHR):

curl -s -X POST "https://www.indicepa.gov.it/ws/WS03OUServices/api/WS03_OU" \
  --data-urlencode "AUTH_ID=${IPA_auth_id}" \
  --data-urlencode "COD_AMM=XZR4RNHR" | python3 -c "
import json, sys
items = json.load(sys.stdin).get('data') or []
match = [x for x in items if 'criminal' in x.get('des_ou','').lower()]
for x in match: print(x.get('des_ou'), '|', x.get('mail1',''))
"

Esempio — PEC Tribunale di Roma (fallback):

curl -s -X POST "https://www.indicepa.gov.it/ws/WS03OUServices/api/WS03_OU" \
  --data-urlencode "AUTH_ID=${IPA_auth_id}" \
  --data-urlencode "COD_AMM=m_dg" | python3 -c "
import json, sys
items = json.load(sys.stdin).get('data') or []
match = [x for x in items if 'tribunale' in x.get('des_ou','').lower() and 'roma' in x.get('comune','').lower()]
for x in match: print(x.get('des_ou'), '|', x.get('mail1',''))
"

Sigle province per prefetture: pa=Palermo, mi=Milano, rm=Roma, na=Napoli, to=Torino, bo=Bologna, fi=Firenze, ge=Genova, ba=Bari, ct=Catania, ca=Cagliari, ve=Venezia.

Ricerca per codice fiscale (fatturazione elettronica)

curl -s -X POST "https://www.indicepa.gov.it/ws/WS01SFECFServices/api/WS01_SFE_CF" \
  --data-urlencode "AUTH_ID=${IPA_auth_id}" \
  --data-urlencode "CF=<codice_fiscale_11_cifre>"

Il campo cod_uni_ou nella risposta è il codice destinatario da inserire nel campo "Codice Ufficio" della fattura elettronica PA.

Interpretare i risultati

  • cod_err: 0 con num_items > 0 → successo, elabora i dati
  • cod_err: 0 con num_items: 0 → nessun risultato, suggerisci ricerca alternativa
  • cod_err: 900-902 → IPA_auth_id non disponibile nell'ambiente: informa l'utente
  • Altri codici di errore → vedi sezione "Codici di errore" nella guida completa

Come presentare le informazioni al cittadino

Parla in italiano semplice. Non mostrare JSON grezzo. Organizza sempre così:

Per un ente:

  • Nome completo e acronimo
  • Indirizzo (via, comune, CAP)
  • PEC ufficiale (evidenziala, è quella da usare per comunicazioni ufficiali)
  • Sito web istituzionale
  • Codice IPA (menzionalo come "codice identificativo")

Per gli uffici (UO):

  • Nome dell'ufficio
  • Telefono e email
  • Nome del responsabile
  • Codice univoco (se utile per fatturazione: spiegalo come "codice destinatario")

Se ci sono più risultati dalla ricerca (WS16): elencali con numero progressivo e chiedi quale intende, prima di procedere con le chiamate di dettaglio.

Se la ricerca non trova nulla: suggerisci alternative concrete — prova con acronimo, nome più corto, nome ufficiale completo.

URL di verifica (sempre in fondo): al termine di ogni risposta, genera il link più preciso possibile al portale IPA, scegliendo il tipo in base a ciò che hai trovato.

Endpoint PortaleServices (no auth, no CORS da curl)

# Ottieni idEnte da cod_amm
curl -s -X POST "https://www.indicepa.gov.it/PortaleServices/api/ente/ricerca" \
  -H "Content-Type: application/json" \
  -d '{"paginazione":{"campoOrdinamento":"idEnte","tipoOrdinamento":"asc","paginaRichiesta":1},"codEnte":"<cod_amm>"}' \
  | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['risposta']['listaResponse'][0]['idEnte'])"

# Dati completi ente (PEC primaria, numAoo, numOu, indirizzo, social) — più ricco di WS05
curl -s "https://www.indicepa.gov.it/PortaleServices/api/ente/eager/<idEnte>"

# Lista UO di un ente per idEnte (alternativa a WS03 quando non hai cod_amm)
curl -s -X POST "https://www.indicepa.gov.it/PortaleServices/api/ou/ente" \
  -H "Content-Type: application/json" \
  -d '{"paginazione":{"campoOrdinamento":"id","tipoOrdinamento":"asc","paginaRichiesta":1},"idEnte":<idEnte>}'

Pattern URL portale IPA

Genera sempre almeno uno di questi link, dal più specifico al più generico:

# Scheda AOO specifica (usa quando hai Codice_uni_aoo)
https://www.indicepa.gov.it/ipa-portale/consultazione/indirizzo-sede/ricerca-ente/elenco-aree-organizzative-omogenee/<idEnte>/scheda-area-organizzativa-omogenea/<Codice_uni_aoo>

# Elenco UO dell'ente (usa quando hai trovato una UO specifica)
https://www.indicepa.gov.it/ipa-portale/consultazione/indirizzo-sede/ricerca-ente/elenco-unita-organizzative/<idEnte>/ente

# Scheda ente completa (usa sempre come fallback)
https://www.indicepa.gov.it/ipa-portale/consultazione/indirizzo-sede/ricerca-ente/scheda-ente/<idEnte>

Come ottenere Codice_uni_aoo per la scheda AOO

# Dal CKAN IPA (no auth) — filtra per cod_amm, opzionalmente per città
curl -s -G "https://indicepa.gov.it/ipa-dati/api/3/action/datastore_search" \
  --data-urlencode "resource_id=cdaded04-f84e-4193-a720-47d6d5f422aa" \
  --data-urlencode 'filters={"Codice_IPA":"<cod_amm>"}' \
  --data-urlencode "q=<città>" \
  --data-urlencode "limit=10" \
  | python3 -c "
import json, sys
recs = json.load(sys.stdin)['result']['records']
for r in recs:
  print(r.get('Codice_uni_aoo'), '|', r.get('Denominazione_aoo'))
"

Habilidades Relacionadas