[{"data":1,"prerenderedAt":499},["ShallowReactive",2],{"navigation_docs":3,"-tinker":139,"-tinker-surround":494},[4,8,12,16,20,24,28,32,59,63,117,121,135],{"title":5,"path":6,"stem":7},"Introduction","\u002Fintroduction","1.introduction",{"title":9,"path":10,"stem":11},"Memory","\u002Fmemory","10.memory",{"title":13,"path":14,"stem":15},"Customization","\u002Fcustomization","11.customization",{"title":17,"path":18,"stem":19},"Deployment","\u002Fdeployment","12.deployment",{"title":21,"path":22,"stem":23},"Reference","\u002Freference","13.reference",{"title":25,"path":26,"stem":27},"Quickstart","\u002Fquickstart","2.quickstart",{"title":29,"path":30,"stem":31},"Installation","\u002Finstallation","3.installation",{"title":33,"icon":34,"path":35,"stem":36,"children":37,"page":58},"Connectors","i-lucide-cable","\u002Fconnectors","4.connectors",[38,42,46,50,54],{"title":39,"path":40,"stem":41},"Telegram","\u002Fconnectors\u002Ftelegram","4.connectors\u002F1.telegram",{"title":43,"path":44,"stem":45},"Slack","\u002Fconnectors\u002Fslack","4.connectors\u002F2.slack",{"title":47,"path":48,"stem":49},"Email","\u002Fconnectors\u002Femail","4.connectors\u002F3.email",{"title":51,"path":52,"stem":53},"API","\u002Fconnectors\u002Fapi","4.connectors\u002F4.api",{"title":55,"path":56,"stem":57},"Terminal","\u002Fconnectors\u002Fterminal","4.connectors\u002F5.terminal",false,{"title":60,"path":61,"stem":62},"Attachments","\u002Fattachments","5.attachments",{"title":64,"icon":65,"path":66,"stem":67,"children":68,"page":58},"Tools","i-lucide-wrench","\u002Ftools","6.tools",[69,73,77,81,85,89,93,97,101,105,109,113],{"title":70,"path":71,"stem":72},"File Manager","\u002Ftools\u002Ffile-manager","6.tools\u002F1.file-manager",{"title":74,"path":75,"stem":76},"Text-to-Speech","\u002Ftools\u002Ftext-to-speech","6.tools\u002F10.text-to-speech",{"title":78,"path":79,"stem":80},"Confirmations","\u002Ftools\u002Fconfirmations","6.tools\u002F11.confirmations",{"title":82,"path":83,"stem":84},"Adding Custom Tools","\u002Ftools\u002Fadding-custom-tools","6.tools\u002F12.adding-custom-tools",{"title":86,"path":87,"stem":88},"Image Manager","\u002Ftools\u002Fimage-manager","6.tools\u002F2.image-manager",{"title":90,"path":91,"stem":92},"Web Request","\u002Ftools\u002Fweb-request","6.tools\u002F3.web-request",{"title":94,"path":95,"stem":96},"Reminders","\u002Ftools\u002Freminders","6.tools\u002F4.reminders",{"title":98,"path":99,"stem":100},"Heartbeats","\u002Ftools\u002Fheartbeats","6.tools\u002F5.heartbeats",{"title":102,"path":103,"stem":104},"Email Manager","\u002Ftools\u002Femail-manager","6.tools\u002F6.email-manager",{"title":106,"path":107,"stem":108},"Calendar","\u002Ftools\u002Fcalendar","6.tools\u002F7.calendar",{"title":110,"path":111,"stem":112},"Read Database","\u002Ftools\u002Fread-database","6.tools\u002F8.read-database",{"title":114,"path":115,"stem":116},"Headless Browser","\u002Ftools\u002Fbrowser","6.tools\u002F9.browser",{"title":118,"path":119,"stem":120},"Tinker","\u002Ftinker","7.tinker",{"title":122,"icon":123,"path":124,"stem":125,"children":126,"page":58},"Skills","i-lucide-sparkles","\u002Fskills","8.skills",[127,131],{"title":128,"path":129,"stem":130},"Overview","\u002Fskills\u002Foverview","8.skills\u002F1.overview",{"title":132,"path":133,"stem":134},"Adding Custom Skills","\u002Fskills\u002Fadding-custom-skills","8.skills\u002F2.adding-custom-skills",{"title":136,"path":137,"stem":138},"Personas","\u002Fpersonas","9.personas",{"id":140,"title":118,"body":141,"description":487,"extension":488,"links":489,"meta":490,"navigation":491,"path":119,"seo":492,"stem":120,"__hash__":493},"docs\u002F7.tinker.md",{"type":142,"value":143,"toc":478},"minimark",[144,148,157,169,172,176,192,199,219,222,226,229,264,283,287,294,305,327,345,349,356,365,374,377,381,389,393,406,447,474],[145,146,5],"h2",{"id":147},"introduction",[149,150,151,152,156],"p",{},"Tinker is the agent's escape hatch. With it enabled, the agent can evaluate arbitrary PHP in the context of your booted Laravel app: query Eloquent models, hit the cache, inspect config, call any facade or service in the container. It can also run shell commands via ",[153,154,155],"code",{},"Process::run(...)",", so this one tool covers both \"ask the database\" and \"run an arbitrary script\".",[149,158,159,160,164,165,168],{},"Ask ",[161,162,163],"em",{},"\"how many orders did we ship last week?\""," and the agent writes the query, runs it, and answers. Ask ",[161,166,167],{},"\"what's on disk in storage\u002Fapp?\""," and it shells out from PHP and tells you.",[149,170,171],{},"It's disabled by default. There is no sandbox.",[145,173,175],{"id":174},"enabling-tinker","Enabling Tinker",[177,178,183],"pre",{"className":179,"code":180,"language":181,"meta":182,"style":182},"language-env shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","LARACLAW_TINKER_ENABLED=true\n","env","",[153,184,185],{"__ignoreMap":182},[186,187,190],"span",{"class":188,"line":189},"line",1,[186,191,180],{},[149,193,194,195,198],{},"You'll also need ",[153,196,197],{},"laravel\u002Ftinker"," installed:",[177,200,204],{"className":201,"code":202,"language":203,"meta":182,"style":182},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","composer require laravel\u002Ftinker\n","bash",[153,205,206],{"__ignoreMap":182},[186,207,208,212,216],{"class":188,"line":189},[186,209,211],{"class":210},"sBMFI","composer",[186,213,215],{"class":214},"sfazB"," require",[186,217,218],{"class":214}," laravel\u002Ftinker\n",[149,220,221],{},"When disabled, the tool is not registered with the agent at all.",[145,223,225],{"id":224},"running-code","Running Code",[149,227,228],{},"The tool accepts a single parameter:",[230,231,232,248],"table",{},[233,234,235],"thead",{},[236,237,238,242,245],"tr",{},[239,240,241],"th",{},"Parameter",[239,243,244],{},"Required",[239,246,247],{},"Description",[249,250,251],"tbody",{},[236,252,253,258,261],{},[254,255,256],"td",{},[153,257,153],{},[254,259,260],{},"Yes",[254,262,263],{},"PHP code to evaluate",[149,265,266,267,270,271,274,275,278,279,282],{},"The code is passed to ",[153,268,269],{},"php artisan tinker --execute"," in-process via ",[153,272,273],{},"Artisan::call",", so there is no separate PHP boot per call. The output is returned as JSON containing ",[153,276,277],{},"exit_code"," and ",[153,280,281],{},"output",".",[145,284,286],{"id":285},"working-with-your-models","Working With Your Models",[149,288,289,290,293],{},"The agent has access to everything in your ",[153,291,292],{},"app\u002FModels"," directory and uses it the way you would in a Tinker session:",[177,295,299],{"className":296,"code":297,"language":298,"meta":182,"style":182},"language-php shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","App\\Models\\Order::where('shipped_at', '>=', now()->subWeek())->count();\n","php",[153,300,301],{"__ignoreMap":182},[186,302,303],{"class":188,"line":189},[186,304,297],{},[177,306,308],{"className":296,"code":307,"language":298,"meta":182,"style":182},"App\\Models\\User::with('subscription')\n    ->where('subscription.cancelled_at', null)\n    ->count();\n",[153,309,310,315,321],{"__ignoreMap":182},[186,311,312],{"class":188,"line":189},[186,313,314],{},"App\\Models\\User::with('subscription')\n",[186,316,318],{"class":188,"line":317},2,[186,319,320],{},"    ->where('subscription.cancelled_at', null)\n",[186,322,324],{"class":188,"line":323},3,[186,325,326],{},"    ->count();\n",[149,328,329,330,333,334,337,338,341,342,282],{},"For the agent to use your models effectively, model and column names should be self-describing. A ",[153,331,332],{},"User"," model with ",[153,335,336],{},"last_login_at"," is easier for the agent to reason about than one with ",[153,339,340],{},"lla"," or ",[153,343,344],{},"t3",[145,346,348],{"id":347},"running-shell-commands","Running Shell Commands",[149,350,351,352,355],{},"Shell commands are available through Laravel's ",[153,353,354],{},"Process"," facade:",[177,357,359],{"className":296,"code":358,"language":298,"meta":182,"style":182},"Process::run('git log --oneline -n 10')->output();\n",[153,360,361],{"__ignoreMap":182},[186,362,363],{"class":188,"line":189},[186,364,358],{},[177,366,368],{"className":296,"code":367,"language":298,"meta":182,"style":182},"Process::run('ls -la storage\u002Fapp')->output();\n",[153,369,370],{"__ignoreMap":182},[186,371,372],{"class":188,"line":189},[186,373,367],{},[149,375,376],{},"The agent does not need a separate shell tool. Wrapping a shell call in PHP is one layer of escaping instead of two.",[145,378,380],{"id":379},"output-limits","Output Limits",[149,382,383,384,388],{},"Output is capped at ",[385,386,387],"strong",{},"100 KB",". Beyond that the response is truncated with a marker.",[145,390,392],{"id":391},"security-considerations","Security Considerations",[394,395,396],"blockquote",{},[149,397,398,401,402,405],{},[186,399,400],{},"!WARNING","\nTinker is full PHP execution inside your running application. The agent can read ",[385,403,404],{},"and write"," any model, run any shell command the PHP process can run, and reach anything the container exposes. There is no read-only mode.",[407,408,409,416,426,432,441],"ul",{},[410,411,412,415],"li",{},[385,413,414],{},"Don't enable this on a shared host"," or any machine where the PHP process has access to data the owner shouldn't see.",[410,417,418,421,422,425],{},[385,419,420],{},"Wrap write operations in custom tools"," that declare ",[153,423,424],{},"requiresApproval",". Tinker itself does not prompt before running code.",[410,427,428,431],{},[385,429,430],{},"Inbound messages can influence prompts."," Anyone who can message a trusted sender or DM the bot can in principle convince the agent to run code. Trust your trusted senders.",[410,433,434,440],{},[385,435,436,437],{},"Set ",[153,438,439],{},"LARACLAW_LOG_AGENT_REQUESTS=true"," to keep an audit trail of every prompt and response.",[410,442,443,446],{},[385,444,445],{},"Be deliberate about who can message the bot."," With Tinker enabled, every trusted sender effectively has database write and shell access.",[149,448,449,450,457,458,461,462,469,470,473],{},"For narrower access — for example, ",[161,451,452,453,456],{},"\"the agent may only run ",[153,454,455],{},"SELECT"," queries\""," — use the ",[459,460,110],"a",{"href":111}," tool instead, which enforces read-only at the database connection level. For ",[161,463,464,465,468],{},"\"the agent may only run queries against the ",[153,466,467],{},"orders"," table\"",", build a ",[459,471,472],{"href":83},"custom tool"," that exposes exactly that.",[475,476,477],"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);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}",{"title":182,"searchDepth":317,"depth":317,"links":479},[480,481,482,483,484,485,486],{"id":147,"depth":317,"text":5},{"id":174,"depth":317,"text":175},{"id":224,"depth":317,"text":225},{"id":285,"depth":317,"text":286},{"id":347,"depth":317,"text":348},{"id":379,"depth":317,"text":380},{"id":391,"depth":317,"text":392},"Let the agent evaluate PHP in the context of your running Laravel app.","md",null,{},true,{"title":118,"description":487},"iMVcPvurd2ksFTka1IuuFLCg6Eyu0TH-pIonBsgO7u0",[495,497],{"title":114,"path":115,"stem":116,"description":496,"children":-1},"Let the agent fetch and interact with JavaScript-rendered pages through Lightpanda.",{"title":128,"path":129,"stem":130,"description":498,"children":-1},"What skills are, how they're stored, and how the agent uses them.",1786661906119]