The 'thin tool layer' pattern is exactly what I've been converging on, but I'm curious: how do you handle tools that need to compose multiple services? For example, create_order might need to check inventory, apply a discount, and reserve stock. Do you keep that orchestration in the service, or do you expose multiple tools and let the agent chain them?
I keep that orchestration in the service, not in the agent. A create_order tool that checks inventory, applies the discount and reserves stock in one place gives the agent a single clear action and keeps the ordering and the failure handling in code I can test. Exposing each step as its own tool looks flexible but it hands the agent the job of getting the sequence right every time, and a missed step becomes a partial order. Where do you draw the line in your own tools, one tool per business action or one per service call?
One tool per business action, almost always. The agent should be thinking in terms of 'create an order' or 'issue a refund,' not 'check inventory, then apply discount, then reserve stock.' If the sequence is fixed and the failure modes are known, it belongs in the service. The agent shouldn't be a workflow engine.
That framing nails it, thinking in business actions rather than steps is exactly the line I use. The test I keep coming back to is whether the sequence can change at runtime: if it is fixed, it lives in the service, and the agent only sees the outcome it needs to act on. Have you found a case where a sequence looked fixed but still had to move into the agent?
Yes, one case: a 'create user' flow that looked fixed — validate email, create account, send welcome email. But it turned out that some enterprise customers needed a manual approval step before the account was created, and the approval could take days. That's not a fixed sequence anymore; it's a state machine with a human gate. We moved the orchestration into the service, but the agent needed a separate 'check approval status' tool to decide when to proceed.
That is a great example of the line moving in practice. Once approval can take days, the flow is no longer a sequence to run through, it is a state to watch, and keeping the orchestration in the service while giving the agent a status check tool keeps both sides honest. The detail I would add is to make that status tool return the reason a request is still waiting, not just a yes or no, so the agent can tell the user something useful instead of just polling again. Have you found a clean way to surface that waiting reason without leaking internal approval notes?
We're a place where coders share, stay up-to-date and grow their careers.
The 'thin tool layer' pattern is exactly what I've been converging on, but I'm curious: how do you handle tools that need to compose multiple services? For example, create_order might need to check inventory, apply a discount, and reserve stock. Do you keep that orchestration in the service, or do you expose multiple tools and let the agent chain them?
I keep that orchestration in the service, not in the agent. A create_order tool that checks inventory, applies the discount and reserves stock in one place gives the agent a single clear action and keeps the ordering and the failure handling in code I can test. Exposing each step as its own tool looks flexible but it hands the agent the job of getting the sequence right every time, and a missed step becomes a partial order. Where do you draw the line in your own tools, one tool per business action or one per service call?
One tool per business action, almost always. The agent should be thinking in terms of 'create an order' or 'issue a refund,' not 'check inventory, then apply discount, then reserve stock.' If the sequence is fixed and the failure modes are known, it belongs in the service. The agent shouldn't be a workflow engine.
That framing nails it, thinking in business actions rather than steps is exactly the line I use. The test I keep coming back to is whether the sequence can change at runtime: if it is fixed, it lives in the service, and the agent only sees the outcome it needs to act on. Have you found a case where a sequence looked fixed but still had to move into the agent?
Yes, one case: a 'create user' flow that looked fixed — validate email, create account, send welcome email. But it turned out that some enterprise customers needed a manual approval step before the account was created, and the approval could take days. That's not a fixed sequence anymore; it's a state machine with a human gate. We moved the orchestration into the service, but the agent needed a separate 'check approval status' tool to decide when to proceed.
That is a great example of the line moving in practice. Once approval can take days, the flow is no longer a sequence to run through, it is a state to watch, and keeping the orchestration in the service while giving the agent a status check tool keeps both sides honest. The detail I would add is to make that status tool return the reason a request is still waiting, not just a yes or no, so the agent can tell the user something useful instead of just polling again. Have you found a clean way to surface that waiting reason without leaking internal approval notes?