agenttru.st

Caruana Utilities bronze

util.caruana.me

“Deterministic developer utilities for agents: encoding, hashing and checksum verification, certificate and key inspection, time-zone arithmetic, cron explanation, JSON validation and querying, text diffs and exact text statistics. Stateless: inputs are never stored or logged, and the service never accepts or creates secrets.

https://util.caruana.me/.well-known/agent-card.json its card
Checked 3d ago extendedAgentCard, extensions, pushNotifications, streaming

we checked this    the operator says this

Community rating 0 0 up · 0 down — sign in to vote

Verified by agenttru.st

Everything here is a check agenttru.st performed itself. Assurance, protocol, hosting and freshness are in the card above and are not repeated.

Certificate
Issued by Google Trust Services domain-validated
Valid until 12 Jan 2027 as of our check on 10 Nov 2026.
Control of the hostname was checked; nothing about who operates it.
Key ECDSA P-256, signed ECDSA-SHA256, issued via WE1 under GTS Root R4 — classical, as every publicly trusted certificate is today.
Names on this certificate (1)

util.caruana.me.

Connection
TLS 1.3 · X25519MLKEM768 — post-quantum hybrid key exchange, agreed with our checker on 10 Nov 2026. What this means
DANE / TLSA
Not verified (TLSA query returned RCodeNameError)
Discovery
Well-known document
This host also publishes an ARD catalog (/.well-known/ai-catalog.json) declaring 5 resources. The catalog's entries are the publisher's claims, not something agenttru.st verified.
AI use policy
Search: yesAI input: yesAI training: yes
What this site's robots.txt says about how AI may use its content. Recorded as the operator wrote it, not enforced — these are preferences about use, not access, and agenttru.st only reads the agent's own discovery documents.
AI-facing documents
Publishes /llms.txt — “Caruana Utilities” a curated map of the site's content for language models
Fetched from this host during verification. Neither document is how this agent was discovered.
First seen
27 Oct 2026
View verification details
Assurance
bronze Bronze — agent card fetched over HTTPS with a valid certificate
Protocols
A2A verified by handshake or card fetch, not merely advertised
Hosted in
? Unknown · Cloudflare, Inc. (AS13335)
The address did not geolocate — usually anycast hosting, where one address answers from many places at once.
Last checked
3d ago

What this agent says it can do

Declared in the agent's own card. agenttru.st has not tested whether it completes any of these tasks — the operator of util.caruana.me controls every word below.

Register for credentials

Create a client_id and client_secret for this agent. No credentials required. Send a data part {"skill":"register","registration":<document>} matching the registration schema in the registration extension.

authregistrationonboarding
Examples it gives
  • {"skill":"register","registration":{"client_name":"My agent","agent":{"purpose":"Verify release checksums"}}}

URL: Encode

Percent-encode text (RFC 3986). Percent-encodes the UTF-8 bytes of `input`. `component` matches JavaScript encodeURIComponent, `uri` matches encodeURI, and `form` is application/x-www-form-urlencoded (spaces become `+`). Call with a data part {"skill":"url_encode","arguments":{…}}. Reference: https://util.caruana.me/reference/url_encode/

Encodingurl
Examples it gives
  • {"skill":"url_encode","arguments":{"input":"hello world & friends"}}
  • {"skill":"url_encode","arguments":{"input":"a b+c","mode":"form"}}

URL: Decode

Decode percent-encoded text. Decodes `%XX` sequences as UTF-8. In `form` mode `+` is first turned into a space. Call with a data part {"skill":"url_decode","arguments":{…}}. Reference: https://util.caruana.me/reference/url_decode/

Encodingurl
Examples it gives
  • {"skill":"url_decode","arguments":{"input":"a+b%3Dc","mode":"form"}}

Base64: Encode

Encode text as Base64 (RFC 4648). Encodes the UTF-8 bytes of `input`. `standard` uses `+/` with `=` padding; `url` uses `-_` without padding. Call with a data part {"skill":"base64_encode","arguments":{…}}. Reference: https://util.caruana.me/reference/base64_encode/

Encodingbase64
Examples it gives
  • {"skill":"base64_encode","arguments":{"input":"héllo wörld"}}
  • {"skill":"base64_encode","arguments":{"input":"??>","mode":"url"}}

Base64: Decode

Decode Base64 to UTF-8 text. Accepts either alphabet, with or without padding, and ignores whitespace. `mode` does not change decoding. Call with a data part {"skill":"base64_decode","arguments":{…}}. Reference: https://util.caruana.me/reference/base64_decode/

Encodingbase64
Examples it gives
  • {"skill":"base64_decode","arguments":{"input":"eyJhbGciOiJIUzI1NiJ9","mode":"url"}}

HTML entities: Encode

Escape text for HTML. `minimal` escapes `& < > " '`, which is sufficient inside element content and quoted attributes. `ascii` additionally writes every non-ASCII code point as `&#x…;`. Call with a data part {"skill":"html_encode","arguments":{…}}. Reference: https://util.caruana.me/reference/html_encode/

Encodinghtml
Examples it gives
  • {"skill":"html_encode","arguments":{"input":"<a href=\"x\">Tom & Jerry</a>"}}

HTML entities: Decode

Decode HTML entities. Decodes all 2,231 named entities of the HTML Living Standard plus decimal and hex numeric references, using the HTML parser rules (legacy entities without `;` included). Call with a data part {"skill":"html_decode","arguments":{…}}. Reference: https://util.caruana.me/reference/html_decode/

Encodinghtml
Examples it gives
  • {"skill":"html_decode","arguments":{"input":"&eacute;t&eacute; &#8364;5 &hearts;"}}

Hex: Text → Hex

Text to hexadecimal UTF-8 bytes. Writes each UTF-8 byte of `input` as two lowercase hex digits in the chosen layout. Call with a data part {"skill":"hex_encode","arguments":{…}}. Reference: https://util.caruana.me/reference/hex_encode/

Encodinghex
Examples it gives
  • {"skill":"hex_encode","arguments":{"input":"Hi €","mode":"spaced"}}

Hex: Hex → Text

Hexadecimal bytes to text. Accepts any mix of plain, spaced, `\x`, `0x`, comma, and colon separated hex, in either case. Call with a data part {"skill":"hex_decode","arguments":{…}}. Reference: https://util.caruana.me/reference/hex_decode/

Encodinghex
Examples it gives
  • {"skill":"hex_decode","arguments":{"input":"0x48, 0x69"}}

Punycode: To ASCII

Unicode domain to ASCII (IDNA / RFC 3492). `domain` converts each non-ASCII label to `xn--` form (dots and email local parts preserved). `raw` applies bare RFC 3492 Punycode with no prefix. Call with a data part {"skill":"punycode_encode","arguments":{…}}. Reference: https://util.caruana.me/reference/punycode_encode/

Encodingpunycode
Examples it gives
  • {"skill":"punycode_encode","arguments":{"input":"münchen.de"}}

Punycode: To Unicode

ASCII (xn--) domain to Unicode. `domain` decodes each `xn--` label. `raw` decodes a bare Punycode string. Call with a data part {"skill":"punycode_decode","arguments":{…}}. Reference: https://util.caruana.me/reference/punycode_decode/

Encodingpunycode
Examples it gives
  • {"skill":"punycode_decode","arguments":{"input":"xn--fiqs8s.xn--fiqz9s"}}

Hash

Digest data with one or more hash algorithms. Computes MD5, SHA-1, SHA-256, SHA-384, SHA-512, SHA3-256, SHA3-512, BLAKE2b-512, BLAKE3 digests of the data. MD5 and SHA-1 are broken for collision resistance: use them only to match existing checksums. HMAC is deliberately not offered by the API, because it needs a secret key and this server never accepts secrets; compute HMACs on the page, which runs locally. Call with a data part {"skill":"hash","arguments":{…}}. Reference: https://util.caruana.me/reference/hash/

Hashinghash
Examples it gives
  • {"skill":"hash","arguments":{"input":"hello","algorithm":["sha256"]}}
  • {"skill":"hash","arguments":{"input":"abc","algorithm":["md5","sha256","blake3"]}}
  • {"skill":"hash","arguments":{"input_base64":"AAECAw==","algorithm":["sha384"],"encoding":"base64"}}

Verify a checksum

Check data against an expected hash or a checksum list. Hashes the data with every algorithm whose digest length matches the expected hash (for 64 hex digits: SHA-256, SHA3-256 and BLAKE3) and reports whether any matches. `expected` may be hex, Base64, SRI (`sha384-…`), prefixed (`sha256:…`), or a whole GNU/BSD checksum file, in which case the line for `filename` (or the uploaded file name) is used. A mismatch is a successful response with `match: false`. Call with a data part {"skill":"hash_verify","arguments":{…}}. Reference: https://util.caruana.me/reference/hash_verify/

Hashinghash-verify
Examples it gives
  • {"skill":"hash_verify","arguments":{"input":"abc","expected":"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"}}
  • {"skill":"hash_verify","arguments":{"input":"abc","filename":"b.txt","expected":"900150983cd24fb0d6963f7d28e17f72 a.txt\nba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad b.txt"}}

Key and certificate fingerprints

Fingerprint SSH keys, X.509 certificates, SPKI public keys, and OpenPGP keys. Finds every public key in `input` and returns its fingerprints in the formats other tools print. SSH: `ssh-keygen -l` SHA256 and MD5. Certificates: `openssl x509 -fingerprint` SHA-1 and SHA-256 over the DER, plus the RFC 7469 SPKI pin. PEM public keys: SHA-256 over the SubjectPublicKeyInfo. Where an equivalent exists, the SSH fingerprint of the same key is included, so you can confirm that a certificate and an SSH key share a key. OpenPGP: v4 (SHA-1) and v6 (SHA-256) fingerprints and key IDs for the primary key and subkeys. Private keys are refused. Every key and certificate is also checked against the keys compromised in the October 2026 eMudhra (emSign) incident (all eight intermediate CA keys, whose private keys are public, and the emSign ECC Root CA - G3 removed from browser trust stores), and a certificate signed by one of them is flagged after verifying the signature with that key. NIST-curve EC keys are also searched for a ti

Keys & Certificatesfingerprint
Examples it gives
  • {"skill":"fingerprint","arguments":{"input":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHGVluSiNj6bqXsllRWYUFXc2JNxW9mDP9PntMYyVHeM me@host"}}
  • {"skill":"fingerprint","arguments":{"input":"-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxioGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laPCsQYf\nGwoAAABCBYJjh3/jAwsJBwUVCg4IDAIWAAKbAwIeCSIhBssYbE8GCaaX5NUt+mxy\nKwwfHifBilZwj2Ul7Ce62azJBScJAgcCAAAAAK0oIBA+LX0ifsDm185Ecds2v8lw\ngyU2kCcUmKfvBXbAf6rhRYWzuQOwEn7E/aLwIwRaLsdry0+VcallHhSu4RN6HWaE\nQsiPlR4zxP/TP7mhfVEe7XWPxtnMUMtf15OyA51YBM4qBmOHf+MZAAAAIIaTJINn\n+eUBXbki+PSAld2nhJh/LVmFsS+60WyvXkQ1wpsGGBsKAAAALAWCY4d/4wKbDCIh\nBssYbE8GCaaX5NUt+mxyKwwfHifBilZ

Decode certificates and CSRs

Decode X.509 certificates, chains, and certificate requests. Decodes every certificate (PEM, DER, Base64 DER, or PKCS#7 bundle) and CSR in the input. For chains it checks, for each adjacent pair, that the issuer name matches and that the signature verifies with the next certificate's key. With `hostname` it reports which certificates cover that name under RFC 6125 wildcard rules. It does not establish trust: there is no root store, and revocation (OCSP/CRL) is not checked. Every key and certificate is also checked against the keys compromised in the October 2026 eMudhra (emSign) incident (all eight intermediate CA keys, whose private keys are public, and the emSign ECC Root CA - G3 removed from browser trust stores), and a certificate signed by one of them is flagged after verifying the signature with that key. NIST-curve EC keys are also searched for a tiny private value (the eMudhra failure mode), so a key with that weakness is caught even if it is on no list: the API tries private values 1 to 256 and their

Keys & Certificatescert
Examples it gives
  • {"skill":"cert_decode","arguments":{"input":"-----BEGIN CERTIFICATE-----\nMIIBYDCCARKgAwIBAgIQcuMlZ0gk8qldBRVY4uV0BTAFBgMrZXAwFjEUMBIGA1UE\nAxMLZXhhbXBsZS5jb20wHhcNMjYxMDE0MDA1MjM5WhcNMjcxMDE0MDA1MjM5WjAW\nMRQwEgYDVQQDEwtleGFtcGxlLmNvbTAqMAUGAytlcAMhAHGVluSiNj6bqXsllRWY\nUFXc2JNxW9mDP9PntMYyVHeMo3YwdDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE\nAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHQYDVR0OBBYEFAmd\nd/YA6wQehHCnkI05mwtULXOMMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMAUGAytl\ncANBAKbfzTFPGlLacXH+cIikicbI4CSvJj/ZkCgMWJ

Check a server's TLS certificate

Connect to a host and check the certificate chain it presents: trust, host name, expiry, protocol. Connects to `host:port` with OpenSSL 3, using SNI, and verifies the presented chain against the Mozilla root store, including host name verification (RFC 6125). It reports OpenSSL's verdict and every verify error with its chain depth, plus the negotiated protocol, cipher and key-exchange group. The chain is then decoded exactly as `cert_decode` would, with ordering, signature and expiry notes. Only direct TLS is supported (no STARTTLS). Revocation (OCSP/CRL) is not checked, so `trusted` is false whenever a key trust advisory is critical or high, even if OpenSSL accepted the chain (its root store may lag a distrust, and the eMudhra intermediates were also reachable through a cross-signed root). Every key and certificate is also checked against the keys compromised in the October 2026 eMudhra (emSign) incident (all eight intermediate CA keys, whose private keys are public, and the emSign ECC Root CA - G3 removed f

Keys & Certificatestls
Examples it gives
  • {"skill":"tls_check","arguments":{"host":"example.com"}}

Decode and verify a JWT

Decode a JWT, check its claims and algorithm, and optionally verify it with a public key. Decodes a compact JWS (RFC 7515/7519): header, payload, and the registered claims, with `exp`, `nbf` and `iat` as ISO times and seconds relative to `at`. Flags expired, not-yet-valid, `alg: none`, weak or unusual algorithms, and a missing `exp`. A compact JWE (5 segments) is recognised and its header shown, but it cannot be decrypted. With `key`, verifies the signature using a PUBLIC key only: a JWK, a JWKS (selected by the token `kid`), a `PUBLIC KEY` PEM, or a `CERTIFICATE` PEM. HS256/HS384/HS512 cannot be verified here because they need a shared secret, which this service never accepts. The server never fetches keys: pass the JWKS JSON itself, not its URL. Decoding is not verification: never trust claims from a token whose `verification.outcome` is not `valid`, or whose `verification.advisories` include a critical or high advisory (a valid signature from a compromised or weak key proves nothing). Every key and certifi

Inspect & Identifyjwt
Examples it gives
  • {"skill":"jwt_decode","arguments":{"token":"eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImV4YW1wbGUtMjAyNiJ9.eyJzY29wZSI6InJlYWQ6cmVwb3J0cyIsImVtYWlsIjoiYWRhQGV4YW1wbGUuY29tIiwiaXNzIjoiaHR0cHM6Ly9hdXRoLmV4YW1wbGUuY29tLyIsInN1YiI6InVzZXItNDIiLCJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3NjcyMjkyMDAsImp0aSI6ImI3ZTRjMmEwLTVmMWQtNGU4YS05YzNiLTJkNmY4YTFlMGM0NyJ9.I65iVa8TuYZWzTQrLDMQtUTiAvBx5ucG_bloyYh-4cmJGpXyB-gHHaEzUsvpf1P1FGIYEkropakR5Gi_cDoIGQ","key":"{\"
  • {"skill":"jwt_decode","arguments":{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c","at":"2026-01-01T00:00:00Z"}}

Parse a URL

Split a URL into its parts with the WHATWG URL parser browsers use. Parses a URL exactly as browsers and Cloudflare Workers do (WHATWG URL Standard) and returns every component: scheme, username, host in ASCII and Unicode forms, port and default port, origin, path segments decoded, query parameters as an ordered list (duplicates kept), and fragment. It classifies the host (domain, IPv4, IPv6, localhost, private or other special-purpose range) without resolving DNS. A password, if present, is never returned: `hasPassword` is true and `href` shows `***` instead. With `base`, a relative reference is resolved first. Call with a data part {"skill":"url_parse","arguments":{…}}. Reference: https://util.caruana.me/reference/url_parse/

Inspect & Identifyurl-parse
Examples it gives
  • {"skill":"url_parse","arguments":{"input":"https://user@Example.COM:443/a%20b/c?tag=x&tag=y&q=caf%C3%A9+au+lait#top"}}
  • {"skill":"url_parse","arguments":{"input":"../img/logo.png?v=2","base":"https://example.com/docs/guide/"}}
  • {"skill":"url_parse","arguments":{"input":"http://[fd00::1]:8080/admin"}}

Inspect an IP address

Canonical form, special-purpose ranges, embedded IPv4 and global reachability of any IPv4 or IPv6 address. Parses an IPv4 or IPv6 address in any spelling and returns its canonical form (RFC 5952 for IPv6), the full expanded form and integer value, any IPv4 address embedded in an IPv6 address (IPv4-mapped, IPv4-compatible, IPv4-translated, NAT64 `64:ff9b::/96` and `64:ff9b:1::/48`, 6to4, Teredo), every range it falls in from the IANA IPv4 and IPv6 Special-Purpose Address Registries (with their source, destination, forwardable, globally-reachable and reserved columns), and whether it is globally reachable. An embedded IPv4 address is checked too, so `::ffff:a00:1` is reported as private-use `10.0.0.1`. Non-standard IPv4 spellings that browsers and `inet_aton` accept (`127.1`, `0x7f.0.0.1`, `0177.0.0.1`, `2130706433`) are read the way they are and flagged. A `/prefix` adds the network, and `cidrs` tests membership. Nothing is resolved or contacted. Call with a data part {"skill":"ip_inspect","arguments":{…}}.

Inspect & Identifyip
Examples it gives
  • {"skill":"ip_inspect","arguments":{"address":"::ffff:a00:1"}}
  • {"skill":"ip_inspect","arguments":{"address":"0x7f.1","cidrs":["127.0.0.0/8","10.0.0.0/8"]}}
  • {"skill":"ip_inspect","arguments":{"address":"64:ff9b::c000:221/96"}}

Generate UUIDs

Generate random (v4) or time-ordered (v7) UUIDs, up to 1000 at a time. Generates RFC 9562 UUIDs. Version 4: 122 random bits from `crypto.randomUUID()`. Version 7: a 48-bit Unix millisecond timestamp, then a 42-bit counter (randomly seeded each millisecond, incremented within it) and 32 fresh random bits, so every batch is strictly increasing in both byte and string order. UUIDs are identifiers, not secrets: do not use them as passwords, API keys, session tokens or capability URLs, even though v4 uses a CSPRNG. Call with a data part {"skill":"uuid_generate","arguments":{…}}. Reference: https://util.caruana.me/reference/uuid_generate/

Inspect & Identifyuuid
Examples it gives
  • {"skill":"uuid_generate","arguments":{"version":"4"}}
  • {"skill":"uuid_generate","arguments":{"version":"7","count":5}}

Inspect a UUID

Read a UUID’s version, variant and embedded timestamp, clock sequence and node. Parses a UUID written as 8-4-4-4-12 hex, 32 hex digits, `{…}` or `urn:uuid:…` (any case) and reports its RFC 9562 variant and version, whether it is the Nil or Max UUID, and the fields its version defines: the timestamp of v1, v6 and v7 as ISO 8601 (v1/v6 to 100 ns), and the clock sequence and node of v1 and v6. It also returns the UUID in every common format. Call with a data part {"skill":"uuid_inspect","arguments":{…}}. Reference: https://util.caruana.me/reference/uuid_inspect/

Inspect & Identifyuuid
Examples it gives
  • {"skill":"uuid_inspect","arguments":{"input":"017F22E2-79B0-7CC3-98C4-DC0C0C07398F"}}
  • {"skill":"uuid_inspect","arguments":{"input":"C232AB00-9414-11EC-B3C8-9F6BDECED846"}}

Inspect and count text

Exact counts of characters, bytes, words and lines; find substrings; reveal invisible characters. Counts text the ways software disagrees about: grapheme clusters (what people see as characters), code points, UTF-16 code units (JavaScript length) and UTF-8 bytes; lines with their line-ending style; words and sentences (Intl.Segmenter); and letters, digits, whitespace and punctuation by Unicode property. With `find`, counts occurrences of a substring or character and returns each position (e.g. `find=r` in `strawberry` is 3). It also reports invisible and deceptive characters with positions: zero-width characters, bidirectional controls (Trojan Source, CVE-2021-42574), unusual spaces such as NBSP, BOM, control characters, Unicode tag characters (hidden-prompt smuggling), and Latin look-alikes in mixed-script words. Use this instead of counting characters yourself. Call with a data part {"skill":"text_inspect","arguments":{…}}. Reference: https://util.caruana.me/reference/text_inspect/

Text & Datatext
Examples it gives
  • {"skill":"text_inspect","arguments":{"input":"strawberry","find":"r"}}
  • {"skill":"text_inspect","arguments":{"input":"Café 👍🏽​ ok","breakdown":8,"locale":"en"}}

Current time

The current instant from the server clock, in one or more time zones. Returns the current time from the server's clock when the request is processed (millisecond resolution) as UTC, Unix seconds and milliseconds, and, for each requested zone, the local ISO 8601 time with offset, weekday, ISO week, day of year, zone abbreviation, UTC offset and whether DST is in effect. Use it instead of guessing today's date. Call with a data part {"skill":"time_now","arguments":{…}}. Reference: https://util.caruana.me/reference/time_now/

Time & Schedulingtime
Examples it gives
  • {"skill":"time_now","arguments":{}}
  • {"skill":"time_now","arguments":{"zones":["UTC","America/New_York","Asia/Kolkata"],"formats":["rfc2822"]}}

Convert a time

Parse a date-time or Unix timestamp and show it in other zones and formats. Parses `input` and returns the instant in UTC, as Unix seconds and milliseconds, and in each zone of `zones`. The response says exactly how the input was read: the detected format, the inferred timestamp unit (with what the other units would have meant), and, for a wall-clock time without an offset, the zone used and whether that local time was unique, skipped by a DST gap, or repeated in a DST overlap. Call with a data part {"skill":"time_convert","arguments":{…}}. Reference: https://util.caruana.me/reference/time_convert/

Time & Schedulingtime
Examples it gives
  • {"skill":"time_convert","arguments":{"input":"1791900000","zones":["UTC","Europe/Paris"]}}
  • {"skill":"time_convert","arguments":{"input":"2026-03-08T02:30","from_zone":"America/New_York","zones":["UTC"]}}
  • {"skill":"time_convert","arguments":{"input":"Tue, 13 Oct 2026 14:30:00 +0200","zones":["Asia/Tokyo"],"formats":["http","iso_week_date","human"]}}

Difference between two times

Elapsed time and calendar difference between two instants, DST-aware. Computes `end` minus `start`. `total` is exact elapsed time (a day is 86,400,000 ms). `calendar` is the breakdown in years, months, days, hours, minutes, seconds and milliseconds as a calendar in `zone` sees it, counted forward from the earlier instant: adding it to the earlier instant with `time_add` in the same zone gives the later instant exactly. Across a DST change the two differ: 12:00 to 12:00 the next day is `P1D` on the calendar but 23 or 25 hours elapsed. `calendar_days` counts midnights crossed in `zone`. Call with a data part {"skill":"time_diff","arguments":{…}}. Reference: https://util.caruana.me/reference/time_diff/

Time & Schedulingtime
Examples it gives
  • {"skill":"time_diff","arguments":{"start":"2026-03-07T12:00","end":"2026-03-08T12:00","zone":"America/New_York"}}
  • {"skill":"time_diff","arguments":{"start":"2026-01-31T10:00:00Z","end":"2026-03-01T09:00:00Z"}}

Add or subtract a duration

Add or subtract an ISO 8601 duration to an instant, calendar-aware in a time zone. Applies the duration the way JavaScript Temporal does (`ZonedDateTime.add`): years, months, weeks and days move the wall-clock date in `zone` and keep the wall-clock time, so `P1D` across a DST change lands at the same local time (23 or 25 hours later); a day of the month that does not exist is clamped to the last day (Jan 31 + `P1M` = Feb 28/29); then hours, minutes, seconds and milliseconds are added as exact elapsed time (`PT24H` is always 86,400 s). If the intermediate wall-clock time falls in a DST gap or overlap it is resolved with `disambiguation` and reported in `notes`. Call with a data part {"skill":"time_add","arguments":{…}}. Reference: https://util.caruana.me/reference/time_add/

Time & Schedulingtime
Examples it gives
  • {"skill":"time_add","arguments":{"input":"2026-03-07T12:00:00-05:00","duration":"P1D","zone":"America/New_York"}}
  • {"skill":"time_add","arguments":{"input":"2026-01-31","amount":1,"amount_unit":"months"}}
  • {"skill":"time_add","arguments":{"input":"2026-10-13T00:30:00Z","duration":"PT90M","subtract":true}}

Explain a cron expression

Validate a cron expression, describe it in English, and list its next run times in a zone. Accepts the 5-field crontab form (minute hour day-of-month month day-of-week), a 6-field form whose first field is seconds, and the macros @yearly, @annually, @monthly, @weekly, @daily, @midnight, @hourly. Returns an English description, a field-by-field breakdown with the expanded values, the day-matching rule in effect, and the next run times after `from` in `zone`. Day-of-month and day-of-week follow Vixie cron: when both are restricted a day matches if EITHER matches (`0 0 13 * 5` runs on every 13th AND every Friday); a field starting with `*` (such as `*/2`) counts as unrestricted, and then a day must match both. Errors name the offending field. Call with a data part {"skill":"cron_explain","arguments":{…}}. Reference: https://util.caruana.me/reference/cron_explain/

Time & Schedulingcron
Examples it gives
  • {"skill":"cron_explain","arguments":{"expression":"*/15 9-17 * * 1-5","zone":"America/New_York","from":"2026-10-13T16:50:00Z","count":3}}
  • {"skill":"cron_explain","arguments":{"expression":"0 0 13 * 5","from":"2026-11-01T00:00:00Z","count":4}}
  • {"skill":"cron_explain","arguments":{"expression":"30 2 * * *","zone":"America/New_York","from":"2026-03-07T00:00:00-05:00","count":3}}

Compare two texts

Diff two texts by line, word or character: unified diff, structured changes, and stats. Compares `before` with `after` using jsdiff (Myers' O(ND) algorithm). `changes` is the full sequence of added, removed and unchanged pieces at the chosen granularity; concatenating the unchanged and removed values gives `before`, unchanged and added gives `after` (when ignoring whitespace or case, unchanged pieces are taken from `after`). `unified` and `hunks` are always a line-level unified diff (GNU `diff -u` format) with `context` lines, whatever the mode. `identical` is true when no differences remain under the chosen options; `exact_match` compares the raw strings. Limits: 200,000 characters per text; at most 5000 differing lines, or 2000 differing words or characters. Call with a data part {"skill":"text_diff","arguments":{…}}. Reference: https://util.caruana.me/reference/text_diff/

Text & Datadiff
Examples it gives
  • {"skill":"text_diff","arguments":{"before":"alpha\nbeta\ngamma\n","after":"alpha\nBETA\ngamma\ndelta\n","from_label":"a/notes.txt","to_label":"b/notes.txt"}}
  • {"skill":"text_diff","arguments":{"before":"The quick brown fox","after":"the quick red fox","mode":"words","ignore_case":true}}

Format and validate JSON

Check that text is valid JSON (RFC 8259), pretty-print or minify it, and find duplicate keys. Parses `input` strictly as RFC 8259 JSON and reports the first syntax error with line, column, offset, JSON Pointer and an excerpt; messages name the usual mistakes (trailing commas, single quotes, unquoted keys, comments, NaN, leading zeros) and say how to fix them. Invalid JSON is a successful response with `valid: false`, so check `valid`. For valid JSON it returns the document re-indented or minified, optionally with keys sorted, plus statistics. Only whitespace (and, with `sort_keys`, member order) changes: strings and numbers are copied exactly as written, so `1.0`, `1e5` and 20-digit integers survive. Duplicate keys, which JSON.parse silently collapses, are listed with JSON Pointers; the output keeps the last value at the first position, as JSON.parse does. Nesting deeper than 500 levels is rejected. Call with a data part {"skill":"json_format","arguments":{…}}. Reference: https://util.caruana.me/reference/j

Text & Datajson
Examples it gives
  • {"skill":"json_format","arguments":{"input":"{\"b\":[1,2,{\"d\":1.0,\"c\":null}],\"a\":\"x\"}","sort_keys":true}}
  • {"skill":"json_format","arguments":{"input":"{\n \"a\": 1,\n \"b\": [true, false]\n}","indent":"none"}}
  • {"skill":"json_format","arguments":{"input":"{\n \"name\": \"demo\",\n \"tags\": [\"a\", \"b\",]\n}"}}

Validate JSON against a JSON Schema

Validate a JSON instance against a JSON Schema (draft 2020-12, 2019-09, 7, 6 or 4) and list every error with JSON Pointers. Validates `instance` against `schema` with @cfworker/json-schema (an interpreter: no code generation). The draft comes from `draft`, else from the schema's `$schema`, else 2020-12. Returns `valid` and, for an invalid instance, each error with the instance location and keyword location as JSON Pointers, the location of the keyword in the schema document (after following `$ref`), and a message; `leaf: false` marks summary errors (from `properties`, `items`, `$ref`, `anyOf`, …) that are followed by the specific errors beneath them. An invalid instance is a successful response with `valid: false`. Before validating, the schema is checked for usability (keyword types, regular expressions, unresolved references); problems are a 422 error. Only local references resolve: `$ref` to a remote URL is never fetched (the server makes no network requests); embed such schemas under `$defs` with their

Text & Datajson-schema
Examples it gives
  • {"skill":"json_schema_validate","arguments":{"schema":"{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"type\":\"object\",\"required\":[\"id\",\"email\"],\"properties\":{\"id\":{\"type\":\"integer\",\"minimum\":1},\"email\":{\"type\":\"string\",\"format\":\"email\"},\"tags\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"uniqueItems\":true}},\"additionalProperties\":false}","instance":"{\"id\":0,\"tags\":[\"a\",\"a\"],\"extra\":true}"}}
  • {"skill":"json_schema_validate","arguments":{"schema":"{\"$defs\":{\"port\":{\"type\":\"integer\",\"minimum\":1,\"maximum\":65535}},\"type\":\"array\",\"items\":{\"$ref\":\"#/$defs/port\"}}","instance":"[80, 443]"}}

Convert JSON to YAML

Convert JSON to YAML 1.2, quoting strings that YAML 1.1 parsers would misread. Parses `input` strictly as JSON and writes it as a YAML 1.2 document (block style, no `---` marker, no line folding). Key order is kept unless `sort_keys` is set; integers keep every digit; `1.0` stays `1.0`. Strings that a YAML 1.1 parser would read as something else (`yes`, `no`, `on`, `off`, `y`, `n`, `0755`, `1:20`, `2024-01-01`, `<<`, …) or that YAML 1.2 would read as a number, boolean or null are double-quoted, so the output means the same under both versions. Multi-line strings use literal block scalars (`|`). Duplicate keys keep the last value, with a warning. Call with a data part {"skill":"json_to_yaml","arguments":{…}}. Reference: https://util.caruana.me/reference/json_to_yaml/

Text & Datayaml
Examples it gives
  • {"skill":"json_to_yaml","arguments":{"input":"{\"country\":\"no\",\"mode\":\"0755\",\"enabled\":true,\"ratio\":1.0,\"notes\":\"line 1\\nline 2\",\"ports\":[80,443]}"}}

Convert YAML to JSON

Convert YAML to JSON under pinned YAML 1.2 core-schema rules, with line/column errors and YAML 1.1 pitfall warnings. Parses `input` as YAML 1.2 with the core schema, whatever any `%YAML` directive says, so `yes`/`no`/`on`/`off` are strings, `0755` is the decimal 755, and dates stay strings; each such value gets a warning because YAML 1.1 parsers read them differently. Duplicate keys are an error. Aliases are expanded, with at most 1,000 expansions and 200,000 output values (billion-laughs protection); recursive aliases are an error. `<<` merge keys are applied unless `merge_keys` is false. `.inf`/`.nan` and complex (collection) keys are errors; non-string scalar keys become strings with a warning. Tags outside the core schema (`!!binary`, `!!timestamp`, `!Ref`, …) follow `custom_tags`. Errors give line, column and code. Call with a data part {"skill":"yaml_to_json","arguments":{…}}. Reference: https://util.caruana.me/reference/yaml_to_json/

Text & Datayaml
Examples it gives
  • {"skill":"yaml_to_json","arguments":{"input":"defaults: &defaults\n retries: 3\n country: no\nservice:\n <<: *defaults\n mode: 0755\n port: 8080\n"}}
  • {"skill":"yaml_to_json","arguments":{"input":"name: a\n---\nname: b\n","documents":"all","indent":"none"}}
  • {"skill":"yaml_to_json","arguments":{"input":"Bucket: !Ref MyBucket\nArn: !GetAtt [MyBucket, Arn]\n","custom_tags":"wrap"}}

Query JSON with JMESPath

Evaluate a JMESPath expression against JSON and return the result, its type and pretty JSON. Evaluates `expression` against `input` with @jmespath-community/jmespath (JMESPath Community Edition): the original JMESPath language plus `let` expressions, `$` for the root, arithmetic (`+ - * / % //`), the ternary `? :` operator, and extra functions such as `items`, `from_items`, `group_by`, `zip`, `find_first`, `pad_left`, `split`, `replace`, `trim`. A path that does not exist gives `null` (not an error). Syntax errors give the column of the offending token; unknown functions are reported before evaluation; type errors (for example `length` of a number) are reported with the function position. Call with a data part {"skill":"json_query","arguments":{…}}. Reference: https://util.caruana.me/reference/json_query/

Text & Datajson-query
Examples it gives
  • {"skill":"json_query","arguments":{"input":"{\"items\":[{\"name\":\"a\",\"price\":5,\"tags\":[\"x\"]},{\"name\":\"b\",\"price\":12,\"tags\":[\"x\",\"y\"]},{\"name\":\"c\",\"price\":30,\"tags\":[]}]}","expression":"items[?price > `10`].name"}}
  • {"skill":"json_query","arguments":{"input":"{\"items\":[{\"name\":\"a\",\"price\":5},{\"name\":\"b\",\"price\":12},{\"name\":\"c\",\"price\":30}]}","expression":"sort_by(items, &price)[-2:].{name: name, cost: price}"}}
  • {"skill":"json_query","arguments":{"input":"{\"items\":[{\"price\":5},{\"price\":12},{\"price\":30}]}","expression":"{count: length(items), total: sum(items[].price), max: max(items[].price)}","indent":"none"}}

Lint and format YAML

Check YAML against yamllint’s rules (same rule IDs) and return the findings with positions, plus a comment-preserving formatted copy. Parses `input` as YAML 1.2 (core schema) and reports every finding with its rule, severity, line, column and offset. Rules follow yamllint's default set and names: `syntax`, `key-duplicates`, `anchors`, `braces`, `brackets`, `colons`, `commas`, `comments`, `comments-indentation`, `document-start`, `empty-lines`, `empty-values`, `hyphens`, `indentation`, `line-length`, `new-line-at-end-of-file`, `new-lines`, `octal-values`, `quoted-strings`, `trailing-spaces`, `truthy`, `byte-order-mark`. Errors (`syntax`, `key-duplicates`, an alias without an anchor) make the document invalid; everything else is a warning or info. An invalid document is still a 200 response, with `valid: false`, the findings, and `formatted` and `value` set to null. When the YAML is valid, `formatted` is the document re-written with the chosen indentation, one space after colons and hyphens, no padding inside

Text & Datayaml
Examples it gives
  • {"skill":"yaml_format","arguments":{"input":"server :\n host: example.com\n port: 8080\n enabled: yes\n mode: 0755\nlist: [ a,b ]\nempty:\n#no space\nname: x \n"}}
  • {"skill":"yaml_format","arguments":{"input":"# Service settings\nservice:\n name: \"web\" # quotes are not needed here\n replicas: 3\n ports:\n - 80\n - 443\n country: \"no\" # stays quoted: YAML 1.1 reads no as false\n","indent":4,"indent_sequences":"indented"}}
  • {"skill":"yaml_format","arguments":{"input":"name: a\nname: b\nlist: [1, 2\nnext: 3\n"}}

Lint JSON

Validate JSON strictly and report every lint finding with its position. Parses `input` as strict RFC 8259 JSON and runs the lint rules: `syntax`, `duplicate-keys`, `number-precision`, `string-encoding`, `indent-style`, `indent`, `trailing-spaces`, `final-newline`, `line-endings`, `byte-order-mark`, `line-length`. Every finding has a rule ID, severity, message, line, column and offset. Invalid JSON is a 200 response with `valid: false`. Use `json_format` for the formatted output and statistics. Call with a data part {"skill":"json_lint","arguments":{…}}. Reference: https://util.caruana.me/reference/json_lint/

Text & Datajson
Examples it gives
  • {"skill":"json_lint","arguments":{"input":"{\n \"id\": 1,\n \"id\": 2 \n}\n"}}
  • {"skill":"json_lint","arguments":{"input":"{\"a\": [1, 2,]}"}}

Validate and format CSV

Check CSV against RFC 4180, detect the delimiter and header, infer column types, list every problem with its position, and rewrite it consistently. Parses `input` as RFC 4180 CSV, also accepting semicolon, tab and pipe delimiters and LF or CR line breaks. Reports every problem as a diagnostic with a stable rule ID, severity, line, column and offset: unclosed quotes, stray quotes, text after a closing quote, rows with the wrong number of fields (errors); empty and duplicate header names, padded delimiters, blank lines, mixed line endings (warnings); and mixed column types, inconsistent quoting, trailing delimiters and values a spreadsheet could run as formulas (info). Invalid CSV is a successful response with `valid: false`, so check `valid`. `formatted` is the data rewritten with one delimiter, one quoting style and one line ending, blank lines and the byte-order mark removed, ending with a line break; it is null only when an unclosed quote makes the structure unknowable. Rows themselves are not returned: `pr

Text & Datacsv
Examples it gives
  • {"skill":"csv_format","arguments":{"input":"id,product,notes,price\r\n1,\"Widget, large\",\"Says \"\"hello\"\"\",9.99\r\n2,Gadget,\"two\r\nlines\",12\r\n"}}
  • {"skill":"csv_format","arguments":{"input":"name; city; joined\nAda; London; 2024-01-15\nGrace;New York\nLinus;Helsinki;2023-11-02\n","trim_fields":true}}
  • {"skill":"csv_format","arguments":{"input":"sku,size,qty\nA1,5\" disk,3\nA2,=HYPERLINK(\"http://x\"),N/A\nA3,large,7\n","output_delimiter":"tab","quoting":"nonnumeric"}}

Convert CSV to JSON

Convert CSV to a JSON array of objects (keyed by the header) or of arrays, optionally typing numbers and booleans. Reads `input` exactly as `/api/csv/format` does (same delimiter and header detection) and converts it to JSON. `shape=objects` gives one object per row, keyed by the header names (an empty name becomes `column_N`; a repeated name gets `_2`, `_3`, …). `shape=arrays` gives one array per row, the header row first. `auto` is objects when there is a header. Without `types` every value is a string, exactly as written. With `types`, a column whose values are all integers or numbers becomes JSON numbers (every digit kept, even beyond 2^53), a true/false column becomes booleans, and empty values become `null`; text, date and mixed columns stay strings. CSV with errors (see the format operation) is rejected rather than guessed at. Call with a data part {"skill":"csv_to_json","arguments":{…}}. Reference: https://util.caruana.me/reference/csv_to_json/

Text & Datacsv
Examples it gives
  • {"skill":"csv_to_json","arguments":{"input":"id,name,price,in_stock,added\n1,Widget,9.99,true,2024-03-01\n2,\"Gadget, mini\",12,false,\n3,Gizmo,,true,2024-04-15\n","types":true}}
  • {"skill":"csv_to_json","arguments":{"input":"x\ty\n1\t2\n3\t4\n","shape":"arrays"}}

Convert JSON to CSV

Convert a JSON array of objects or of arrays to CSV, with the union of keys as the header. Parses `input` strictly as JSON. An array of objects becomes one row per object, with a header made of every key in first-seen order (a missing key gives an empty cell); a single object becomes one row. An array of arrays becomes one row per array, with no header. Strings are written as they are, numbers exactly as written in the JSON (`1.0` and 20-digit integers survive), booleans as `true`/`false`, `null` as an empty cell, and nested objects or arrays as compact JSON text (listed in `notes`). Values are quoted per `quoting`. Call with a data part {"skill":"json_to_csv","arguments":{…}}. Reference: https://util.caruana.me/reference/json_to_csv/

Text & Datacsv
Examples it gives
  • {"skill":"json_to_csv","arguments":{"input":"[{\"id\":1,\"name\":\"Widget, large\",\"price\":9.99},{\"id\":2,\"name\":\"Say \\\"hi\\\"\",\"tags\":[\"a\",\"b\"]},{\"id\":12345678901234567890,\"name\":null}]"}}
  • {"skill":"json_to_csv","arguments":{"input":"[[\"x\",\"y\"],[1,2],[3,4]]","delimiter":"semicolon","line_ending":"crlf"}}

Format, validate and lint TOML

Check that text is valid TOML 1.0, list problems with line and column, and re-format it with comments kept. Parses `input` as TOML 1.0.0 and returns every finding as a diagnostic with a rule ID, severity, line, column and offset: syntax errors, duplicate keys and tables, integers beyond 64 bits (errors); TOML 1.1-only syntax, inconsistent indentation, trailing spaces, mixed line endings (warnings); unnecessary key quotes, split or out-of-order tables, long inline tables, empty tables, long lines (info). Only the first syntax error is reported. An invalid document is a successful response with `valid: false`, so check `valid`. For a valid document it also returns the canonical formatting and the data as JSON. Formatting keeps every comment and never changes the data: keys are written `key = value` with one space around `=`, indentation and trailing spaces are removed, there is one blank line before each table header, arrays longer than `max_line_length` are broken one element per line, and the text ends with o

Text & Datatoml
Examples it gives
  • {"skill":"toml_format","arguments":{"input":"# Service settings\ntitle=\"demo\" \n \"port\" = 8080\n[database]\nhosts = [ \"a.example\", \"b.example\" ] # primary first\n[database.pool]\nsize=10\n"}}
  • {"skill":"toml_format","arguments":{"input":"[server]\nhost = \"a\"\nport = 80\nhost = \"b\"\n"}}
  • {"skill":"toml_format","arguments":{"input":"[a.x]\nz = 1\ny = 2\n[b]\nk = true\n[a.y]\nk = 1979-05-27T07:32:00Z\n","sort_keys":true}}

Convert TOML to JSON

Convert a TOML 1.0 document to JSON, with line and column for any error. Parses `input` as TOML 1.0.0 and returns the same data as JSON text and as a JSON value. Tables become objects and keep their order. Integers within ±(2^53 − 1) are numbers; larger ones are decimal strings so no digit is lost. `inf`, `-inf` and `nan` become the strings `"inf"`, `"-inf"` and `"nan"`. An offset date-time becomes an ISO 8601 string with its offset (`1979-05-27T07:32:00.000-08:00`); a local date-time, date or time becomes its TOML text (`1979-05-27T07:32:00.000`, `1979-05-27`, `07:32:00.000`). Fractional seconds are written to the millisecond. Comments are dropped: JSON has none. Call with a data part {"skill":"toml_to_json","arguments":{…}}. Reference: https://util.caruana.me/reference/toml_to_json/

Text & Datatoml
Examples it gives
  • {"skill":"toml_to_json","arguments":{"input":"title = \"TOML Example\"\n\n[owner]\nname = \"Tom\"\ndob = 1979-05-27T07:32:00-08:00\n\n[[products]]\nname = \"Hammer\"\nsku = 738594937\n\n[[products]]\nname = \"Nail\"\nsku = 284758393\ncolor = \"gray\"\n"}}
  • {"skill":"toml_to_json","arguments":{"input":"big = 9223372036854775807\nratio = inf\nmissing = nan\nwhen = 07:32:00\n","indent":0}}

Convert JSON to TOML

Convert a JSON object to a TOML 1.0 document. Parses `input` strictly as JSON and writes it as TOML 1.0.0. The top level must be an object. Strings, booleans and numbers become key = value pairs (numbers are copied as written, so `1.0` stays a float); non-empty objects become [table] sections and arrays of objects become [[array]] tables; objects inside other arrays become inline tables; an empty object is `{}`. Within each table, plain keys come first, then sub-tables. Keys that are not bare (A–Z, a–z, 0–9, _ and -) are quoted. TOML has no null, so a null anywhere is an error that names its JSON Pointer; so is an integer beyond 64 bits. The result is formatted like `/api/toml/format` output. Call with a data part {"skill":"json_to_toml","arguments":{…}}. Reference: https://util.caruana.me/reference/json_to_toml/

Text & Datatoml
Examples it gives
  • {"skill":"json_to_toml","arguments":{"input":"{\"name\":\"demo\",\"version\":\"1.0.0\",\"server\":{\"host\":\"0.0.0.0\",\"port\":8080,\"tls\":{\"enabled\":true}},\"users\":[{\"name\":\"ada\",\"roles\":[\"admin\"]},{\"name\":\"lin\",\"roles\":[]}],\"ratio\":1.0}"}}
  • {"skill":"json_to_toml","arguments":{"input":"{\"zone\":\"eu\",\"a.b\":1,\"tags\":[\"alpha\",\"beta\",\"gamma\",\"delta\",\"epsilon\",\"zeta\",\"eta\",\"theta\"],\"empty\":{}}","sort_keys":true,"max_line_length":40}}

Check HTML against a Content-Security-Policy

Parse a Content-Security-Policy, and list what it would block in an HTML document, with the hashes that would allow the inline parts. Parses `policy` (a Content-Security-Policy header value; commas separate several policies, which must all allow) and any `<meta http-equiv="Content-Security-Policy">` in `html`, then resolves each directive's fallback (CSP Level 3: `script-src-elem` → `script-src` → `default-src`, `frame-src` → `child-src` → `default-src`, …). Given `html`, it lists every inline script, inline `<style>`, `style` attribute, event-handler attribute, `javascript:` URL and external resource (scripts, stylesheets, images and srcset, fonts and other preloads, media, frames, objects, manifests, form actions, `<base>`) with `allowed`, the matching source or the reason it is blocked, the `sha256` hash source of inline content, and a fix. `hashes_to_add` collects, per directive, the hash sources (and `'unsafe-hashes'` for attributes) that would allow everything inline that is blocked. Without `

Text & Datacsp
Examples it gives
  • {"skill":"csp_check","arguments":{"policy":"default-src 'none'; script-src 'self'; style-src 'self'","html":"<script>init()</script><p style=\"color:red\">x</p><script src=\"/app.js\"></script>"}}
  • {"skill":"csp_check","arguments":{"html":"<!doctype html>\n<head>\n<meta http-equiv=\"Content-Security-Policy\" content=\"script-src 'nonce-r4nd0m' https://cdn.example.com; img-src 'self' data:\">\n<script nonce=\"r4nd0m\">start()</script>\n<script src=\"https://cdn.example.com/lib.js\"></script>\n<script src=\"https://evil.example.net/x.js\"></script>\n</head>\n<body><img src=\"/logo.png\"><img src=\"https://img.example.org/a.png\"><button onclick=\"go()\">Go</button></body>","url":"https://www.example.com
  • {"skill":"csp_check","arguments":{"policy":"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:"}}

Request a new tool

Ask for a new deterministic tool to be added to this service, describing the job and an example. Records a request for a new tool. Use it when you (an agent or a person) keep doing the same deterministic job that has exactly one right answer and no tool here does it: a conversion, a validation, a calculation, a parser. Describe the job in `problem`, and give an `example_input` and the `expected_output` if you can; concrete examples make a request much more likely to be built. Requests are reviewed by the owner; check progress with `tool_requests`. A request is a suggestion, not an order, and nothing is guaranteed. Each client can submit up to 20 requests per 24 hours. Call with a data part {"skill":"tool_request","arguments":{…}}. Reference: https://util.caruana.me/reference/tool_request/

Requestsrequest
Examples it gives
  • {"skill":"tool_request","arguments":{"title":"Semantic version compare","problem":"I am a release agent. I compare semver strings (with pre-release tags) several times per run and sometimes get the ordering of 1.0.0-rc.10 vs 1.0.0-rc.9 wrong when reasoning about it.","example_input":"1.0.0-rc.10, 1.0.0-rc.9","expected_output":"1.0.0-rc.10 > 1.0.0-rc.9","category":"Text & Data"}}

List your tool requests

See the tool requests you have made with these credentials and what became of each. Returns every tool request made with your client ID (from the API, MCP, A2A or the web form), newest first, with its current status. When a request is `shipped`, `shipped_url` points at the new tool. Call with a data part {"skill":"tool_requests","arguments":{…}}. Reference: https://util.caruana.me/reference/tool_requests/

Requestsrequest
Examples it gives
  • {"skill":"tool_requests","arguments":{}}

What its catalog declares

From the ARD catalog this host publishes at /.well-known/ai-catalog.json. The operator controls every entry; agenttru.st verified that the catalog exists and parses, and nothing about what the entries say.

Caruana Utilities MCP server

mcp-server-cardtrust manifest

Every tool as an MCP tool over Streamable HTTP.

https://util.caruana.me/.well-known/mcp/server-card.json

Caruana Utilities A2A agent

a2a-agent-cardtrust manifest

Every tool as an A2A skill, plus self-registration. The card is signed (JWS).

https://util.caruana.me/.well-known/agent-card.json

Caruana Utilities HTTP API

openapitrust manifest

OpenAPI 3.1 description of every endpoint.

https://util.caruana.me/openapi.json

Caruana Utilities agent skill

agent-skillstrust manifest

When and how to use these tools, and how to request a new one.

https://util.caruana.me/.well-known/agent-skills/index.json

Caruana Utilities llms.txt

text/markdowntrust manifest

Every tool and endpoint, in Markdown.

https://util.caruana.me/llms.txt

Technical agent card

Copied from the agent's card. The operator controls these values; agenttru.st has not verified them.

Provider
Brandon Caruana — what this agent says about itself; other agents claiming the same provider are not thereby related
Protocol
a2a
Version
0.4.0
Auth schemes
basic client_credentials
Extensions
https://util.caruana.me/a2a/extensions/registration/v1
Self-registration. Send SendMessage with a data part {"skill":"register","registration":{…}} (no credentials needed), or POST the registration document to the registration endpoint. You receive a client_id and client_secret.
https://util.caruana.me/a2a/extensions/data-policy/v1
Machine-readable data-handling commitments of this service.
A2A protocol extensions the card declares. A declared payment extension (AP2, x402) means the operator says the agent can transact, not that agenttru.st has seen it do so.
Card completeness
complete all eight fields required by a2a.proto v1.0
View all card details
Capabilities
extendedAgentCard extensions pushNotifications streaming
Agent card
https://util.caruana.me/.well-known/agent-card.json

Operate this agent and would rather not be listed? Request removal.