Portal logins
The agent signs in to portals such as Sankhya with the login of whoever uses it, without the username and password passing through the conversation.
Some work starts in a portal that asks for a username and password, such as an ERP or a bank’s site. The agent stores that login in Siglata once and, when it needs it, a script on your machine reads it and signs in. The username and password never appear in the conversation, and nobody has to keep them in a .env file.
Each person stores their own login. Two people can each have their own sankhya, so a company skill signs in to the portal as whoever runs it.
Store a login
Ask the agent, for example: “store the Sankhya login”. It calls credential_request with a name and the login’s fields:
return await credential_request({
name: "sankhya",
fields: ["username", "password"],
});
The answer carries a link. Open it and type the values on the page; if Siglata asks you to sign in, sign in and open the link again. The link works once, for an hour, and only for the person who asked. To change the password, ask again with the same name: the new values replace the old ones.
credential_list shows the names, the fields, whose each login is and whether it has values, never the values. isSelected: true marks the login credential_use uses for you.
Skills that sign in to portals
A company skill declares the logins it needs in its SKILL.md frontmatter:
---
name: extrair-pedidos-sankhya
description: Extracts the day's orders from Sankhya.
credentials: [sankhya]
---
skill_find returns that list as credentials. Before running the skill, the agent checks each name with credential_list and, for each missing login, sends the person a credential_request link right away so they type their own. A credentials entry that is not a list of login names makes the file_write of the SKILL.md fail, naming the field.
Use a login
When a script needs the login, the agent calls credential_use and hands the URL to the script. The token follows the # and never appears in a request URL: the script sends { "token" } in a POST to the URL without the #:
return await credential_use({ name: "sankhya" });
name leads to your own login with that name; if you have none, to the company login shared with you. If neither exists, credential_use fails with not_found and the agent asks for yours with credential_request.
The URL works once, for about 60 seconds, and answers with { "name": "sankhya", "values": { "username": "…", "password": "…" } }. Every use is recorded with the login, the person and the time. The agent never opens the URL or shows what it returns.
Who can use it
The login credential_request creates is personal: only the person who created it can use it or change its values. Owners and administrators see that it exists (its name, owner, fields and whether it has values) and can delete it when someone leaves the organization, with credential_delete({ credentialId }), but they can’t use it or read its values. A personal login can’t be shared.
For a login several people use, an owner or administrator creates the company login with visibility: "org":
return await credential_request({
name: "sankhya",
fields: ["username", "password"],
visibility: "org",
});
It serves every member who has no login of their own with that name. To let specific members or teams change its values, grant write with grant_set and the credentialId that credential_list shows. credential_delete removes the values, the open links and the grants.
How the values are kept
The values are encrypted with AES-GCM before they reach the database, under a key of their own, which is itself encrypted under the server’s vault key. The organization is part of the encryption, so a value copied into another organization does not open. The database holds only the ciphertext.