ARCA

open-service

arca.gob.ar
InstallationInstalls just this skill for your agent
Side effectread
Authsession (a Clave Fiscal session on the ARCA portal; the login itself is manual and cannot be automated)
Needsnavigate · evaluate · tabs
Summary

Open any ARCA (ex AFIP) Clave Fiscal service by name from the portal, doing the SSO handoff. The service lands in a NEW TAB.

Params
{"servicio":"string, service name as it reads on the portal (default \"Comprobantes en linea\"). Matched case and accent insensitive, exact then prefix then substring"}
Returns
{"done":"bool, true when the service was clicked","ok":"bool","servicio":"string, the exact name matched","origen":"\"destacados\" | \"mis-servicios\"","nuevaPestana":"always true, the portal opens services in a new tab","wait":"bool, true means it navigated to /mis-servicios, call again","error":"string|null","disponibles":"array of every adhered service name, present on servicio_no_encontrado"}
SKILL.md84 lines

arca-open-service

Opens an ARCA Clave Fiscal service from the portal at portalcf.cloud.afip.gob.ar, so nothing between the login and the service has to be clicked by hand.

You cannot deep-link to an ARCA service. Going straight to https://fe.afip.gob.ar/rcel/jsp/index_bis.jsp returns 403 (verified). The portal performs an SSO handoff on click that mints the service session, so the click has to happen on the portal page.

The service opens in a NEW TAB. The extractor cannot switch tabs from inside a page. After done: true, the runner has to select the new tab before doing anything else.

The extractor is fully synchronous, no await. The one asynchronous hop (loading /portal/app/mis-servicios) is expressed as {wait: true} and resolved by calling again.

ARCA (ex AFIP) keeps its service URLs on afip.gob.ar. The catalog domain reads ARCA but the tab must be on portalcf.cloud.afip.gob.ar.

Default action: just call (step 1). The call reports NEEDS_STORE when the extractor is missing or out of date; only then store (step 2) and call again.

Versioning. Gated by VER (must match version in the frontmatter). When evaluate.js changes, bump both.

1. Call

Navigate to https://portalcf.cloud.afip.gob.ar/portal/app/ first, then:

await (() => {
  const KEY = "arca-open-service", VER = "1";
  const s = localStorage.getItem(KEY);
  if (!s || localStorage.getItem(KEY + ":ver") !== VER) return 'NEEDS_STORE';
  const fn = eval('(' + s + ')');
  return fn(document, { servicio: "Comprobantes en linea" });
})()

Run this snippet verbatim. Never add an await before the eval. Only the outer await is allowed.

One call is usually enough: the four tiles under "Servicios | Mas utilizados" are already in the DOM. If the service is not among them the call returns {wait: true, next: "mis-servicios"} and navigates to the full list; call again and it clicks it there.

Then switch to the new tab and continue with whatever skill drives that service.

2. Store (only when step 1 returned NEEDS_STORE)

From a portalcf.cloud.afip.gob.ar tab, evaluate the following with the bridge, replacing <FN> with the contents of evaluate.js. Keep VER equal to the call snippet's:

(() => {
  const KEY = "arca-open-service", VER = "1";
  const fn = (<FN>);
  localStorage.setItem(KEY, String(fn));
  localStorage.setItem(KEY + ":ver", VER);
  return 'stored';
})()

Returns "stored". Then go back to step 1.

Chaining into RCEL

The invoice flow is two skills because they live on two different origins, and localStorage is per origin:

  1. arca-open-service on portalcf.cloud.afip.gob.ar with {servicio: "Comprobantes en linea"}
  2. Switch to the new tab (fe.afip.gob.ar/rcel/jsp/index_bis.jsp)
  3. arca-prepare-invoice in a loop until done: true

Step 3 picks up at the contribuyente selector, so nothing in between is manual.

Notes

Login is manual, by design. Clave Fiscal (plus its second factor if enabled) has to be typed by the user in the browser. This skill starts working once there is a session.

Two layouts. The portal home renders the most-used services as a.full-width; /portal/app/mis-servicios renders every adhered service as an a.panel with the name in an <h3>. The extractor reads both, so it works from either screen.

No href, no onclick. The service cards bind their listeners in JS, so there is nothing to read a URL from. The extractor calls .click() and lets the portal do the handoff.

Works for any service, not just RCEL: "Mis Comprobantes", "Sistema Registral", "Monotributo", "Administrador de Relaciones", whatever is adhered. When the name does not match, the error carries disponibles with the full list.

Errors

  • NEEDS_STORE -> extractor missing or version-mismatched; run step 2 once, then retry.
  • session_expired -> no Clave Fiscal session. The user has to log in by hand.
  • wrong_site -> the tab is not on the portal; navigate to https://portalcf.cloud.afip.gob.ar/portal/app/.
  • servicio_no_encontrado -> not adhered, or the name differs. Read disponibles and retry with an exact name; if it is genuinely missing, it has to be adhered from "Administrador de Relaciones".

Success assertion

{ "type": "json", "jsonPath": "done" }
open-service: a ARCA skill for AI browsing agents · browser-memory