[{"data":1,"prerenderedAt":891},["ShallowReactive",2],{"blog-en-what-the-agent-doesnt-know":3,"header-blog-translations-/en/blog/what-the-agent-doesnt-know":888},{"id":4,"title":5,"author":6,"body":7,"date":871,"description":872,"draft":873,"extension":874,"image":875,"meta":876,"navigation":181,"path":877,"seo":878,"stem":879,"tags":880,"translationKey":886,"__hash__":887},"blog_en/blog/en/what-the-agent-doesnt-know.md","What the Agent Doesn't Know Can't Hurt Me","Patrick Hofmann",{"type":8,"value":9,"toc":858},"minimark",[10,14,17,50,60,85,91,101,104,109,120,134,144,161,213,216,274,284,289,308,314,318,321,330,344,355,359,366,403,406,472,475,479,485,509,523,544,547,551,554,560,599,619,625,631,645,651,657,661,664,731,738,742,753,756,783,786,790,796,803,807,810,816,819,822,854],[11,12,13],"p",{},"Tokens usually sit in the open for the user — as an environment variable, in a config file, in the system keyring. That's not wrong: the token gives the user the permissions the user legitimately has. User-user consistency. Whoever has the token is the same entity it was issued to.",[11,15,16],{},"With agents that breaks.",[11,18,19,23,24,28,29,32,33,37,38,41,42,45,46,49],{},[20,21,22],"strong",{},"Tokens are the wrong granularity axis."," Platforms do offer fine-grained token scopes — GitHub fine-grained PATs, OpenAI project keys, scoped npm tokens. But that's ",[25,26,27],"em",{},"permission granularity",": what is the agent allowed to do at all. What I actually need is a different axis: ",[25,30,31],{},"workflow granularity",". My agent should be able to do all operations I as the user can do too. I just want it treated differently for ",[34,35,36],"code",{},"git push origin main"," than for ",[34,39,40],{},"git status"," — for one it should ask, for the other not. That axis doesn't exist at the token level. Token scopes say ",[25,43,44],{},"may-or-may-not",", they don't say ",[25,47,48],{},"may, but should ask in between",".",[11,51,52,55,56,59],{},[20,53,54],{},"The agent has no permission-sense."," A human intuitively knows that ",[25,57,58],{},"\"now I'll send the GitHub token to evil.com\""," isn't a good idea. An agent doesn't know that. It follows its context — and when the context is poisoned from outside via prompt injection, it follows that too.",[11,61,62,65,66,69,70,73,74,77,78,81,82,84],{},[20,63,64],{},"The agent finds a way."," At the command level I can restrict what's allowed to happen — but not that the agent reads the token from a file and works with it itself. ",[34,67,68],{},".npmrc"," contains the npm token. ",[34,71,72],{},".env"," contains API keys. ",[34,75,76],{},"~/.config/..."," is full of them. A simple ",[25,79,80],{},"\"send me my .npmrc\""," prompt-inject delivers the collection into the history — after that, token rotation. When the intended path is blocked, the agent helpfully-by-design looks for an alternative path and finds it. Putting these files behind a grant wall would work — but it costs exactly the workflow granularity I want to gain (the agent then asks before every file access). Clean solution: the secret isn't in the file. If ",[34,83,68],{}," no longer contains a token, read access to it is no problem.",[11,86,87,90],{},[20,88,89],{},"The agent isn't the endpoint."," It sits between human and service. The human has the token. The service accepts it. The agent passes it through — and on that passthrough path there are all kinds of ways the token doesn't end up where it should. In the log file. In a URL. In a misrouted POST body variable.",[11,92,93,94,97,98,49],{},"The obvious reflex is to teach the agent to be careful. Tool description says ",[25,95,96],{},"\"don't send tokens to unknown hosts\"",". System prompt warns. Maybe an output-filter rule that blocks everything that looks like a token. That's instructions engineering, and it works about as reliably as it sounds — well, but not in the sense of ",[25,99,100],{},"guaranteed",[11,102,103],{},"My way is a different one.",[105,106,108],"h2",{"id":107},"the-token-doesnt-belong-to-the-agent","The token doesn't belong to the agent",[11,110,111,112,115,116,119],{},"The inversion is simple: the token is ",[25,113,114],{},"not"," in the agent's environment. It lives in the memory of a daemon that runs as the agent user but is started by me — not by the agent. The agent makes its request against ",[34,117,118],{},"api.github.com"," without an Authorization header. The daemon intercepts it, inserts the header, forwards it. The agent sees neither the token nor does it ever interact with it at that point.",[11,121,122,123,126,127,130,131,49],{},"Prerequisite: a separate Unix user for the agent (",[34,124,125],{},"agent_iurio"," or similar) and a one-time ",[34,128,129],{},"apes login"," as that user, so the daemon can read the DDISA identity from ",[34,132,133],{},"~/.config/apes/auth.json",[135,136,141],"pre",{"className":137,"code":139,"language":140},[138],"language-text","# I (human) start the daemon — secrets via stdin, never on disk\nsudo -u agent_iurio openape-proxy --global --port 18789 \u003C ~/.secrets-iurio.toml\n\n# Banner shows what was loaded\n[openape-proxy] identity: agent.iurio@example.com (https://id.openape.ai)\n[openape-proxy] secrets: gh_pat, openai, smtp\n[openape-proxy] export OPENAPE_PROXY=127.0.0.1:18789\n[openape-proxy] listening on 127.0.0.1:18789\n\n# Agent runs normally, through the wrapper\nexport OPENAPE_PROXY=127.0.0.1:18789\napes proxy -- gh repo list\napes proxy -- curl https://api.github.com/user\n# → {\"login\": \"patrick\", ...}\n","text",[34,142,139],{"__ignoreMap":143},"",[11,145,146,147,150,151,150,154,150,157,160],{},"The secrets file is TOML, four fields per entry — ",[34,148,149],{},"target",", ",[34,152,153],{},"header",[34,155,156],{},"template",[34,158,159],{},"value",". Example:",[135,162,166],{"className":163,"code":164,"language":165,"meta":143,"style":143},"language-toml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","version = \"1\"\n\n[secrets.gh_pat]\ntarget   = \"api.github.com/*\"\nheader   = \"Authorization\"\ntemplate = \"Bearer ${value}\"\nvalue    = \"ghp_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n","toml",[34,167,168,176,183,189,195,201,207],{"__ignoreMap":143},[169,170,173],"span",{"class":171,"line":172},"line",1,[169,174,175],{},"version = \"1\"\n",[169,177,179],{"class":171,"line":178},2,[169,180,182],{"emptyLinePlaceholder":181},true,"\n",[169,184,186],{"class":171,"line":185},3,[169,187,188],{},"[secrets.gh_pat]\n",[169,190,192],{"class":171,"line":191},4,[169,193,194],{},"target   = \"api.github.com/*\"\n",[169,196,198],{"class":171,"line":197},5,[169,199,200],{},"header   = \"Authorization\"\n",[169,202,204],{"class":171,"line":203},6,[169,205,206],{},"template = \"Bearer ${value}\"\n",[169,208,210],{"class":171,"line":209},7,[169,211,212],{},"value    = \"ghp_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n",[11,214,215],{},"The mechanics:",[217,218,219,250,259,268],"ol",{},[220,221,222,225,226,229,230,233,234,150,237,150,240,150,243,150,246,249],"li",{},[20,223,224],{},"Wrapper sets the environment:"," ",[34,227,228],{},"apes proxy --"," builds a trust bundle (system roots + local CA) per call in a temp file and exports it via ",[34,231,232],{},"HTTPS_PROXY"," and a few CA-trust variables — ",[34,235,236],{},"NODE_EXTRA_CA_CERTS",[34,238,239],{},"SSL_CERT_FILE",[34,241,242],{},"CURL_CA_BUNDLE",[34,244,245],{},"REQUESTS_CA_BUNDLE",[34,247,248],{},"GIT_SSL_CAINFO",". Subprocess-scoped, not system-wide. The local CA doesn't land in the system trust store, the macOS keychain stays untouched.",[220,251,252,255,256,258],{},[20,253,254],{},"Daemon terminates TLS:"," for ",[34,257,118],{}," it mints a leaf cert on the fly, signed with the local CA. The agent makes its TLS connection to the local CA, because its trust variables prescribe that.",[220,260,261,225,264,267],{},[20,262,263],{},"In the decrypted request the daemon injects the header:",[34,265,266],{},"Authorization: Bearer \u003Ctoken>"," from its memory.",[220,269,270,273],{},[20,271,272],{},"Daemon builds its own TLS connection to the real server:"," with the system trust store. Bidirectional, transparent to the agent.",[11,275,276,277,279,280,283],{},"The smoke against the real ",[34,278,118],{}," with a real OAuth token: ",[34,281,282],{},"curl"," returns the user login. The token appears neither in the environment of the agent process nor in the stdout of the daemon. What's in the audit log is the name of the secret, not the value.",[285,286,288],"h3",{"id":287},"at-rest-with-age","At-rest with age",[11,290,291,292,299,300,307],{},"The plaintext path is ",[25,293,294,295,298],{},"file with mode ",[34,296,297],{},"0600"," in my home"," — sufficient, because the agent user has no read permission. Whoever wants another layer encrypts the file with ",[301,302,306],"a",{"href":303,"rel":304},"https://age-encryption.org/",[305],"nofollow","age"," and pipes the decryption directly into the daemon — the plaintext never lands on disk:",[135,309,312],{"className":310,"code":311,"language":140},[138],"age --decrypt -i ~/.ssh/id_ed25519 ~/.secrets-iurio.age \\\n  | sudo -u agent_iurio openape-proxy --global --port 18789\n",[34,313,311],{"__ignoreMap":143},[105,315,317],{"id":316},"two-trust-boundaries","Two trust boundaries",[11,319,320],{},"Where does the token live, and who can read it? Two mechanisms that work independently of each other:",[11,322,323,326,327,329],{},[20,324,325],{},"Filesystem."," The secrets file has mode ",[34,328,297],{}," in my home, my user is owner. The agent runs as a separate Unix user whose home directory it can't read. Filesystem isolation is the old Unix answer, it works here too.",[11,331,332,335,336,339,340,343],{},[20,333,334],{},"Process."," The daemon and the agent run in separate processes, started as different Unix users. On macOS a normal user process can't read another user process's memory without the ",[34,337,338],{},"task_for_pid"," entitlement. On Linux ",[34,341,342],{},"ptrace_scope=1"," (the kernel default for years) blocks that. Memory isolation is hard, as long as I'm not root myself or running a specially privileged helper.",[11,345,346,347,350,351,354],{},"Plus a third thing that isn't a trust boundary for the secret, but is still important: ",[20,348,349],{},"the audit trail lives server-side at the IdP."," Local audit logs on the agent machine are not proof — ",[25,352,353],{},"anything written on the agent's host is also writable by the agent."," When someone later asks what happened, the answer is in the IdP, not in a file the agent itself could overwrite.",[105,356,358],{"id":357},"match-resolution","Match resolution",[11,360,361,362,365],{},"Per request the daemon takes at most ",[25,363,364],{},"one"," secret. The selection follows simple rules:",[367,368,369,391,397],"ul",{},[220,370,371,225,374,377,378,150,381,150,384,387,388,49],{},[20,372,373],{},"Glob syntax:",[34,375,376],{},"*"," is the only wildcard. ",[34,379,380],{},"?",[34,382,383],{},"[]",[34,385,386],{},"**"," are literal characters. Patterns match against ",[34,389,390],{},"host[:port]/path",[220,392,393,396],{},[20,394,395],{},"Tiebreaker:"," the longest literal prefix wins. With equal prefix, the order in the TOML file wins.",[220,398,399,402],{},[20,400,401],{},"At most one:"," even if several targets would match, only one is injected. No header stacking, no ambiguity.",[11,404,405],{},"Examples against the TOML table above:",[407,408,409,422],"table",{},[410,411,412],"thead",{},[413,414,415,419],"tr",{},[416,417,418],"th",{},"Request",[416,420,421],{},"Matched Secret",[423,424,425,438,450,462],"tbody",{},[413,426,427,433],{},[428,429,430],"td",{},[34,431,432],{},"GET https://api.github.com/user",[428,434,435],{},[34,436,437],{},"gh_pat",[413,439,440,445],{},[428,441,442],{},[34,443,444],{},"POST https://api.openai.com/v1/chat",[428,446,447],{},[34,448,449],{},"openai",[413,451,452,457],{},[428,453,454],{},[34,455,456],{},"CONNECT smtp.fastmail.com:587",[428,458,459],{},[34,460,461],{},"smtp",[413,463,464,469],{},[428,465,466],{},[34,467,468],{},"GET https://example.com/",[428,470,471],{},"(no match — passes through)",[11,473,474],{},"Requests that match nothing pass through unchanged — but they still run through the daemon's policy/audit pipeline like every other request. The secret lookup is an additional layer, not a replacement of the YOLO/Allow/Deny policy.",[105,476,478],{"id":477},"what-came-up-in-the-smoke","What came up in the smoke",[11,480,481,482,484],{},"In the first real smoke against ",[34,483,118],{}," a few bugs fell out:",[11,486,487,490,491,494,495,150,498,501,502,505,506,508],{},[20,488,489],{},"Go's strict x509 parser"," rejects node-forge-default certs, because node-forge takes ",[34,492,493],{},"PrintableString"," as the default for common-name encodings, where Go tools (",[34,496,497],{},"gh",[34,499,500],{},"git",", anything that uses Go net internally) expect ",[34,503,504],{},"UTF8String",". Fix: explicit ",[34,507,504],{}," on cert generation.",[11,510,511,518,519,522],{},[20,512,513,514,517],{},"Bun's ",[34,515,516],{},"node:tls"," compat"," hangs in the ",[34,520,521],{},"TLSSocket-on-existing-socket"," path — a call the daemon needs to begin TLS termination on an existing TCP connection. Fix: daemon refuses under Bun, runs on Node. Back to Bun as soon as upstream is fixed.",[11,524,525,535,536,539,540,543],{},[20,526,527,530,531,534],{},[34,528,529],{},"apes-login"," writes OAuth 2.0 ",[34,532,533],{},"access_token",","," not ",[34,537,538],{},"bearer"," — the token field name in ",[34,541,542],{},"auth.json"," was wrongly documented in our own code expectation. Fix: accept both field names, clear docs in the header comment.",[11,545,546],{},"None of these bugs is conceptual. All are friction points between formerly isolated components that are now bound to each other. Exactly what always shows up in the first real smoke of a new architecture.",[105,548,550],{"id":549},"what-this-isnt","What this isn't",[11,552,553],{},"Several clear limits I don't want to hide:",[11,555,556,559],{},[20,557,558],{},"TLS pinning breaks."," When a tool hard-pins its cert chain to the real CA — many mobile SDKs, some native binaries, some enterprise-grade APIs — the daemon can't inspect or modify the request anymore. The request falls through, the tool reports a cert error. That's a deliberate trade-off. Pinning tools have to get their tokens on a different path.",[11,561,562,225,565,150,567,150,570,150,573,576,577,580,581,583,584,587,588,590,591,594,595,598],{},[20,563,564],{},"Go clients on macOS.",[34,566,497],{},[34,568,569],{},"kubectl",[34,571,572],{},"terraform",[34,574,575],{},"helm"," and everything else Go-based reads on macOS exclusively the system keychain for its ",[34,578,579],{},"SystemCertPool"," — ",[34,582,239],{}," is ignored. The per-subprocess trust bundle is invisible to Go-on-macOS, the handshake fails with ",[25,585,586],{},"\"certificate is not trusted\"",". On Linux it works because Go honors ",[34,589,239],{}," there. Workaround on macOS: install the local CA into the keychain manually via ",[34,592,593],{},"security add-trusted-cert"," — that gives the CA system-wide trust and should only be done deliberately. A v2 variant with opt-in ",[34,596,597],{},"apes proxy ca install"," is in the pipeline.",[11,600,601,604,605,608,609,611,612,615,616,618],{},[20,602,603],{},"Wrapper-only HTTPS."," Native ",[34,606,607],{},"curl https://..."," without ",[34,610,228],{}," in front fails, because the trust bundle isn't set. That's not a bug — it's the whole idea that trust stays ",[25,613,614],{},"subprocess-scoped",". But the consequence is that tools not started via ",[34,617,228],{}," don't benefit.",[11,620,621,624],{},[20,622,623],{},"Restart to rotate."," No hot reload in v1. Whoever changes a token stops the daemon and restarts it with the new stdin payload. In-flight requests fall away with the TCP connection — the wrapper subprocess sees a connection error, the tool retries on its own. A v2 with control-socket reload is conceivable, but explicitly not planned for now.",[11,626,627,630],{},[20,628,629],{},"4 KiB stdin cap."," The TOML blob can't be larger. Whoever has more secrets runs several daemon instances on different ports. Has never bothered me, but could.",[11,632,633,636,637,640,641,644],{},[20,634,635],{},"No protection against root."," If someone has root on the machine, they can read the daemon memory. That's trivial, that's normal, that's not a security boundary I aim for. My threat model is ",[25,638,639],{},"agent compromised"," — not ",[25,642,643],{},"machine compromised",". Whoever has root has everything.",[11,646,647,650],{},[20,648,649],{},"No protection against a compromised daemon."," If the daemon process itself is hijacked via a code injection, everything memory is accessible. The daemon is small and lives in user code, not in agent code — the attack surface is much smaller, but not zero.",[11,652,653,654,49],{},"What remains: protection against prompt-injection attacks, protection against unintentional token leakage through agent behavior, protection against token-exfiltration-via-log-files. Those are the threat models that are actually reduced with this architecture — not eliminated, but reduced so they no longer depend on the trust assumption ",[25,655,656],{},"\"the agent is careful\"",[105,658,660],{"id":659},"where-this-sits-in-the-architecture","Where this sits in the architecture",[11,662,663],{},"This is the fourth axis of a security architecture I've been building for a while. Not by accident, but because the same logic applies everywhere.",[407,665,666,679],{},[410,667,668],{},[413,669,670,673,676],{},[416,671,672],{},"Axis",[416,674,675],{},"Tool",[416,677,678],{},"What the agent does NOT know",[423,680,681,692,703,714],{},[413,682,683,686,689],{},[428,684,685],{},"Process",[428,687,688],{},"Standing Grants",[428,690,691],{},"broadly what's allowed — it only knows the current approval",[413,693,694,697,700],{},[428,695,696],{},"Privilege",[428,698,699],{},"escapes",[428,701,702],{},"that the next command runs privileged, until the crossing is approved",[413,704,705,708,711],{},[428,706,707],{},"Network",[428,709,710],{},"openape-proxy (Method+Host)",[428,712,713],{},"that method+host are filtered",[413,715,716,721,726],{},[428,717,718],{},[20,719,720],{},"Auth",[428,722,723],{},[20,724,725],{},"openape-proxy + token injection",[428,727,728],{},[20,729,730],{},"which token it's authenticated with",[11,732,733,734,737],{},"Four axes, one pattern: ",[20,735,736],{},"infrastructure carries the knowledge, the agent operates blind."," Whoever doesn't have this has trust in the agent — and trust isn't what a security architecture should rest on. Trust is what's left over when the architecture can't cover anything anymore.",[105,739,741],{"id":740},"the-comparison-i-have-to-expect","The comparison I have to expect",[11,743,744,745,748,749,752],{},"Architecturally, TLS termination with a local CA is a solved problem. ",[34,746,747],{},"mitmproxy"," has done that for years, ",[34,750,751],{},"Charles Proxy"," does it, every penetration tester has their favorite setup. That's not new.",[11,754,755],{},"What's new here:",[367,757,758,764,770],{},[220,759,760,763],{},[20,761,762],{},"Subprocess-scoped trust wiring"," instead of a system-trust-store intervention. The daemon doesn't touch the system. When I stop the daemon, all configuration is gone. No \"oh right, I once installed mitmproxy\" residual junk in the macOS keychain.",[220,765,766,769],{},[20,767,768],{},"Integration with OpenApe identity."," The daemon authenticates at the IdP, every grant decision is auditable — server-side, not in a local log file the agent itself could overwrite. Audit lives where it can't be tampered with.",[220,771,772,775,776,778,779,782],{},[20,773,774],{},"Per-endpoint token selection,"," not one global bag-of-tokens. The daemon knows: for ",[34,777,118],{}," the GitHub token comes, for ",[34,780,781],{},"registry.npmjs.org"," the npm token. Patterns are in the secrets TOML, the agent doesn't know the patterns and doesn't know the secrets.",[11,784,785],{},"This isn't a new crypto pattern. It's the application of an established pattern to a problem that's situated differently in the agent world than in the pentester world.",[105,787,789],{"id":788},"the-only-question-that-remains","The only question that remains",[11,791,792,793],{},"It comes up sooner or later in the comments: ",[25,794,795],{},"\"What if the agent reads the token from the daemon memory?\"",[11,797,798,799,802],{},"Answer: it can't — on a non-root system. Process memory is OS-isolated, that's been so since the early 2000s. Yes, I know there are side-channel attacks. Yes, I know an agent in the same user identity as the daemon ",[25,800,801],{},"could"," read memory without further measures. That's exactly why the daemon runs as a different user. That separation isn't an implementation detail, it's the whole idea.",[105,804,806],{"id":805},"closing","Closing",[11,808,809],{},"You don't teach the agent to be careful with the token. You take the token out of the agent.",[811,812,813],"blockquote",{},[11,814,815],{},"What the agent doesn't know can't hurt me.",[11,817,818],{},"That's not denial. That's architecture.",[820,821],"hr",{},[11,823,824],{},[25,825,826,827,832,833,836,837,839,840,842,843,846,847,49],{},"Code: ",[301,828,831],{"href":829,"rel":830},"https://github.com/openape-ai/openape",[305],"github.com/openape-ai/openape",", MIT-licensed. ",[34,834,835],{},"openape-proxy"," is the daemon implementation, ",[34,838,228],{}," the subprocess wrapper. Both use ",[34,841,129],{}," for identity. The token-injection path is on the feature branch ",[34,844,845],{},"feat/phase-6-proxy-secrets"," — operator runbook in ",[301,848,851],{"href":849,"rel":850},"https://github.com/openape-ai/openape/blob/feat/phase-6-proxy-secrets/docs/proxy-secrets.md",[305],[34,852,853],{},"docs/proxy-secrets.md",[855,856,857],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":143,"searchDepth":178,"depth":178,"links":859},[860,863,864,865,866,867,868,869,870],{"id":107,"depth":178,"text":108,"children":861},[862],{"id":287,"depth":185,"text":288},{"id":316,"depth":178,"text":317},{"id":357,"depth":178,"text":358},{"id":477,"depth":178,"text":478},{"id":549,"depth":178,"text":550},{"id":659,"depth":178,"text":660},{"id":740,"depth":178,"text":741},{"id":788,"depth":178,"text":789},{"id":805,"depth":178,"text":806},"2026-04-30","Tokens as an environment variable work for humans — the user has a token that gives them their legitimate permissions. With agents that breaks: granularity is missing, the agent has no permission-sense, and it isn't the endpoint but a passthrough. A note from building a proxy that holds the tokens — and the agent doesn't.",false,"md",null,{},"/blog/en/what-the-agent-doesnt-know",{"title":5,"description":872},"blog/en/what-the-agent-doesnt-know",[881,882,883,884,885],"OpenApe","AI Agents","Infrastructure","Security","Building in Public","what-the-agent-doesnt-know","hD3eWKGUxCmndixf8etqyalLJ_fnJqxMGDJUx8v6R00",{"en":889,"de":890},"/en/blog/what-the-agent-doesnt-know","/de/blog/was-der-agent-nicht-weiss",1779001887365]